blob: 9b8d07e2428bd4ff52b715640fa8ecdd4e6c741e [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);
Caroline Tice1f954f52011-04-11 15:51:10 +0000689
Johnny Chen01d61572011-02-25 00:23:25 +0000690 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000691 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000692 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000693 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:
Caroline Tice89c6d582011-03-29 19:53:44 +0000780 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
781 Rd = Bits32 (opcode, 15, 12);
782 setflags = BitIsSet (opcode, 20);
783 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000784
785 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
786 if ((Rd == 15) && setflags)
787 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000788
789 break;
790
791 case eEncodingA2:
792 {
793 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
794 Rd = Bits32 (opcode, 15, 12);
795 setflags = false;
796 uint32_t imm4 = Bits32 (opcode, 19, 16);
797 uint32_t imm12 = Bits32 (opcode, 11, 0);
798 imm32 = (imm4 << 12) | imm12;
799
800 // if d == 15 then UNPREDICTABLE;
801 if (Rd == 15)
802 return false;
803 }
804 break;
805
806 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000807 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000808 }
809 uint32_t result = imm32;
810
811 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000812 EmulateInstruction::Context context;
813 context.type = EmulateInstruction::eContextImmediate;
814 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000815
Johnny Chen10530c22011-02-17 22:37:12 +0000816 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000817 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000818 }
819 return true;
820}
821
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000822// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
823// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
824// unsigned values.
825//
826// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
827// limited to only a few forms of the instruction.
828bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000829EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000830{
831#if 0
832 if ConditionPassed() then
833 EncodingSpecificOperations();
834 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
835 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
836 result = operand1 * operand2;
837 R[d] = result<31:0>;
838 if setflags then
839 APSR.N = result<31>;
840 APSR.Z = IsZeroBit(result);
841 if ArchVersion() == 4 then
842 APSR.C = bit UNKNOWN;
843 // else APSR.C unchanged
844 // APSR.V always unchanged
845#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000846
Greg Clayton7bc39082011-03-24 23:53:38 +0000847 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000848 {
849 uint32_t d;
850 uint32_t n;
851 uint32_t m;
852 bool setflags;
853
854 // EncodingSpecificOperations();
855 switch (encoding)
856 {
857 case eEncodingT1:
858 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
859 d = Bits32 (opcode, 2, 0);
860 n = Bits32 (opcode, 5, 3);
861 m = Bits32 (opcode, 2, 0);
862 setflags = !InITBlock();
863
864 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
865 if ((ArchVersion() < ARMv6) && (d == n))
866 return false;
867
868 break;
869
870 case eEncodingT2:
871 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
872 d = Bits32 (opcode, 11, 8);
873 n = Bits32 (opcode, 19, 16);
874 m = Bits32 (opcode, 3, 0);
875 setflags = false;
876
877 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
878 if (BadReg (d) || BadReg (n) || BadReg (m))
879 return false;
880
881 break;
882
883 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000884 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000885 d = Bits32 (opcode, 19, 16);
886 n = Bits32 (opcode, 3, 0);
887 m = Bits32 (opcode, 11, 8);
888 setflags = BitIsSet (opcode, 20);
889
890 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
891 if ((d == 15) || (n == 15) || (m == 15))
892 return false;
893
894 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
895 if ((ArchVersion() < ARMv6) && (d == n))
896 return false;
897
898 break;
899
900 default:
901 return false;
902 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000903
904 bool success = false;
905
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000906 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
907 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
908 if (!success)
909 return false;
910
911 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
912 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
913 if (!success)
914 return false;
915
916 // result = operand1 * operand2;
917 uint64_t result = operand1 * operand2;
918
919 // R[d] = result<31:0>;
920 Register op1_reg;
921 Register op2_reg;
922 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
923 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
924
925 EmulateInstruction::Context context;
926 context.type = eContextMultiplication;
927 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
928
929 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
930 return false;
931
932 // if setflags then
933 if (setflags)
934 {
935 // APSR.N = result<31>;
936 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000937 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000938 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
939 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000940 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000941 {
942 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
943 return false;
944 }
945
946 // if ArchVersion() == 4 then
947 // APSR.C = bit UNKNOWN;
948 }
949 }
950 return true;
951}
952
Johnny Chend642a6a2011-02-22 01:01:03 +0000953// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
954// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000955bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000956EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000957{
958#if 0
959 // ARM pseudo code...
960 if (ConditionPassed())
961 {
962 EncodingSpecificOperations();
963 result = NOT(imm32);
964 if d == 15 then // Can only occur for ARM encoding
965 ALUWritePC(result); // setflags is always FALSE here
966 else
967 R[d] = result;
968 if setflags then
969 APSR.N = result<31>;
970 APSR.Z = IsZeroBit(result);
971 APSR.C = carry;
972 // APSR.V unchanged
973 }
974#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000975
Greg Clayton7bc39082011-03-24 23:53:38 +0000976 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000977 {
978 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000979 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
980 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000981 bool setflags;
982 switch (encoding) {
983 case eEncodingT1:
984 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000985 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000986 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000987 break;
988 case eEncodingA1:
989 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000990 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000991 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000992
Johnny Chend642a6a2011-02-22 01:01:03 +0000993 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +0000994 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000995 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000996 break;
997 default:
998 return false;
999 }
1000 uint32_t result = ~imm32;
1001
1002 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001003 EmulateInstruction::Context context;
1004 context.type = EmulateInstruction::eContextImmediate;
1005 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001006
Johnny Chen10530c22011-02-17 22:37:12 +00001007 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001008 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001009 }
1010 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001011}
1012
Johnny Chend642a6a2011-02-22 01:01:03 +00001013// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1014// It can optionally update the condition flags based on the result.
1015bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001016EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001017{
1018#if 0
1019 // ARM pseudo code...
1020 if (ConditionPassed())
1021 {
1022 EncodingSpecificOperations();
1023 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1024 result = NOT(shifted);
1025 if d == 15 then // Can only occur for ARM encoding
1026 ALUWritePC(result); // setflags is always FALSE here
1027 else
1028 R[d] = result;
1029 if setflags then
1030 APSR.N = result<31>;
1031 APSR.Z = IsZeroBit(result);
1032 APSR.C = carry;
1033 // APSR.V unchanged
1034 }
1035#endif
1036
Greg Clayton7bc39082011-03-24 23:53:38 +00001037 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001038 {
1039 uint32_t Rm; // the source register
1040 uint32_t Rd; // the destination register
1041 ARM_ShifterType shift_t;
1042 uint32_t shift_n; // the shift applied to the value read from Rm
1043 bool setflags;
1044 uint32_t carry; // the carry bit after the shift operation
1045 switch (encoding) {
1046 case eEncodingT1:
1047 Rd = Bits32(opcode, 2, 0);
1048 Rm = Bits32(opcode, 5, 3);
1049 setflags = !InITBlock();
1050 shift_t = SRType_LSL;
1051 shift_n = 0;
1052 if (InITBlock())
1053 return false;
1054 break;
1055 case eEncodingT2:
1056 Rd = Bits32(opcode, 11, 8);
1057 Rm = Bits32(opcode, 3, 0);
1058 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001059 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001060 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001061 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001062 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001063 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001064 case eEncodingA1:
1065 Rd = Bits32(opcode, 15, 12);
1066 Rm = Bits32(opcode, 3, 0);
1067 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001068 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001069 break;
1070 default:
1071 return false;
1072 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001073 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001074 uint32_t value = ReadCoreReg(Rm, &success);
1075 if (!success)
1076 return false;
1077
1078 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1079 uint32_t result = ~shifted;
1080
1081 // The context specifies that an immediate is to be moved into Rd.
1082 EmulateInstruction::Context context;
1083 context.type = EmulateInstruction::eContextImmediate;
1084 context.SetNoArgs ();
1085
1086 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1087 return false;
1088 }
1089 return true;
1090}
1091
Johnny Chen788e0552011-01-27 22:52:23 +00001092// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1093// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001094bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001095EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001096{
1097#if 0
1098 // ARM pseudo code...
1099 if (ConditionPassed())
1100 {
1101 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1102 base = Align(PC,4);
1103 address = if add then (base + imm32) else (base - imm32);
1104 data = MemU[address,4];
1105 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001106 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1107 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001108 R[t] = data;
1109 else // Can only apply before ARMv7
1110 if CurrentInstrSet() == InstrSet_ARM then
1111 R[t] = ROR(data, 8*UInt(address<1:0>));
1112 else
1113 R[t] = bits(32) UNKNOWN;
1114 }
1115#endif
1116
Greg Clayton7bc39082011-03-24 23:53:38 +00001117 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001118 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001119 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001120 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001121 if (!success)
1122 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001123
1124 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001125 EmulateInstruction::Context context;
1126 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1127 Register pc_reg;
1128 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1129 context.SetRegisterPlusOffset (pc_reg, 0);
1130
Johnny Chenc9de9102011-02-11 19:12:30 +00001131 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001132 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001133 bool add; // +imm32 or -imm32?
1134 addr_t base; // the base address
1135 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001136 uint32_t data; // the literal data value from the PC relative load
1137 switch (encoding) {
1138 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001139 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001140 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001141 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001142 break;
1143 case eEncodingT2:
1144 Rt = Bits32(opcode, 15, 12);
1145 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1146 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001147 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001148 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001149 break;
1150 default:
1151 return false;
1152 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001153
Johnny Chene39f22d2011-02-19 01:36:13 +00001154 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001155 if (add)
1156 address = base + imm32;
1157 else
1158 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001159
1160 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001161 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001162 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001163 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001164
1165 if (Rt == 15)
1166 {
1167 if (Bits32(address, 1, 0) == 0)
1168 {
1169 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001170 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001171 return false;
1172 }
1173 else
1174 return false;
1175 }
1176 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1177 {
1178 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1179 return false;
1180 }
1181 else // We don't handle ARM for now.
1182 return false;
1183
Johnny Chen788e0552011-01-27 22:52:23 +00001184 }
1185 return true;
1186}
1187
Johnny Chen5b442b72011-01-27 19:34:30 +00001188// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001189// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001190bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001191EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001192{
1193#if 0
1194 // ARM pseudo code...
1195 if (ConditionPassed())
1196 {
1197 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001198 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001199 if d == 15 then // Can only occur for ARM encoding
1200 ALUWritePC(result); // setflags is always FALSE here
1201 else
1202 R[d] = result;
1203 if setflags then
1204 APSR.N = result<31>;
1205 APSR.Z = IsZeroBit(result);
1206 APSR.C = carry;
1207 APSR.V = overflow;
1208 }
1209#endif
1210
1211 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001212
Greg Clayton7bc39082011-03-24 23:53:38 +00001213 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001214 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001215 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001216 if (!success)
1217 return false;
1218 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001219 uint32_t d;
1220 bool setflags;
1221 switch (encoding)
1222 {
1223 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001224 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001225 d = Bits32 (opcode, 10, 8);
1226 setflags = false;
1227 imm32 = (Bits32 (opcode, 7, 0) << 2);
1228
1229 break;
1230
1231 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001232 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001233 d = 13;
1234 setflags = false;
1235 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1236
1237 break;
1238
1239 default:
1240 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001241 }
1242 addr_t sp_offset = imm32;
1243 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1244
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001245 EmulateInstruction::Context context;
1246 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice080bf612011-04-05 18:46:00 +00001247 Register sp_reg;
1248 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1249 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001250
Caroline Ticee2212882011-03-22 22:38:28 +00001251 if (d == 15)
1252 {
1253 if (!ALUWritePC (context, addr))
1254 return false;
1255 }
1256 else
1257 {
1258 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1259 return false;
1260 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001261 }
1262 return true;
1263}
1264
1265// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001266// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001267bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001268EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001269{
1270#if 0
1271 // ARM pseudo code...
1272 if (ConditionPassed())
1273 {
1274 EncodingSpecificOperations();
1275 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001276 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001277 if d == 15 then
1278 ALUWritePC(result); // setflags is always FALSE here
1279 else
1280 R[d] = result;
1281 if setflags then
1282 APSR.N = result<31>;
1283 APSR.Z = IsZeroBit(result);
1284 APSR.C = carry;
1285 APSR.V = overflow;
1286 }
1287#endif
1288
1289 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001290
Greg Clayton7bc39082011-03-24 23:53:38 +00001291 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001292 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001293 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001294 if (!success)
1295 return false;
1296 uint32_t Rm; // the second operand
1297 switch (encoding) {
1298 case eEncodingT2:
1299 Rm = Bits32(opcode, 6, 3);
1300 break;
1301 default:
1302 return false;
1303 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001304 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001305 if (!success)
1306 return false;
1307
1308 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1309
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001310 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +00001311 context.type = EmulateInstruction::eContextAddition;
1312 Register sp_reg;
1313 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1314 Register other_reg;
1315 other_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1316 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001317
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001318 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001319 return false;
1320 }
1321 return true;
1322}
1323
Johnny Chen9b8d7832011-02-02 01:13:56 +00001324// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1325// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1326// from Thumb to ARM.
1327// BLX (immediate)
1328bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001329EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001330{
1331#if 0
1332 // ARM pseudo code...
1333 if (ConditionPassed())
1334 {
1335 EncodingSpecificOperations();
1336 if CurrentInstrSet() == InstrSet_ARM then
1337 LR = PC - 4;
1338 else
1339 LR = PC<31:1> : '1';
1340 if targetInstrSet == InstrSet_ARM then
1341 targetAddress = Align(PC,4) + imm32;
1342 else
1343 targetAddress = PC + imm32;
1344 SelectInstrSet(targetInstrSet);
1345 BranchWritePC(targetAddress);
1346 }
1347#endif
1348
Greg Clayton7bc39082011-03-24 23:53:38 +00001349 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001350
Greg Clayton7bc39082011-03-24 23:53:38 +00001351 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001352 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001353 EmulateInstruction::Context context;
1354 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001355 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001356 if (!success)
1357 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001358 addr_t lr; // next instruction address
1359 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001360 int32_t imm32; // PC-relative offset
1361 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001362 case eEncodingT1:
1363 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001364 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001365 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001366 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001367 uint32_t J1 = Bit32(opcode, 13);
1368 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001369 uint32_t imm11 = Bits32(opcode, 10, 0);
1370 uint32_t I1 = !(J1 ^ S);
1371 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001372 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001373 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001374 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001375 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001376 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001377 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001378 break;
1379 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001380 case eEncodingT2:
1381 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001382 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001383 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001384 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001385 uint32_t J1 = Bit32(opcode, 13);
1386 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001387 uint32_t imm10L = Bits32(opcode, 10, 1);
1388 uint32_t I1 = !(J1 ^ S);
1389 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001390 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001391 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001392 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001393 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001394 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001395 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001396 break;
1397 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001398 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001399 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001400 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001401 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001402 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001403 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001404 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001405 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001406 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001407 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001408 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001409 break;
1410 default:
1411 return false;
1412 }
1413 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1414 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001415 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001416 return false;
1417 }
1418 return true;
1419}
1420
1421// Branch with Link and Exchange (register) calls a subroutine at an address and
1422// instruction set specified by a register.
1423// BLX (register)
1424bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001425EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001426{
1427#if 0
1428 // ARM pseudo code...
1429 if (ConditionPassed())
1430 {
1431 EncodingSpecificOperations();
1432 target = R[m];
1433 if CurrentInstrSet() == InstrSet_ARM then
1434 next_instr_addr = PC - 4;
1435 LR = next_instr_addr;
1436 else
1437 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001438 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001439 BXWritePC(target);
1440 }
1441#endif
1442
1443 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001444
Greg Clayton7bc39082011-03-24 23:53:38 +00001445 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001446 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001447 EmulateInstruction::Context context;
1448 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001449 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001450 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001451 if (!success)
1452 return false;
1453 uint32_t Rm; // the register with the target address
1454 switch (encoding) {
1455 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001456 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001457 Rm = Bits32(opcode, 6, 3);
1458 // if m == 15 then UNPREDICTABLE;
1459 if (Rm == 15)
1460 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001461 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001462 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001463 break;
1464 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001465 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001466 Rm = Bits32(opcode, 3, 0);
1467 // if m == 15 then UNPREDICTABLE;
1468 if (Rm == 15)
1469 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001470 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001471 default:
1472 return false;
1473 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001474 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001475 if (!success)
1476 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001477 Register dwarf_reg;
1478 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1479 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001480 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1481 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001482 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001483 return false;
1484 }
1485 return true;
1486}
1487
Johnny Chenab3b3512011-02-12 00:10:51 +00001488// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001489bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001490EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001491{
1492#if 0
1493 // ARM pseudo code...
1494 if (ConditionPassed())
1495 {
1496 EncodingSpecificOperations();
1497 BXWritePC(R[m]);
1498 }
1499#endif
1500
Greg Clayton7bc39082011-03-24 23:53:38 +00001501 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001502 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001503 EmulateInstruction::Context context;
1504 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001505 uint32_t Rm; // the register with the target address
1506 switch (encoding) {
1507 case eEncodingT1:
1508 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001509 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001510 return false;
1511 break;
1512 case eEncodingA1:
1513 Rm = Bits32(opcode, 3, 0);
1514 break;
1515 default:
1516 return false;
1517 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001518 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001519 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001520 if (!success)
1521 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001522
1523 Register dwarf_reg;
1524 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001525 context.SetRegister (dwarf_reg);
1526 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001527 return false;
1528 }
1529 return true;
1530}
1531
Johnny Chen59e6ab72011-02-24 21:01:20 +00001532// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1533// address and instruction set specified by a register as though it were a BX instruction.
1534//
1535// TODO: Emulate Jazelle architecture?
1536// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1537bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001538EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001539{
1540#if 0
1541 // ARM pseudo code...
1542 if (ConditionPassed())
1543 {
1544 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001545 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001546 BXWritePC(R[m]);
1547 else
1548 if JazelleAcceptsExecution() then
1549 SwitchToJazelleExecution();
1550 else
1551 SUBARCHITECTURE_DEFINED handler call;
1552 }
1553#endif
1554
Greg Clayton7bc39082011-03-24 23:53:38 +00001555 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001556 {
1557 EmulateInstruction::Context context;
1558 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1559 uint32_t Rm; // the register with the target address
1560 switch (encoding) {
1561 case eEncodingT1:
1562 Rm = Bits32(opcode, 19, 16);
1563 if (BadReg(Rm))
1564 return false;
1565 if (InITBlock() && !LastInITBlock())
1566 return false;
1567 break;
1568 case eEncodingA1:
1569 Rm = Bits32(opcode, 3, 0);
1570 if (Rm == 15)
1571 return false;
1572 break;
1573 default:
1574 return false;
1575 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001576 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001577 addr_t target = ReadCoreReg (Rm, &success);
1578 if (!success)
1579 return false;
1580
1581 Register dwarf_reg;
1582 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1583 context.SetRegister (dwarf_reg);
1584 if (!BXWritePC(context, target))
1585 return false;
1586 }
1587 return true;
1588}
1589
Johnny Chen0d0148e2011-01-28 02:26:08 +00001590// Set r7 to point to some ip offset.
1591// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001592bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001593EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001594{
1595#if 0
1596 // ARM pseudo code...
1597 if (ConditionPassed())
1598 {
1599 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001600 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001601 if d == 15 then // Can only occur for ARM encoding
1602 ALUWritePC(result); // setflags is always FALSE here
1603 else
1604 R[d] = result;
1605 if setflags then
1606 APSR.N = result<31>;
1607 APSR.Z = IsZeroBit(result);
1608 APSR.C = carry;
1609 APSR.V = overflow;
1610 }
1611#endif
1612
Greg Clayton7bc39082011-03-24 23:53:38 +00001613 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001614 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001615 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001616 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001617 if (!success)
1618 return false;
1619 uint32_t imm32;
1620 switch (encoding) {
1621 case eEncodingA1:
1622 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1623 break;
1624 default:
1625 return false;
1626 }
1627 addr_t ip_offset = imm32;
1628 addr_t addr = ip - ip_offset; // the adjusted ip value
1629
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001630 EmulateInstruction::Context context;
1631 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1632 Register dwarf_reg;
1633 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1634 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001635
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001636 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001637 return false;
1638 }
1639 return true;
1640}
1641
1642// Set ip to point to some stack offset.
1643// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001644bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001645EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001646{
1647#if 0
1648 // ARM pseudo code...
1649 if (ConditionPassed())
1650 {
1651 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001652 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001653 if d == 15 then // Can only occur for ARM encoding
1654 ALUWritePC(result); // setflags is always FALSE here
1655 else
1656 R[d] = result;
1657 if setflags then
1658 APSR.N = result<31>;
1659 APSR.Z = IsZeroBit(result);
1660 APSR.C = carry;
1661 APSR.V = overflow;
1662 }
1663#endif
1664
Greg Clayton7bc39082011-03-24 23:53:38 +00001665 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001666 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001667 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001668 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001669 if (!success)
1670 return false;
1671 uint32_t imm32;
1672 switch (encoding) {
1673 case eEncodingA1:
1674 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1675 break;
1676 default:
1677 return false;
1678 }
1679 addr_t sp_offset = imm32;
1680 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1681
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001682 EmulateInstruction::Context context;
1683 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1684 Register dwarf_reg;
1685 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1686 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001687
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001688 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001689 return false;
1690 }
1691 return true;
1692}
1693
Johnny Chenc9e747f2011-02-23 01:55:07 +00001694// This instruction subtracts an immediate value from the SP value, and writes
1695// the result to the destination register.
1696//
1697// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001698bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001699EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001700{
1701#if 0
1702 // ARM pseudo code...
1703 if (ConditionPassed())
1704 {
1705 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001706 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001707 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001708 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001709 else
1710 R[d] = result;
1711 if setflags then
1712 APSR.N = result<31>;
1713 APSR.Z = IsZeroBit(result);
1714 APSR.C = carry;
1715 APSR.V = overflow;
1716 }
1717#endif
1718
1719 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001720 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001721 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001722 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001723 if (!success)
1724 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001725
1726 uint32_t Rd;
1727 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001728 uint32_t imm32;
1729 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001730 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001731 Rd = 13;
1732 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001733 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001734 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001735 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001736 Rd = Bits32(opcode, 11, 8);
1737 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001738 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001739 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001740 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001741 if (Rd == 15 && !setflags)
1742 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001743 break;
1744 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001745 Rd = Bits32(opcode, 11, 8);
1746 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001747 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001748 if (Rd == 15)
1749 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001750 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001751 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001752 Rd = Bits32(opcode, 15, 12);
1753 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001754 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001755
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001756 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001757 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001758 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001759 break;
1760 default:
1761 return false;
1762 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001763 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1764
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001765 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001766 if (Rd == 13)
1767 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001768 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1769 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001770 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001771 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001772 }
1773 else
1774 {
1775 context.type = EmulateInstruction::eContextImmediate;
1776 context.SetNoArgs ();
1777 }
1778
1779 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001780 return false;
1781 }
1782 return true;
1783}
1784
Johnny Chen08c25e82011-01-31 18:02:28 +00001785// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001786bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001787EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001788{
1789#if 0
1790 // ARM pseudo code...
1791 if (ConditionPassed())
1792 {
1793 EncodingSpecificOperations();
1794 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1795 address = if index then offset_addr else R[n];
1796 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1797 if wback then R[n] = offset_addr;
1798 }
1799#endif
1800
1801 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001802
Greg Clayton7bc39082011-03-24 23:53:38 +00001803 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001804 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001805 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001806 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001807 if (!success)
1808 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001809 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001810 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001811 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1812
1813 bool index;
1814 bool add;
1815 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001816 switch (encoding) {
1817 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001818 Rt = Bits32(opcode, 15, 12);
1819 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001820 Rn = Bits32 (opcode, 19, 16);
1821
1822 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1823 return false;
1824
1825 index = BitIsSet (opcode, 24);
1826 add = BitIsSet (opcode, 23);
1827 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1828
1829 if (wback && ((Rn == 15) || (Rn == Rt)))
1830 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001831 break;
1832 default:
1833 return false;
1834 }
Caroline Tice3e407972011-03-18 19:41:00 +00001835 addr_t offset_addr;
1836 if (add)
1837 offset_addr = sp + imm12;
1838 else
1839 offset_addr = sp - imm12;
1840
1841 addr_t addr;
1842 if (index)
1843 addr = offset_addr;
1844 else
1845 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001846
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001847 EmulateInstruction::Context context;
1848 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001849 Register sp_reg;
1850 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1851 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001852 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001853 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001854 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001855 if (!success)
1856 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001857 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001858 return false;
1859 }
1860 else
1861 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001862 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001863 if (!success)
1864 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001865 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001866 return false;
1867 }
1868
Caroline Tice3e407972011-03-18 19:41:00 +00001869
1870 if (wback)
1871 {
1872 context.type = EmulateInstruction::eContextAdjustStackPointer;
1873 context.SetImmediateSigned (addr - sp);
1874 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1875 return false;
1876 }
Johnny Chence1ca772011-01-25 01:13:00 +00001877 }
1878 return true;
1879}
1880
Johnny Chen08c25e82011-01-31 18:02:28 +00001881// Vector Push stores multiple extension registers to the stack.
1882// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001883bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001884EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001885{
1886#if 0
1887 // ARM pseudo code...
1888 if (ConditionPassed())
1889 {
1890 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1891 address = SP - imm32;
1892 SP = SP - imm32;
1893 if single_regs then
1894 for r = 0 to regs-1
1895 MemA[address,4] = S[d+r]; address = address+4;
1896 else
1897 for r = 0 to regs-1
1898 // Store as two word-aligned words in the correct order for current endianness.
1899 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1900 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1901 address = address+8;
1902 }
1903#endif
1904
1905 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001906
Greg Clayton7bc39082011-03-24 23:53:38 +00001907 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001908 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001909 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001910 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001911 if (!success)
1912 return false;
1913 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001914 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001915 uint32_t imm32; // stack offset
1916 uint32_t regs; // number of registers
1917 switch (encoding) {
1918 case eEncodingT1:
1919 case eEncodingA1:
1920 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001921 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001922 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1923 // If UInt(imm8) is odd, see "FSTMX".
1924 regs = Bits32(opcode, 7, 0) / 2;
1925 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1926 if (regs == 0 || regs > 16 || (d + regs) > 32)
1927 return false;
1928 break;
1929 case eEncodingT2:
1930 case eEncodingA2:
1931 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001932 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001933 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1934 regs = Bits32(opcode, 7, 0);
1935 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1936 if (regs == 0 || regs > 16 || (d + regs) > 32)
1937 return false;
1938 break;
1939 default:
1940 return false;
1941 }
1942 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1943 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1944 addr_t sp_offset = imm32;
1945 addr_t addr = sp - sp_offset;
1946 uint32_t i;
1947
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001948 EmulateInstruction::Context context;
1949 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1950 Register dwarf_reg;
1951 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001952 Register sp_reg;
1953 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1954 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001955 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001956 dwarf_reg.num = start_reg + d + i;
1957 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001958 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001959 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001960 if (!success)
1961 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001962 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001963 return false;
1964 addr += reg_byte_size;
1965 }
1966
1967 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001968 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001969
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001970 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001971 return false;
1972 }
1973 return true;
1974}
1975
Johnny Chen587a0a42011-02-01 18:35:28 +00001976// Vector Pop loads multiple extension registers from the stack.
1977// It also updates SP to point just above the loaded data.
1978bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001979EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00001980{
1981#if 0
1982 // ARM pseudo code...
1983 if (ConditionPassed())
1984 {
1985 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1986 address = SP;
1987 SP = SP + imm32;
1988 if single_regs then
1989 for r = 0 to regs-1
1990 S[d+r] = MemA[address,4]; address = address+4;
1991 else
1992 for r = 0 to regs-1
1993 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1994 // Combine the word-aligned words in the correct order for current endianness.
1995 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1996 }
1997#endif
1998
1999 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002000
Greg Clayton7bc39082011-03-24 23:53:38 +00002001 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002002 {
2003 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002004 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002005 if (!success)
2006 return false;
2007 bool single_regs;
2008 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2009 uint32_t imm32; // stack offset
2010 uint32_t regs; // number of registers
2011 switch (encoding) {
2012 case eEncodingT1:
2013 case eEncodingA1:
2014 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002015 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002016 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2017 // If UInt(imm8) is odd, see "FLDMX".
2018 regs = Bits32(opcode, 7, 0) / 2;
2019 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2020 if (regs == 0 || regs > 16 || (d + regs) > 32)
2021 return false;
2022 break;
2023 case eEncodingT2:
2024 case eEncodingA2:
2025 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002026 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002027 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2028 regs = Bits32(opcode, 7, 0);
2029 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2030 if (regs == 0 || regs > 16 || (d + regs) > 32)
2031 return false;
2032 break;
2033 default:
2034 return false;
2035 }
2036 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2037 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2038 addr_t sp_offset = imm32;
2039 addr_t addr = sp;
2040 uint32_t i;
2041 uint64_t data; // uint64_t to accomodate 64-bit registers.
2042
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002043 EmulateInstruction::Context context;
2044 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2045 Register dwarf_reg;
2046 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002047 Register sp_reg;
2048 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
2049 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002050 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002051 dwarf_reg.num = start_reg + d + i;
2052 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002053 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002054 if (!success)
2055 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002056 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002057 return false;
2058 addr += reg_byte_size;
2059 }
2060
2061 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002062 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002063
2064 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2065 return false;
2066 }
2067 return true;
2068}
2069
Johnny Chenb77be412011-02-04 00:40:18 +00002070// SVC (previously SWI)
2071bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002072EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002073{
2074#if 0
2075 // ARM pseudo code...
2076 if (ConditionPassed())
2077 {
2078 EncodingSpecificOperations();
2079 CallSupervisor();
2080 }
2081#endif
2082
2083 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002084
Greg Clayton7bc39082011-03-24 23:53:38 +00002085 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002086 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002087 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002088 addr_t lr; // next instruction address
2089 if (!success)
2090 return false;
2091 uint32_t imm32; // the immediate constant
2092 uint32_t mode; // ARM or Thumb mode
2093 switch (encoding) {
2094 case eEncodingT1:
2095 lr = (pc + 2) | 1u; // return address
2096 imm32 = Bits32(opcode, 7, 0);
2097 mode = eModeThumb;
2098 break;
2099 case eEncodingA1:
2100 lr = pc + 4; // return address
2101 imm32 = Bits32(opcode, 23, 0);
2102 mode = eModeARM;
2103 break;
2104 default:
2105 return false;
2106 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002107
2108 EmulateInstruction::Context context;
2109 context.type = EmulateInstruction::eContextSupervisorCall;
2110 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002111 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2112 return false;
2113 }
2114 return true;
2115}
2116
Johnny Chenc315f862011-02-05 00:46:10 +00002117// If Then makes up to four following instructions (the IT block) conditional.
2118bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002119EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002120{
2121#if 0
2122 // ARM pseudo code...
2123 EncodingSpecificOperations();
2124 ITSTATE.IT<7:0> = firstcond:mask;
2125#endif
2126
Johnny Chenc315f862011-02-05 00:46:10 +00002127 m_it_session.InitIT(Bits32(opcode, 7, 0));
2128 return true;
2129}
2130
Johnny Chen3b620b32011-02-07 20:11:47 +00002131// Branch causes a branch to a target address.
2132bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002133EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002134{
2135#if 0
2136 // ARM pseudo code...
2137 if (ConditionPassed())
2138 {
2139 EncodingSpecificOperations();
2140 BranchWritePC(PC + imm32);
2141 }
2142#endif
2143
2144 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002145
Greg Clayton7bc39082011-03-24 23:53:38 +00002146 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002147 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002148 EmulateInstruction::Context context;
2149 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002150 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002151 if (!success)
2152 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002153 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002154 int32_t imm32; // PC-relative offset
2155 switch (encoding) {
2156 case eEncodingT1:
2157 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2158 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002159 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002160 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002161 break;
2162 case eEncodingT2:
2163 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002164 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002165 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002166 break;
2167 case eEncodingT3:
2168 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2169 {
Johnny Chenbd599902011-02-10 21:39:01 +00002170 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002171 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002172 uint32_t J1 = Bit32(opcode, 13);
2173 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002174 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002175 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002176 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002177 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002178 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002179 break;
2180 }
2181 case eEncodingT4:
2182 {
Johnny Chenbd599902011-02-10 21:39:01 +00002183 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002184 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002185 uint32_t J1 = Bit32(opcode, 13);
2186 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002187 uint32_t imm11 = Bits32(opcode, 10, 0);
2188 uint32_t I1 = !(J1 ^ S);
2189 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002190 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002191 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002192 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002193 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002194 break;
2195 }
2196 case eEncodingA1:
2197 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002198 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002199 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002200 break;
2201 default:
2202 return false;
2203 }
2204 if (!BranchWritePC(context, target))
2205 return false;
2206 }
2207 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002208}
2209
Johnny Chen53ebab72011-02-08 23:21:57 +00002210// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2211// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2212// CBNZ, CBZ
2213bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002214EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002215{
2216#if 0
2217 // ARM pseudo code...
2218 EncodingSpecificOperations();
2219 if nonzero ^ IsZero(R[n]) then
2220 BranchWritePC(PC + imm32);
2221#endif
2222
2223 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002224
2225 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002226 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002227 if (!success)
2228 return false;
2229
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002230 EmulateInstruction::Context context;
2231 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002232 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002233 if (!success)
2234 return false;
2235
2236 addr_t target; // target address
2237 uint32_t imm32; // PC-relative offset to branch forward
2238 bool nonzero;
2239 switch (encoding) {
2240 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002241 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002242 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002243 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002244 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002245 break;
2246 default:
2247 return false;
2248 }
2249 if (nonzero ^ (reg_val == 0))
2250 if (!BranchWritePC(context, target))
2251 return false;
2252
2253 return true;
2254}
2255
Johnny Chen60299ec2011-02-17 19:34:27 +00002256// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2257// A base register provides a pointer to the table, and a second register supplies an index into the table.
2258// The branch length is twice the value of the byte returned from the table.
2259//
2260// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2261// A base register provides a pointer to the table, and a second register supplies an index into the table.
2262// The branch length is twice the value of the halfword returned from the table.
2263// TBB, TBH
2264bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002265EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002266{
2267#if 0
2268 // ARM pseudo code...
2269 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2270 if is_tbh then
2271 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2272 else
2273 halfwords = UInt(MemU[R[n]+R[m], 1]);
2274 BranchWritePC(PC + 2*halfwords);
2275#endif
2276
2277 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002278
2279 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2280 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2281 bool is_tbh; // true if table branch halfword
2282 switch (encoding) {
2283 case eEncodingT1:
2284 Rn = Bits32(opcode, 19, 16);
2285 Rm = Bits32(opcode, 3, 0);
2286 is_tbh = BitIsSet(opcode, 4);
2287 if (Rn == 13 || BadReg(Rm))
2288 return false;
2289 if (InITBlock() && !LastInITBlock())
2290 return false;
2291 break;
2292 default:
2293 return false;
2294 }
2295
2296 // Read the address of the table from the operand register Rn.
2297 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002298 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002299 if (!success)
2300 return false;
2301
2302 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002303 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002304 if (!success)
2305 return false;
2306
2307 // the offsetted table address
2308 addr_t addr = base + (is_tbh ? index*2 : index);
2309
2310 // PC-relative offset to branch forward
2311 EmulateInstruction::Context context;
2312 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002313 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002314 if (!success)
2315 return false;
2316
Johnny Chene39f22d2011-02-19 01:36:13 +00002317 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002318 if (!success)
2319 return false;
2320
2321 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002322 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002323 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2324 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2325
2326 if (!BranchWritePC(context, target))
2327 return false;
2328
2329 return true;
2330}
2331
Caroline Ticedcc11b32011-03-02 23:57:02 +00002332// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2333// It can optionally update the condition flags based on the result.
2334bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002335EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002336{
2337#if 0
2338 if ConditionPassed() then
2339 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002340 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002341 R[d] = result;
2342 if setflags then
2343 APSR.N = result<31>;
2344 APSR.Z = IsZeroBit(result);
2345 APSR.C = carry;
2346 APSR.V = overflow;
2347#endif
2348
2349 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002350
Greg Clayton7bc39082011-03-24 23:53:38 +00002351 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002352 {
2353 uint32_t d;
2354 uint32_t n;
2355 bool setflags;
2356 uint32_t imm32;
2357 uint32_t carry_out;
2358
2359 //EncodingSpecificOperations();
2360 switch (encoding)
2361 {
2362 case eEncodingT1:
2363 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2364 d = Bits32 (opcode, 2, 0);
2365 n = Bits32 (opcode, 5, 3);
2366 setflags = !InITBlock();
2367 imm32 = Bits32 (opcode, 8,6);
2368
2369 break;
2370
2371 case eEncodingT2:
2372 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2373 d = Bits32 (opcode, 10, 8);
2374 n = Bits32 (opcode, 10, 8);
2375 setflags = !InITBlock();
2376 imm32 = Bits32 (opcode, 7, 0);
2377
2378 break;
2379
2380 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002381 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2382 // if Rn == '1101' then SEE ADD (SP plus immediate);
2383 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002384 d = Bits32 (opcode, 11, 8);
2385 n = Bits32 (opcode, 19, 16);
2386 setflags = BitIsSet (opcode, 20);
2387 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2388
2389 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2390 if (BadReg (d) || (n == 15))
2391 return false;
2392
2393 break;
2394
2395 case eEncodingT4:
2396 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002397 // if Rn == '1111' then SEE ADR;
2398 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002399 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2400 d = Bits32 (opcode, 11, 8);
2401 n = Bits32 (opcode, 19, 16);
2402 setflags = false;
2403 uint32_t i = Bit32 (opcode, 26);
2404 uint32_t imm3 = Bits32 (opcode, 14, 12);
2405 uint32_t imm8 = Bits32 (opcode, 7, 0);
2406 imm32 = (i << 11) | (imm3 << 8) | imm8;
2407
2408 // if BadReg(d) then UNPREDICTABLE;
2409 if (BadReg (d))
2410 return false;
2411
2412 break;
2413 }
2414 default:
2415 return false;
2416 }
2417
2418 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2419 if (!success)
2420 return false;
2421
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002422 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002423 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2424
2425 Register reg_n;
2426 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2427
2428 EmulateInstruction::Context context;
2429 context.type = eContextAddition;
2430 context.SetRegisterPlusOffset (reg_n, imm32);
2431
2432 //R[d] = result;
2433 //if setflags then
2434 //APSR.N = result<31>;
2435 //APSR.Z = IsZeroBit(result);
2436 //APSR.C = carry;
2437 //APSR.V = overflow;
2438 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2439 return false;
2440
2441 }
2442 return true;
2443}
2444
Johnny Chen8fa20592011-02-18 01:22:22 +00002445// This instruction adds an immediate value to a register value, and writes the result to the destination
2446// register. It can optionally update the condition flags based on the result.
2447bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002448EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002449{
2450#if 0
2451 // ARM pseudo code...
2452 if ConditionPassed() then
2453 EncodingSpecificOperations();
2454 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2455 if d == 15 then
2456 ALUWritePC(result); // setflags is always FALSE here
2457 else
2458 R[d] = result;
2459 if setflags then
2460 APSR.N = result<31>;
2461 APSR.Z = IsZeroBit(result);
2462 APSR.C = carry;
2463 APSR.V = overflow;
2464#endif
2465
2466 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002467
Greg Clayton7bc39082011-03-24 23:53:38 +00002468 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002469 {
2470 uint32_t Rd, Rn;
2471 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2472 bool setflags;
2473 switch (encoding)
2474 {
2475 case eEncodingA1:
2476 Rd = Bits32(opcode, 15, 12);
2477 Rn = Bits32(opcode, 19, 16);
2478 setflags = BitIsSet(opcode, 20);
2479 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2480 break;
2481 default:
2482 return false;
2483 }
2484
Johnny Chen8fa20592011-02-18 01:22:22 +00002485 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002486 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002487 if (!success)
2488 return false;
2489
2490 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2491
2492 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +00002493 context.type = EmulateInstruction::eContextAddition;
2494 Register dwarf_reg;
2495 dwarf_reg.SetRegister (eRegisterKindDWARF, Rn);
2496 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002497
2498 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2499 return false;
2500 }
2501 return true;
2502}
2503
Johnny Chend761dcf2011-02-17 22:03:29 +00002504// This instruction adds a register value and an optionally-shifted register value, and writes the result
2505// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002506bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002507EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002508{
2509#if 0
2510 // ARM pseudo code...
2511 if ConditionPassed() then
2512 EncodingSpecificOperations();
2513 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2514 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2515 if d == 15 then
2516 ALUWritePC(result); // setflags is always FALSE here
2517 else
2518 R[d] = result;
2519 if setflags then
2520 APSR.N = result<31>;
2521 APSR.Z = IsZeroBit(result);
2522 APSR.C = carry;
2523 APSR.V = overflow;
2524#endif
2525
2526 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002527
Greg Clayton7bc39082011-03-24 23:53:38 +00002528 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002529 {
2530 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002531 ARM_ShifterType shift_t;
2532 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002533 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002534 switch (encoding)
2535 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002536 case eEncodingT1:
2537 Rd = Bits32(opcode, 2, 0);
2538 Rn = Bits32(opcode, 5, 3);
2539 Rm = Bits32(opcode, 8, 6);
2540 setflags = !InITBlock();
2541 shift_t = SRType_LSL;
2542 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002543 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002544 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002545 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002546 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002547 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002548 shift_t = SRType_LSL;
2549 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002550 if (Rn == 15 && Rm == 15)
2551 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002552 if (Rd == 15 && InITBlock() && !LastInITBlock())
2553 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002554 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002555 case eEncodingA1:
2556 Rd = Bits32(opcode, 15, 12);
2557 Rn = Bits32(opcode, 19, 16);
2558 Rm = Bits32(opcode, 3, 0);
2559 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002560 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002561 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002562 default:
2563 return false;
2564 }
2565
Johnny Chen26863dc2011-02-09 23:43:29 +00002566 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002567 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002568 if (!success)
2569 return false;
2570
2571 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002572 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002573 if (!success)
2574 return false;
2575
Johnny Chene97c0d52011-02-18 19:32:20 +00002576 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002577 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002578
2579 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002580 context.type = EmulateInstruction::eContextAddition;
2581 Register op1_reg;
2582 Register op2_reg;
2583 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2584 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2585 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002586
Johnny Chen10530c22011-02-17 22:37:12 +00002587 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002588 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002589 }
2590 return true;
2591}
2592
Johnny Chen34075cb2011-02-22 01:56:31 +00002593// Compare Negative (immediate) adds a register value and an immediate value.
2594// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002595bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002596EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002597{
2598#if 0
2599 // ARM pseudo code...
2600 if ConditionPassed() then
2601 EncodingSpecificOperations();
2602 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2603 APSR.N = result<31>;
2604 APSR.Z = IsZeroBit(result);
2605 APSR.C = carry;
2606 APSR.V = overflow;
2607#endif
2608
2609 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002610
2611 uint32_t Rn; // the first operand
2612 uint32_t imm32; // the immediate value to be compared with
2613 switch (encoding) {
2614 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002615 Rn = Bits32(opcode, 19, 16);
2616 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2617 if (Rn == 15)
2618 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002619 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002620 case eEncodingA1:
2621 Rn = Bits32(opcode, 19, 16);
2622 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2623 break;
2624 default:
2625 return false;
2626 }
2627 // Read the register value from the operand register Rn.
2628 uint32_t reg_val = ReadCoreReg(Rn, &success);
2629 if (!success)
2630 return false;
2631
Johnny Chen078fbc62011-02-22 19:48:22 +00002632 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002633
2634 EmulateInstruction::Context context;
2635 context.type = EmulateInstruction::eContextImmediate;
2636 context.SetNoArgs ();
2637 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2638 return false;
2639
2640 return true;
2641}
2642
2643// Compare Negative (register) adds a register value and an optionally-shifted register value.
2644// It updates the condition flags based on the result, and discards the result.
2645bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002646EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002647{
2648#if 0
2649 // ARM pseudo code...
2650 if ConditionPassed() then
2651 EncodingSpecificOperations();
2652 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2653 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2654 APSR.N = result<31>;
2655 APSR.Z = IsZeroBit(result);
2656 APSR.C = carry;
2657 APSR.V = overflow;
2658#endif
2659
2660 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002661
2662 uint32_t Rn; // the first operand
2663 uint32_t Rm; // the second operand
2664 ARM_ShifterType shift_t;
2665 uint32_t shift_n; // the shift applied to the value read from Rm
2666 switch (encoding) {
2667 case eEncodingT1:
2668 Rn = Bits32(opcode, 2, 0);
2669 Rm = Bits32(opcode, 5, 3);
2670 shift_t = SRType_LSL;
2671 shift_n = 0;
2672 break;
2673 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002674 Rn = Bits32(opcode, 19, 16);
2675 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002676 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002677 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2678 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002679 return false;
2680 break;
2681 case eEncodingA1:
2682 Rn = Bits32(opcode, 19, 16);
2683 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002684 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002685 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002686 default:
2687 return false;
2688 }
2689 // Read the register value from register Rn.
2690 uint32_t val1 = ReadCoreReg(Rn, &success);
2691 if (!success)
2692 return false;
2693
2694 // Read the register value from register Rm.
2695 uint32_t val2 = ReadCoreReg(Rm, &success);
2696 if (!success)
2697 return false;
2698
2699 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002700 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002701
2702 EmulateInstruction::Context context;
2703 context.type = EmulateInstruction::eContextImmediate;
2704 context.SetNoArgs();
2705 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2706 return false;
2707
2708 return true;
2709}
2710
2711// Compare (immediate) subtracts an immediate value from a register value.
2712// It updates the condition flags based on the result, and discards the result.
2713bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002714EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002715{
2716#if 0
2717 // ARM pseudo code...
2718 if ConditionPassed() then
2719 EncodingSpecificOperations();
2720 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2721 APSR.N = result<31>;
2722 APSR.Z = IsZeroBit(result);
2723 APSR.C = carry;
2724 APSR.V = overflow;
2725#endif
2726
2727 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002728
2729 uint32_t Rn; // the first operand
2730 uint32_t imm32; // the immediate value to be compared with
2731 switch (encoding) {
2732 case eEncodingT1:
2733 Rn = Bits32(opcode, 10, 8);
2734 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002735 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002736 case eEncodingT2:
2737 Rn = Bits32(opcode, 19, 16);
2738 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2739 if (Rn == 15)
2740 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002741 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002742 case eEncodingA1:
2743 Rn = Bits32(opcode, 19, 16);
2744 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002745 break;
2746 default:
2747 return false;
2748 }
2749 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002750 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002751 if (!success)
2752 return false;
2753
Johnny Chen10530c22011-02-17 22:37:12 +00002754 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2755
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002756 EmulateInstruction::Context context;
2757 context.type = EmulateInstruction::eContextImmediate;
2758 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002759 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2760 return false;
2761
Johnny Chend4dc4442011-02-11 02:02:56 +00002762 return true;
2763}
2764
Johnny Chen34075cb2011-02-22 01:56:31 +00002765// Compare (register) subtracts an optionally-shifted register value from a register value.
2766// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002767bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002768EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002769{
2770#if 0
2771 // ARM pseudo code...
2772 if ConditionPassed() then
2773 EncodingSpecificOperations();
2774 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2775 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2776 APSR.N = result<31>;
2777 APSR.Z = IsZeroBit(result);
2778 APSR.C = carry;
2779 APSR.V = overflow;
2780#endif
2781
2782 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002783
2784 uint32_t Rn; // the first operand
2785 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002786 ARM_ShifterType shift_t;
2787 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002788 switch (encoding) {
2789 case eEncodingT1:
2790 Rn = Bits32(opcode, 2, 0);
2791 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002792 shift_t = SRType_LSL;
2793 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002794 break;
2795 case eEncodingT2:
2796 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2797 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002798 shift_t = SRType_LSL;
2799 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002800 if (Rn < 8 && Rm < 8)
2801 return false;
2802 if (Rn == 15 || Rm == 15)
2803 return false;
2804 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002805 case eEncodingA1:
2806 Rn = Bits32(opcode, 19, 16);
2807 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002808 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002809 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002810 default:
2811 return false;
2812 }
2813 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002814 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002815 if (!success)
2816 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002817
Johnny Chene4a4d302011-02-11 21:53:58 +00002818 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002819 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002820 if (!success)
2821 return false;
2822
Johnny Chen34075cb2011-02-22 01:56:31 +00002823 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2824 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002825
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002826 EmulateInstruction::Context context;
2827 context.type = EmulateInstruction::eContextImmediate;
2828 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002829 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2830 return false;
2831
Johnny Chene4a4d302011-02-11 21:53:58 +00002832 return true;
2833}
2834
Johnny Chen82f16aa2011-02-15 20:10:55 +00002835// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2836// shifting in copies of its sign bit, and writes the result to the destination register. It can
2837// optionally update the condition flags based on the result.
2838bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002839EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002840{
2841#if 0
2842 // ARM pseudo code...
2843 if ConditionPassed() then
2844 EncodingSpecificOperations();
2845 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2846 if d == 15 then // Can only occur for ARM encoding
2847 ALUWritePC(result); // setflags is always FALSE here
2848 else
2849 R[d] = result;
2850 if setflags then
2851 APSR.N = result<31>;
2852 APSR.Z = IsZeroBit(result);
2853 APSR.C = carry;
2854 // APSR.V unchanged
2855#endif
2856
Greg Clayton7bc39082011-03-24 23:53:38 +00002857 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002858}
2859
2860// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2861// shifting in copies of its sign bit, and writes the result to the destination register.
2862// The variable number of bits is read from the bottom byte of a register. It can optionally update
2863// the condition flags based on the result.
2864bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002865EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002866{
2867#if 0
2868 // ARM pseudo code...
2869 if ConditionPassed() then
2870 EncodingSpecificOperations();
2871 shift_n = UInt(R[m]<7:0>);
2872 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2873 R[d] = result;
2874 if setflags then
2875 APSR.N = result<31>;
2876 APSR.Z = IsZeroBit(result);
2877 APSR.C = carry;
2878 // APSR.V unchanged
2879#endif
2880
Greg Clayton7bc39082011-03-24 23:53:38 +00002881 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002882}
2883
2884// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2885// shifting in zeros, and writes the result to the destination register. It can optionally
2886// update the condition flags based on the result.
2887bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002888EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002889{
2890#if 0
2891 // ARM pseudo code...
2892 if ConditionPassed() then
2893 EncodingSpecificOperations();
2894 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2895 if d == 15 then // Can only occur for ARM encoding
2896 ALUWritePC(result); // setflags is always FALSE here
2897 else
2898 R[d] = result;
2899 if setflags then
2900 APSR.N = result<31>;
2901 APSR.Z = IsZeroBit(result);
2902 APSR.C = carry;
2903 // APSR.V unchanged
2904#endif
2905
Greg Clayton7bc39082011-03-24 23:53:38 +00002906 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002907}
2908
2909// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2910// shifting in zeros, and writes the result to the destination register. The variable number
2911// of bits is read from the bottom byte of a register. It can optionally update the condition
2912// flags based on the result.
2913bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002914EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002915{
2916#if 0
2917 // ARM pseudo code...
2918 if ConditionPassed() then
2919 EncodingSpecificOperations();
2920 shift_n = UInt(R[m]<7:0>);
2921 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2922 R[d] = result;
2923 if setflags then
2924 APSR.N = result<31>;
2925 APSR.Z = IsZeroBit(result);
2926 APSR.C = carry;
2927 // APSR.V unchanged
2928#endif
2929
Greg Clayton7bc39082011-03-24 23:53:38 +00002930 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002931}
2932
2933// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2934// shifting in zeros, and writes the result to the destination register. It can optionally
2935// update the condition flags based on the result.
2936bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002937EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002938{
2939#if 0
2940 // ARM pseudo code...
2941 if ConditionPassed() then
2942 EncodingSpecificOperations();
2943 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2944 if d == 15 then // Can only occur for ARM encoding
2945 ALUWritePC(result); // setflags is always FALSE here
2946 else
2947 R[d] = result;
2948 if setflags then
2949 APSR.N = result<31>;
2950 APSR.Z = IsZeroBit(result);
2951 APSR.C = carry;
2952 // APSR.V unchanged
2953#endif
2954
Greg Clayton7bc39082011-03-24 23:53:38 +00002955 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002956}
2957
2958// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2959// shifting in zeros, and writes the result to the destination register. The variable number
2960// of bits is read from the bottom byte of a register. It can optionally update the condition
2961// flags based on the result.
2962bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002963EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002964{
2965#if 0
2966 // ARM pseudo code...
2967 if ConditionPassed() then
2968 EncodingSpecificOperations();
2969 shift_n = UInt(R[m]<7:0>);
2970 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2971 R[d] = result;
2972 if setflags then
2973 APSR.N = result<31>;
2974 APSR.Z = IsZeroBit(result);
2975 APSR.C = carry;
2976 // APSR.V unchanged
2977#endif
2978
Greg Clayton7bc39082011-03-24 23:53:38 +00002979 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002980}
2981
Johnny Cheneeab4852011-02-16 22:14:44 +00002982// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2983// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2984// It can optionally update the condition flags based on the result.
2985bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002986EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002987{
2988#if 0
2989 // ARM pseudo code...
2990 if ConditionPassed() then
2991 EncodingSpecificOperations();
2992 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2993 if d == 15 then // Can only occur for ARM encoding
2994 ALUWritePC(result); // setflags is always FALSE here
2995 else
2996 R[d] = result;
2997 if setflags then
2998 APSR.N = result<31>;
2999 APSR.Z = IsZeroBit(result);
3000 APSR.C = carry;
3001 // APSR.V unchanged
3002#endif
3003
Greg Clayton7bc39082011-03-24 23:53:38 +00003004 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003005}
3006
3007// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3008// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3009// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3010// flags based on the result.
3011bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003012EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003013{
3014#if 0
3015 // ARM pseudo code...
3016 if ConditionPassed() then
3017 EncodingSpecificOperations();
3018 shift_n = UInt(R[m]<7:0>);
3019 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3020 R[d] = result;
3021 if setflags then
3022 APSR.N = result<31>;
3023 APSR.Z = IsZeroBit(result);
3024 APSR.C = carry;
3025 // APSR.V unchanged
3026#endif
3027
Greg Clayton7bc39082011-03-24 23:53:38 +00003028 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003029}
3030
3031// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3032// with the carry flag shifted into bit [31].
3033//
3034// RRX can optionally update the condition flags based on the result.
3035// In that case, bit [0] is shifted into the carry flag.
3036bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003037EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003038{
3039#if 0
3040 // ARM pseudo code...
3041 if ConditionPassed() then
3042 EncodingSpecificOperations();
3043 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3044 if d == 15 then // Can only occur for ARM encoding
3045 ALUWritePC(result); // setflags is always FALSE here
3046 else
3047 R[d] = result;
3048 if setflags then
3049 APSR.N = result<31>;
3050 APSR.Z = IsZeroBit(result);
3051 APSR.C = carry;
3052 // APSR.V unchanged
3053#endif
3054
Greg Clayton7bc39082011-03-24 23:53:38 +00003055 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003056}
3057
Johnny Chen41a0a152011-02-16 01:27:54 +00003058bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003059EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003060{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003061 assert(shift_type == SRType_ASR
3062 || shift_type == SRType_LSL
3063 || shift_type == SRType_LSR
3064 || shift_type == SRType_ROR
3065 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003066
Johnny Chen82f16aa2011-02-15 20:10:55 +00003067 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003068
Greg Clayton7bc39082011-03-24 23:53:38 +00003069 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003070 {
Johnny Chene7f89532011-02-15 23:22:46 +00003071 uint32_t Rd; // the destination register
3072 uint32_t Rm; // the first operand register
3073 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003074 uint32_t carry; // the carry bit after the shift operation
3075 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003076
3077 // Special case handling!
3078 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003079 ARMEncoding use_encoding = encoding;
3080 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003081 {
3082 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3083 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003084 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003085 }
3086
Greg Clayton7bc39082011-03-24 23:53:38 +00003087 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003088 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003089 // Due to the above special case handling!
3090 assert(shift_type != SRType_ROR);
3091
Johnny Chen82f16aa2011-02-15 20:10:55 +00003092 Rd = Bits32(opcode, 2, 0);
3093 Rm = Bits32(opcode, 5, 3);
3094 setflags = !InITBlock();
3095 imm5 = Bits32(opcode, 10, 6);
3096 break;
3097 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003098 // A8.6.141 RRX
3099 assert(shift_type != SRType_RRX);
3100
Johnny Chen82f16aa2011-02-15 20:10:55 +00003101 Rd = Bits32(opcode, 11, 8);
3102 Rm = Bits32(opcode, 3, 0);
3103 setflags = BitIsSet(opcode, 20);
3104 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3105 if (BadReg(Rd) || BadReg(Rm))
3106 return false;
3107 break;
3108 case eEncodingA1:
3109 Rd = Bits32(opcode, 15, 12);
3110 Rm = Bits32(opcode, 3, 0);
3111 setflags = BitIsSet(opcode, 20);
3112 imm5 = Bits32(opcode, 11, 7);
3113 break;
3114 default:
3115 return false;
3116 }
3117
Johnny Cheneeab4852011-02-16 22:14:44 +00003118 // A8.6.139 ROR (immediate)
3119 if (shift_type == SRType_ROR && imm5 == 0)
3120 shift_type = SRType_RRX;
3121
Johnny Chen82f16aa2011-02-15 20:10:55 +00003122 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003123 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003124 if (!success)
3125 return false;
3126
Johnny Cheneeab4852011-02-16 22:14:44 +00003127 // Decode the shift amount if not RRX.
3128 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003129
Johnny Chene97c0d52011-02-18 19:32:20 +00003130 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003131
3132 // The context specifies that an immediate is to be moved into Rd.
3133 EmulateInstruction::Context context;
3134 context.type = EmulateInstruction::eContextImmediate;
3135 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003136
Johnny Chen10530c22011-02-17 22:37:12 +00003137 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003138 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003139 }
3140 return true;
3141}
3142
Johnny Chene7f89532011-02-15 23:22:46 +00003143bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003144EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003145{
Johnny Chen41a0a152011-02-16 01:27:54 +00003146 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003147
3148 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003149
Greg Clayton7bc39082011-03-24 23:53:38 +00003150 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003151 {
3152 uint32_t Rd; // the destination register
3153 uint32_t Rn; // the first operand register
3154 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3155 uint32_t carry; // the carry bit after the shift operation
3156 bool setflags;
3157 switch (encoding) {
3158 case eEncodingT1:
3159 Rd = Bits32(opcode, 2, 0);
3160 Rn = Rd;
3161 Rm = Bits32(opcode, 5, 3);
3162 setflags = !InITBlock();
3163 break;
3164 case eEncodingT2:
3165 Rd = Bits32(opcode, 11, 8);
3166 Rn = Bits32(opcode, 19, 16);
3167 Rm = Bits32(opcode, 3, 0);
3168 setflags = BitIsSet(opcode, 20);
3169 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3170 return false;
3171 break;
3172 case eEncodingA1:
3173 Rd = Bits32(opcode, 15, 12);
3174 Rn = Bits32(opcode, 3, 0);
3175 Rm = Bits32(opcode, 11, 8);
3176 setflags = BitIsSet(opcode, 20);
3177 if (Rd == 15 || Rn == 15 || Rm == 15)
3178 return false;
3179 break;
3180 default:
3181 return false;
3182 }
3183
3184 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003185 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003186 if (!success)
3187 return false;
3188 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003189 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003190 if (!success)
3191 return false;
3192
3193 // Get the shift amount.
3194 uint32_t amt = Bits32(val, 7, 0);
3195
Johnny Chene97c0d52011-02-18 19:32:20 +00003196 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003197
3198 // The context specifies that an immediate is to be moved into Rd.
3199 EmulateInstruction::Context context;
3200 context.type = EmulateInstruction::eContextImmediate;
3201 context.SetNoArgs ();
3202
Johnny Chen10530c22011-02-17 22:37:12 +00003203 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003204 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003205 }
3206 return true;
3207}
3208
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003209// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003210// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003211// can be written back to the base register.
3212bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003213EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003214{
3215#if 0
3216 // ARM pseudo code...
3217 if ConditionPassed()
3218 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3219 address = R[n];
3220
3221 for i = 0 to 14
3222 if registers<i> == '1' then
3223 R[i] = MemA[address, 4]; address = address + 4;
3224 if registers<15> == '1' then
3225 LoadWritePC (MemA[address, 4]);
3226
3227 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3228 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3229
3230#endif
3231
3232 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003233
Greg Clayton7bc39082011-03-24 23:53:38 +00003234 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003235 {
3236 uint32_t n;
3237 uint32_t registers = 0;
3238 bool wback;
3239 const uint32_t addr_byte_size = GetAddressByteSize();
3240 switch (encoding)
3241 {
3242 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003243 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003244 n = Bits32 (opcode, 10, 8);
3245 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003246 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003247 wback = BitIsClear (registers, n);
3248 // if BitCount(registers) < 1 then UNPREDICTABLE;
3249 if (BitCount(registers) < 1)
3250 return false;
3251 break;
3252 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003253 // if W == '1' && Rn == '1101' then SEE POP;
3254 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003255 n = Bits32 (opcode, 19, 16);
3256 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003257 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003258 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003259
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003260 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003261 if ((n == 15)
3262 || (BitCount (registers) < 2)
3263 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3264 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003265
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003266 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003267 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003268 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003269
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003270 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003271 if (wback
3272 && BitIsSet (registers, n))
3273 return false;
3274 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003275
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003276 case eEncodingA1:
3277 n = Bits32 (opcode, 19, 16);
3278 registers = Bits32 (opcode, 15, 0);
3279 wback = BitIsSet (opcode, 21);
3280 if ((n == 15)
3281 || (BitCount (registers) < 1))
3282 return false;
3283 break;
3284 default:
3285 return false;
3286 }
3287
3288 int32_t offset = 0;
3289 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3290 if (!success)
3291 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003292
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003293 EmulateInstruction::Context context;
3294 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3295 Register dwarf_reg;
3296 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3297 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003298
3299 for (int i = 0; i < 14; ++i)
3300 {
3301 if (BitIsSet (registers, i))
3302 {
Caroline Tice85aab332011-02-08 23:56:10 +00003303 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003304 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003305 if (wback && (n == 13)) // Pop Instruction
3306 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3307
3308 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003309 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003310 if (!success)
3311 return false;
3312
3313 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3314 return false;
3315
3316 offset += addr_byte_size;
3317 }
3318 }
3319
3320 if (BitIsSet (registers, 15))
3321 {
3322 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003323 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003324 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003325 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003326 if (!success)
3327 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003328 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003329 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003330 return false;
3331 }
3332
3333 if (wback && BitIsClear (registers, n))
3334 {
Caroline Ticefa172202011-02-11 22:49:54 +00003335 // R[n] = R[n] + 4 * BitCount (registers)
3336 int32_t offset = addr_byte_size * BitCount (registers);
3337 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003338 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003339
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003340 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3341 return false;
3342 }
3343 if (wback && BitIsSet (registers, n))
3344 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003345 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003346 }
3347 return true;
3348}
Caroline Tice713c2662011-02-11 17:59:55 +00003349
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003350// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3351// The consecutive memory locations end at this address and the address just below the lowest of those locations
3352// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003353bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003354EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003355{
3356#if 0
3357 // ARM pseudo code...
3358 if ConditionPassed() then
3359 EncodingSpecificOperations();
3360 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003361
Caroline Tice713c2662011-02-11 17:59:55 +00003362 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003363 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003364 R[i] = MemA[address,4]; address = address + 4;
3365
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003366 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003367 LoadWritePC(MemA[address,4]);
3368
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003369 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3370 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003371#endif
3372
3373 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003374
Greg Clayton7bc39082011-03-24 23:53:38 +00003375 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003376 {
3377 uint32_t n;
3378 uint32_t registers = 0;
3379 bool wback;
3380 const uint32_t addr_byte_size = GetAddressByteSize();
3381
3382 // EncodingSpecificOperations();
3383 switch (encoding)
3384 {
3385 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003386 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003387 n = Bits32 (opcode, 19, 16);
3388 registers = Bits32 (opcode, 15, 0);
3389 wback = BitIsSet (opcode, 21);
3390
3391 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3392 if ((n == 15) || (BitCount (registers) < 1))
3393 return false;
3394
3395 break;
3396
3397 default:
3398 return false;
3399 }
3400 // address = R[n] - 4*BitCount(registers) + 4;
3401
3402 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003403 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003404
3405 if (!success)
3406 return false;
3407
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003408 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003409
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003410 EmulateInstruction::Context context;
3411 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3412 Register dwarf_reg;
3413 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3414 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003415
3416 // for i = 0 to 14
3417 for (int i = 0; i < 14; ++i)
3418 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003419 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003420 if (BitIsSet (registers, i))
3421 {
3422 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003423 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003424 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003425 if (!success)
3426 return false;
3427 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3428 return false;
3429 offset += addr_byte_size;
3430 }
3431 }
3432
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003433 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003434 // LoadWritePC(MemA[address,4]);
3435 if (BitIsSet (registers, 15))
3436 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003437 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003438 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003439 if (!success)
3440 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003441 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003442 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003443 return false;
3444 }
3445
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003446 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003447 if (wback && BitIsClear (registers, n))
3448 {
Caroline Tice713c2662011-02-11 17:59:55 +00003449 if (!success)
3450 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003451
3452 offset = (addr_byte_size * BitCount (registers)) * -1;
3453 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003454 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003455 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003456 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3457 return false;
3458 }
3459
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003460 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003461 if (wback && BitIsSet (registers, n))
3462 return WriteBits32Unknown (n);
3463 }
3464 return true;
3465}
3466
3467// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3468// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3469// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003470bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003471EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003472{
3473#if 0
3474 // ARM pseudo code...
3475 if ConditionPassed() then
3476 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3477 address = R[n] - 4*BitCount(registers);
3478
3479 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003480 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003481 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003482 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003483 LoadWritePC(MemA[address,4]);
3484
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003485 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3486 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003487#endif
3488
3489 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003490
Greg Clayton7bc39082011-03-24 23:53:38 +00003491 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003492 {
3493 uint32_t n;
3494 uint32_t registers = 0;
3495 bool wback;
3496 const uint32_t addr_byte_size = GetAddressByteSize();
3497 switch (encoding)
3498 {
3499 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003500 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003501 n = Bits32 (opcode, 19, 16);
3502 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003503 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003504 wback = BitIsSet (opcode, 21);
3505
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003506 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003507 if ((n == 15)
3508 || (BitCount (registers) < 2)
3509 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3510 return false;
3511
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003512 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003513 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003514 return false;
3515
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003516 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003517 if (wback && BitIsSet (registers, n))
3518 return false;
3519
3520 break;
3521
3522 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003523 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003524 n = Bits32 (opcode, 19, 16);
3525 registers = Bits32 (opcode, 15, 0);
3526 wback = BitIsSet (opcode, 21);
3527
3528 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3529 if ((n == 15) || (BitCount (registers) < 1))
3530 return false;
3531
3532 break;
3533
3534 default:
3535 return false;
3536 }
3537
Caroline Tice713c2662011-02-11 17:59:55 +00003538 // address = R[n] - 4*BitCount(registers);
3539
Caroline Tice0b29e242011-02-08 23:16:02 +00003540 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003541 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003542
3543 if (!success)
3544 return false;
3545
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003546 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003547 EmulateInstruction::Context context;
3548 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3549 Register dwarf_reg;
3550 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003551 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003552
3553 for (int i = 0; i < 14; ++i)
3554 {
3555 if (BitIsSet (registers, i))
3556 {
3557 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003558 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003559 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003560 if (!success)
3561 return false;
3562
3563 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3564 return false;
3565
3566 offset += addr_byte_size;
3567 }
3568 }
3569
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003570 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003571 // LoadWritePC(MemA[address,4]);
3572 if (BitIsSet (registers, 15))
3573 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003574 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003575 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003576 if (!success)
3577 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003578 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003579 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003580 return false;
3581 }
3582
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003583 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003584 if (wback && BitIsClear (registers, n))
3585 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003586 if (!success)
3587 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003588
3589 offset = (addr_byte_size * BitCount (registers)) * -1;
3590 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003591 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003592 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003593 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3594 return false;
3595 }
3596
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003597 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003598 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003599 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003600 }
3601 return true;
3602}
Caroline Tice85aab332011-02-08 23:56:10 +00003603
Caroline Tice713c2662011-02-11 17:59:55 +00003604// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3605// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3606// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003607bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003608EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003609{
3610#if 0
3611 if ConditionPassed() then
3612 EncodingSpecificOperations();
3613 address = R[n] + 4;
3614
3615 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003616 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003617 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003618 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003619 LoadWritePC(MemA[address,4]);
3620
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003621 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3622 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003623#endif
3624
3625 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003626
Greg Clayton7bc39082011-03-24 23:53:38 +00003627 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003628 {
3629 uint32_t n;
3630 uint32_t registers = 0;
3631 bool wback;
3632 const uint32_t addr_byte_size = GetAddressByteSize();
3633 switch (encoding)
3634 {
3635 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003636 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003637 n = Bits32 (opcode, 19, 16);
3638 registers = Bits32 (opcode, 15, 0);
3639 wback = BitIsSet (opcode, 21);
3640
3641 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3642 if ((n == 15) || (BitCount (registers) < 1))
3643 return false;
3644
3645 break;
3646 default:
3647 return false;
3648 }
3649 // address = R[n] + 4;
3650
3651 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003652 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003653
3654 if (!success)
3655 return false;
3656
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003657 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003658
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003659 EmulateInstruction::Context context;
3660 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3661 Register dwarf_reg;
3662 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3663 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003664
3665 for (int i = 0; i < 14; ++i)
3666 {
3667 if (BitIsSet (registers, i))
3668 {
3669 // R[i] = MemA[address,4]; address = address + 4;
3670
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003671 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003672 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003673 if (!success)
3674 return false;
3675
3676 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3677 return false;
3678
3679 offset += addr_byte_size;
3680 }
3681 }
3682
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003683 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003684 // LoadWritePC(MemA[address,4]);
3685 if (BitIsSet (registers, 15))
3686 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003687 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003688 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003689 if (!success)
3690 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003691 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003692 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003693 return false;
3694 }
3695
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003696 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003697 if (wback && BitIsClear (registers, n))
3698 {
Caroline Tice85aab332011-02-08 23:56:10 +00003699 if (!success)
3700 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003701
3702 offset = addr_byte_size * BitCount (registers);
3703 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003704 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003705 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003706 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3707 return false;
3708 }
3709
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003710 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003711 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003712 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003713 }
3714 return true;
3715}
Caroline Tice0b29e242011-02-08 23:16:02 +00003716
Johnny Chenef21b592011-02-10 01:52:38 +00003717// Load Register (immediate) calculates an address from a base register value and
3718// an immediate offset, loads a word from memory, and writes to a register.
3719// LDR (immediate, Thumb)
3720bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003721EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003722{
3723#if 0
3724 // ARM pseudo code...
3725 if (ConditionPassed())
3726 {
3727 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3728 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3729 address = if index then offset_addr else R[n];
3730 data = MemU[address,4];
3731 if wback then R[n] = offset_addr;
3732 if t == 15 then
3733 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3734 elsif UnalignedSupport() || address<1:0> = '00' then
3735 R[t] = data;
3736 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3737 }
3738#endif
3739
3740 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003741
Greg Clayton7bc39082011-03-24 23:53:38 +00003742 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003743 {
3744 uint32_t Rt; // the destination register
3745 uint32_t Rn; // the base register
3746 uint32_t imm32; // the immediate offset used to form the address
3747 addr_t offset_addr; // the offset address
3748 addr_t address; // the calculated address
3749 uint32_t data; // the literal data value from memory load
3750 bool add, index, wback;
3751 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003752 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003753 Rt = Bits32(opcode, 2, 0);
3754 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003755 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3756 // index = TRUE; add = TRUE; wback = FALSE
3757 add = true;
3758 index = true;
3759 wback = false;
3760
3761 break;
3762
3763 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003764 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003765 Rt = Bits32 (opcode, 10, 8);
3766 Rn = 13;
3767 imm32 = Bits32 (opcode, 7, 0) << 2;
3768
3769 // index = TRUE; add = TRUE; wback = FALSE;
3770 index = true;
3771 add = true;
3772 wback = false;
3773
3774 break;
3775
3776 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003777 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003778 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3779 Rt = Bits32 (opcode, 15, 12);
3780 Rn = Bits32 (opcode, 19, 16);
3781 imm32 = Bits32 (opcode, 11, 0);
3782
3783 // index = TRUE; add = TRUE; wback = FALSE;
3784 index = true;
3785 add = true;
3786 wback = false;
3787
3788 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3789 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3790 return false;
3791
3792 break;
3793
3794 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003795 // if Rn == '1111' then SEE LDR (literal);
3796 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3797 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3798 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003799 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3800 return false;
3801
3802 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3803 Rt = Bits32 (opcode, 15, 12);
3804 Rn = Bits32 (opcode, 19, 16);
3805 imm32 = Bits32 (opcode, 7, 0);
3806
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003807 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003808 index = BitIsSet (opcode, 10);
3809 add = BitIsSet (opcode, 9);
3810 wback = BitIsSet (opcode, 8);
3811
3812 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3813 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3814 return false;
3815
3816 break;
3817
3818 default:
3819 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003820 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003821 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003822 if (!success)
3823 return false;
3824 if (add)
3825 offset_addr = base + imm32;
3826 else
3827 offset_addr = base - imm32;
3828
3829 address = (index ? offset_addr : base);
3830
Caroline Ticebaf1f642011-03-24 19:23:45 +00003831 Register base_reg;
3832 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003833 if (wback)
3834 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003835 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003836 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3837 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003838
Johnny Chenef21b592011-02-10 01:52:38 +00003839 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3840 return false;
3841 }
3842
3843 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003844 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003845 context.type = EmulateInstruction::eContextRegisterLoad;
3846 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003847
3848 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003849 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003850 if (!success)
3851 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003852
3853 if (Rt == 15)
3854 {
3855 if (Bits32(address, 1, 0) == 0)
3856 {
Johnny Chen668b4512011-02-15 21:08:58 +00003857 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003858 return false;
3859 }
3860 else
3861 return false;
3862 }
3863 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3864 {
3865 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3866 return false;
3867 }
3868 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003869 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003870 }
3871 return true;
3872}
3873
Caroline Ticeaf556562011-02-15 18:42:15 +00003874// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3875// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3876// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003877bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003878EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003879{
3880#if 0
3881 if ConditionPassed() then
3882 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3883 address = R[n];
3884
3885 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003886 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003887 if i == n && wback && i != LowestSetBit(registers) then
3888 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3889 else
3890 MemA[address,4] = R[i];
3891 address = address + 4;
3892
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003893 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003894 MemA[address,4] = PCStoreValue();
3895 if wback then R[n] = R[n] + 4*BitCount(registers);
3896#endif
3897
3898 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003899
Greg Clayton7bc39082011-03-24 23:53:38 +00003900 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003901 {
3902 uint32_t n;
3903 uint32_t registers = 0;
3904 bool wback;
3905 const uint32_t addr_byte_size = GetAddressByteSize();
3906
3907 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3908 switch (encoding)
3909 {
3910 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003911 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003912 n = Bits32 (opcode, 10, 8);
3913 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003914 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003915 wback = true;
3916
3917 // if BitCount(registers) < 1 then UNPREDICTABLE;
3918 if (BitCount (registers) < 1)
3919 return false;
3920
3921 break;
3922
3923 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003924 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003925 n = Bits32 (opcode, 19, 16);
3926 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003927 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003928 wback = BitIsSet (opcode, 21);
3929
3930 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3931 if ((n == 15) || (BitCount (registers) < 2))
3932 return false;
3933
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003934 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003935 if (wback && BitIsSet (registers, n))
3936 return false;
3937
3938 break;
3939
3940 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003941 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003942 n = Bits32 (opcode, 19, 16);
3943 registers = Bits32 (opcode, 15, 0);
3944 wback = BitIsSet (opcode, 21);
3945
3946 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3947 if ((n == 15) || (BitCount (registers) < 1))
3948 return false;
3949
3950 break;
3951
3952 default:
3953 return false;
3954 }
3955
3956 // address = R[n];
3957 int32_t offset = 0;
3958 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3959 if (!success)
3960 return false;
3961
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003962 EmulateInstruction::Context context;
3963 context.type = EmulateInstruction::eContextRegisterStore;
3964 Register base_reg;
3965 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003966
3967 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003968 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003969 for (int i = 0; i < 14; ++i)
3970 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003971 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003972 if (BitIsSet (registers, i))
3973 {
3974 if (i < lowest_set_bit)
3975 lowest_set_bit = i;
3976 // if i == n && wback && i != LowestSetBit(registers) then
3977 if ((i == n) && wback && (i != lowest_set_bit))
3978 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3979 WriteBits32UnknownToMemory (address + offset);
3980 else
3981 {
3982 // MemA[address,4] = R[i];
3983 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3984 if (!success)
3985 return false;
3986
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003987 Register data_reg;
3988 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3989 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003990 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003991 return false;
3992 }
3993
3994 // address = address + 4;
3995 offset += addr_byte_size;
3996 }
3997 }
3998
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003999 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004000 // MemA[address,4] = PCStoreValue();
4001 if (BitIsSet (registers, 15))
4002 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004003 Register pc_reg;
4004 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4005 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004006 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004007 if (!success)
4008 return false;
4009
Caroline Tice8d681f52011-03-17 23:50:16 +00004010 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004011 return false;
4012 }
4013
4014 // if wback then R[n] = R[n] + 4*BitCount(registers);
4015 if (wback)
4016 {
4017 offset = addr_byte_size * BitCount (registers);
4018 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004019 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004020 addr_t data = address + offset;
4021 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4022 return false;
4023 }
4024 }
4025 return true;
4026}
4027
Caroline Ticeaf556562011-02-15 18:42:15 +00004028// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4029// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4030// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004031bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004032EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004033{
4034#if 0
4035 if ConditionPassed() then
4036 EncodingSpecificOperations();
4037 address = R[n] - 4*BitCount(registers) + 4;
4038
4039 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004040 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004041 if i == n && wback && i != LowestSetBit(registers) then
4042 MemA[address,4] = bits(32) UNKNOWN;
4043 else
4044 MemA[address,4] = R[i];
4045 address = address + 4;
4046
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004047 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004048 MemA[address,4] = PCStoreValue();
4049
4050 if wback then R[n] = R[n] - 4*BitCount(registers);
4051#endif
4052
4053 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004054
Greg Clayton7bc39082011-03-24 23:53:38 +00004055 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004056 {
4057 uint32_t n;
4058 uint32_t registers = 0;
4059 bool wback;
4060 const uint32_t addr_byte_size = GetAddressByteSize();
4061
4062 // EncodingSpecificOperations();
4063 switch (encoding)
4064 {
4065 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004066 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004067 n = Bits32 (opcode, 19, 16);
4068 registers = Bits32 (opcode, 15, 0);
4069 wback = BitIsSet (opcode, 21);
4070
4071 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4072 if ((n == 15) || (BitCount (registers) < 1))
4073 return false;
4074 break;
4075 default:
4076 return false;
4077 }
4078
4079 // address = R[n] - 4*BitCount(registers) + 4;
4080 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004081 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004082 if (!success)
4083 return false;
4084
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004085 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004086
4087 EmulateInstruction::Context context;
4088 context.type = EmulateInstruction::eContextRegisterStore;
4089 Register base_reg;
4090 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4091
4092 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004093 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004094 for (int i = 0; i < 14; ++i)
4095 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004096 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004097 if (BitIsSet (registers, i))
4098 {
4099 if (i < lowest_bit_set)
4100 lowest_bit_set = i;
4101 //if i == n && wback && i != LowestSetBit(registers) then
4102 if ((i == n) && wback && (i != lowest_bit_set))
4103 // MemA[address,4] = bits(32) UNKNOWN;
4104 WriteBits32UnknownToMemory (address + offset);
4105 else
4106 {
4107 // MemA[address,4] = R[i];
4108 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4109 if (!success)
4110 return false;
4111
4112 Register data_reg;
4113 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004114 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004115 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004116 return false;
4117 }
4118
4119 // address = address + 4;
4120 offset += addr_byte_size;
4121 }
4122 }
4123
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004124 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004125 // MemA[address,4] = PCStoreValue();
4126 if (BitIsSet (registers, 15))
4127 {
4128 Register pc_reg;
4129 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4130 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004131 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004132 if (!success)
4133 return false;
4134
Caroline Tice8d681f52011-03-17 23:50:16 +00004135 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004136 return false;
4137 }
4138
4139 // if wback then R[n] = R[n] - 4*BitCount(registers);
4140 if (wback)
4141 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004142 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004143 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4144 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004145 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004146 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4147 return false;
4148 }
4149 }
4150 return true;
4151}
4152
Caroline Ticeaf556562011-02-15 18:42:15 +00004153// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4154// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4155// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004156bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004157EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004158{
4159#if 0
4160 if ConditionPassed() then
4161 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4162 address = R[n] - 4*BitCount(registers);
4163
4164 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004165 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004166 if i == n && wback && i != LowestSetBit(registers) then
4167 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4168 else
4169 MemA[address,4] = R[i];
4170 address = address + 4;
4171
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004172 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004173 MemA[address,4] = PCStoreValue();
4174
4175 if wback then R[n] = R[n] - 4*BitCount(registers);
4176#endif
4177
4178
4179 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004180
Greg Clayton7bc39082011-03-24 23:53:38 +00004181 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004182 {
4183 uint32_t n;
4184 uint32_t registers = 0;
4185 bool wback;
4186 const uint32_t addr_byte_size = GetAddressByteSize();
4187
4188 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4189 switch (encoding)
4190 {
4191 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004192 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004193 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4194 {
4195 // See PUSH
4196 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004197 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004198 n = Bits32 (opcode, 19, 16);
4199 registers = Bits32 (opcode, 15, 0);
4200 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4201 wback = BitIsSet (opcode, 21);
4202 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4203 if ((n == 15) || BitCount (registers) < 2)
4204 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004205 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004206 if (wback && BitIsSet (registers, n))
4207 return false;
4208 break;
4209
4210 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004211 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004212 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4213 {
4214 // See Push
4215 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004216 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004217 n = Bits32 (opcode, 19, 16);
4218 registers = Bits32 (opcode, 15, 0);
4219 wback = BitIsSet (opcode, 21);
4220 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4221 if ((n == 15) || BitCount (registers) < 1)
4222 return false;
4223 break;
4224
4225 default:
4226 return false;
4227 }
4228
4229 // address = R[n] - 4*BitCount(registers);
4230
4231 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004232 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004233 if (!success)
4234 return false;
4235
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004236 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004237
4238 EmulateInstruction::Context context;
4239 context.type = EmulateInstruction::eContextRegisterStore;
4240 Register base_reg;
4241 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4242
4243 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004244 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004245 for (int i = 0; i < 14; ++i)
4246 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004247 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004248 if (BitIsSet (registers, i))
4249 {
4250 if (i < lowest_set_bit)
4251 lowest_set_bit = i;
4252 // if i == n && wback && i != LowestSetBit(registers) then
4253 if ((i == n) && wback && (i != lowest_set_bit))
4254 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4255 WriteBits32UnknownToMemory (address + offset);
4256 else
4257 {
4258 // MemA[address,4] = R[i];
4259 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4260 if (!success)
4261 return false;
4262
4263 Register data_reg;
4264 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004265 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004266 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004267 return false;
4268 }
4269
4270 // address = address + 4;
4271 offset += addr_byte_size;
4272 }
4273 }
4274
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004275 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004276 // MemA[address,4] = PCStoreValue();
4277 if (BitIsSet (registers, 15))
4278 {
4279 Register pc_reg;
4280 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4281 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004282 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004283 if (!success)
4284 return false;
4285
Caroline Tice8d681f52011-03-17 23:50:16 +00004286 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004287 return false;
4288 }
4289
4290 // if wback then R[n] = R[n] - 4*BitCount(registers);
4291 if (wback)
4292 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004293 offset = (addr_byte_size * BitCount (registers)) * -1;
4294 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4295 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004296 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004297 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4298 return false;
4299 }
4300 }
4301 return true;
4302}
4303
4304// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4305// from a base register. The consecutive memory locations start just above this address, and the address of the last
4306// of those locations can optionally be written back to the base register.
4307bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004308EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004309{
4310#if 0
4311 if ConditionPassed() then
4312 EncodingSpecificOperations();
4313 address = R[n] + 4;
4314
4315 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004316 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004317 if i == n && wback && i != LowestSetBit(registers) then
4318 MemA[address,4] = bits(32) UNKNOWN;
4319 else
4320 MemA[address,4] = R[i];
4321 address = address + 4;
4322
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004323 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004324 MemA[address,4] = PCStoreValue();
4325
4326 if wback then R[n] = R[n] + 4*BitCount(registers);
4327#endif
4328
4329 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004330
Greg Clayton7bc39082011-03-24 23:53:38 +00004331 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004332 {
4333 uint32_t n;
4334 uint32_t registers = 0;
4335 bool wback;
4336 const uint32_t addr_byte_size = GetAddressByteSize();
4337
4338 // EncodingSpecificOperations();
4339 switch (encoding)
4340 {
4341 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004342 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004343 n = Bits32 (opcode, 19, 16);
4344 registers = Bits32 (opcode, 15, 0);
4345 wback = BitIsSet (opcode, 21);
4346
4347 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4348 if ((n == 15) && (BitCount (registers) < 1))
4349 return false;
4350 break;
4351 default:
4352 return false;
4353 }
4354 // address = R[n] + 4;
4355
4356 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004357 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004358 if (!success)
4359 return false;
4360
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004361 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004362
4363 EmulateInstruction::Context context;
4364 context.type = EmulateInstruction::eContextRegisterStore;
4365 Register base_reg;
4366 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4367
4368 uint32_t lowest_set_bit = 14;
4369 // for i = 0 to 14
4370 for (int i = 0; i < 14; ++i)
4371 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004372 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004373 if (BitIsSet (registers, i))
4374 {
4375 if (i < lowest_set_bit)
4376 lowest_set_bit = i;
4377 // if i == n && wback && i != LowestSetBit(registers) then
4378 if ((i == n) && wback && (i != lowest_set_bit))
4379 // MemA[address,4] = bits(32) UNKNOWN;
4380 WriteBits32UnknownToMemory (address + offset);
4381 // else
4382 else
4383 {
4384 // MemA[address,4] = R[i];
4385 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4386 if (!success)
4387 return false;
4388
4389 Register data_reg;
4390 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004391 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004392 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004393 return false;
4394 }
4395
4396 // address = address + 4;
4397 offset += addr_byte_size;
4398 }
4399 }
4400
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004401 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004402 // MemA[address,4] = PCStoreValue();
4403 if (BitIsSet (registers, 15))
4404 {
4405 Register pc_reg;
4406 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4407 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004408 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004409 if (!success)
4410 return false;
4411
Caroline Tice8d681f52011-03-17 23:50:16 +00004412 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004413 return false;
4414 }
4415
4416 // if wback then R[n] = R[n] + 4*BitCount(registers);
4417 if (wback)
4418 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004419 offset = addr_byte_size * BitCount (registers);
4420 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4421 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004422 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004423 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4424 return false;
4425 }
4426 }
4427 return true;
4428}
Caroline Tice7fac8572011-02-15 22:53:54 +00004429
4430// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4431// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4432bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004433EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004434{
4435#if 0
4436 if ConditionPassed() then
4437 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4438 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4439 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004440 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004441 MemU[address,4] = R[t];
4442 else // Can only occur before ARMv7
4443 MemU[address,4] = bits(32) UNKNOWN;
4444 if wback then R[n] = offset_addr;
4445#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004446
Caroline Tice7fac8572011-02-15 22:53:54 +00004447 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004448
Greg Clayton7bc39082011-03-24 23:53:38 +00004449 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004450 {
4451 const uint32_t addr_byte_size = GetAddressByteSize();
4452
4453 uint32_t t;
4454 uint32_t n;
4455 uint32_t imm32;
4456 bool index;
4457 bool add;
4458 bool wback;
4459 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4460 switch (encoding)
4461 {
4462 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004463 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004464 t = Bits32 (opcode, 2, 0);
4465 n = Bits32 (opcode, 5, 3);
4466 imm32 = Bits32 (opcode, 10, 6) << 2;
4467
4468 // index = TRUE; add = TRUE; wback = FALSE;
4469 index = true;
4470 add = false;
4471 wback = false;
4472 break;
4473
4474 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004475 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004476 t = Bits32 (opcode, 10, 8);
4477 n = 13;
4478 imm32 = Bits32 (opcode, 7, 0) << 2;
4479
4480 // index = TRUE; add = TRUE; wback = FALSE;
4481 index = true;
4482 add = true;
4483 wback = false;
4484 break;
4485
4486 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004487 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004488 if (Bits32 (opcode, 19, 16) == 15)
4489 return false;
4490
4491 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4492 t = Bits32 (opcode, 15, 12);
4493 n = Bits32 (opcode, 19, 16);
4494 imm32 = Bits32 (opcode, 11, 0);
4495
4496 // index = TRUE; add = TRUE; wback = FALSE;
4497 index = true;
4498 add = true;
4499 wback = false;
4500
4501 // if t == 15 then UNPREDICTABLE;
4502 if (t == 15)
4503 return false;
4504 break;
4505
4506 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004507 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4508 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4509 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004510 if ((Bits32 (opcode, 19, 16) == 15)
4511 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4512 return false;
4513
4514 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4515 t = Bits32 (opcode, 15, 12);
4516 n = Bits32 (opcode, 19, 16);
4517 imm32 = Bits32 (opcode, 7, 0);
4518
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004519 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004520 index = BitIsSet (opcode, 10);
4521 add = BitIsSet (opcode, 9);
4522 wback = BitIsSet (opcode, 8);
4523
4524 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4525 if ((t == 15) || (wback && (n == t)))
4526 return false;
4527 break;
4528
4529 default:
4530 return false;
4531 }
4532
4533 addr_t offset_addr;
4534 addr_t address;
4535
4536 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004537 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004538 if (!success)
4539 return false;
4540
4541 if (add)
4542 offset_addr = base_address + imm32;
4543 else
4544 offset_addr = base_address - imm32;
4545
4546 // address = if index then offset_addr else R[n];
4547 if (index)
4548 address = offset_addr;
4549 else
4550 address = base_address;
4551
4552 EmulateInstruction::Context context;
4553 context.type = eContextRegisterStore;
4554 Register base_reg;
4555 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4556
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004557 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004558 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4559 {
4560 // MemU[address,4] = R[t];
4561 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4562 if (!success)
4563 return false;
4564
4565 Register data_reg;
4566 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4567 int32_t offset = address - base_address;
4568 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004569 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004570 return false;
4571 }
4572 else
4573 {
4574 // MemU[address,4] = bits(32) UNKNOWN;
4575 WriteBits32UnknownToMemory (address);
4576 }
4577
4578 // if wback then R[n] = offset_addr;
4579 if (wback)
4580 {
4581 context.type = eContextRegisterLoad;
4582 context.SetAddress (offset_addr);
4583 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4584 return false;
4585 }
4586 }
4587 return true;
4588}
Caroline Ticeaf556562011-02-15 18:42:15 +00004589
Caroline Tice3fd63e92011-02-16 00:33:43 +00004590// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4591// word from a register to memory. The offset register value can optionally be shifted.
4592bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004593EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004594{
4595#if 0
4596 if ConditionPassed() then
4597 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4598 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4599 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4600 address = if index then offset_addr else R[n];
4601 if t == 15 then // Only possible for encoding A1
4602 data = PCStoreValue();
4603 else
4604 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004605 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004606 MemU[address,4] = data;
4607 else // Can only occur before ARMv7
4608 MemU[address,4] = bits(32) UNKNOWN;
4609 if wback then R[n] = offset_addr;
4610#endif
4611
4612 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004613
Greg Clayton7bc39082011-03-24 23:53:38 +00004614 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004615 {
4616 const uint32_t addr_byte_size = GetAddressByteSize();
4617
4618 uint32_t t;
4619 uint32_t n;
4620 uint32_t m;
4621 ARM_ShifterType shift_t;
4622 uint32_t shift_n;
4623 bool index;
4624 bool add;
4625 bool wback;
4626
4627 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4628 switch (encoding)
4629 {
4630 case eEncodingT1:
4631 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4632 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4633 t = Bits32 (opcode, 2, 0);
4634 n = Bits32 (opcode, 5, 3);
4635 m = Bits32 (opcode, 8, 6);
4636
4637 // index = TRUE; add = TRUE; wback = FALSE;
4638 index = true;
4639 add = true;
4640 wback = false;
4641
4642 // (shift_t, shift_n) = (SRType_LSL, 0);
4643 shift_t = SRType_LSL;
4644 shift_n = 0;
4645 break;
4646
4647 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004648 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004649 if (Bits32 (opcode, 19, 16) == 15)
4650 return false;
4651
4652 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4653 t = Bits32 (opcode, 15, 12);
4654 n = Bits32 (opcode, 19, 16);
4655 m = Bits32 (opcode, 3, 0);
4656
4657 // index = TRUE; add = TRUE; wback = FALSE;
4658 index = true;
4659 add = true;
4660 wback = false;
4661
4662 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4663 shift_t = SRType_LSL;
4664 shift_n = Bits32 (opcode, 5, 4);
4665
4666 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4667 if ((t == 15) || (BadReg (m)))
4668 return false;
4669 break;
4670
4671 case eEncodingA1:
4672 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004673 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004674 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4675 t = Bits32 (opcode, 15, 12);
4676 n = Bits32 (opcode, 19, 16);
4677 m = Bits32 (opcode, 3, 0);
4678
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004679 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004680 index = BitIsSet (opcode, 24);
4681 add = BitIsSet (opcode, 23);
4682 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4683
4684 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4685 uint32_t typ = Bits32 (opcode, 6, 5);
4686 uint32_t imm5 = Bits32 (opcode, 11, 7);
4687 shift_n = DecodeImmShift(typ, imm5, shift_t);
4688
4689 // if m == 15 then UNPREDICTABLE;
4690 if (m == 15)
4691 return false;
4692
4693 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4694 if (wback && ((n == 15) || (n == t)))
4695 return false;
4696
4697 break;
4698 }
4699 default:
4700 return false;
4701 }
4702
4703 addr_t offset_addr;
4704 addr_t address;
4705 int32_t offset = 0;
4706
4707 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4708 if (!success)
4709 return false;
4710
4711 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4712 if (!success)
4713 return false;
4714
4715 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004716 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004717
4718 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4719 if (add)
4720 offset_addr = base_address + offset;
4721 else
4722 offset_addr = base_address - offset;
4723
4724 // address = if index then offset_addr else R[n];
4725 if (index)
4726 address = offset_addr;
4727 else
4728 address = base_address;
4729
4730 uint32_t data;
4731 // if t == 15 then // Only possible for encoding A1
4732 if (t == 15)
4733 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004734 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004735 else
4736 // data = R[t];
4737 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4738
4739 if (!success)
4740 return false;
4741
4742 EmulateInstruction::Context context;
4743 context.type = eContextRegisterStore;
4744
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004745 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004746 if (UnalignedSupport ()
4747 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4748 || CurrentInstrSet() == eModeARM)
4749 {
4750 // MemU[address,4] = data;
4751
4752 Register base_reg;
4753 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4754
4755 Register data_reg;
4756 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4757
4758 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004759 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004760 return false;
4761
4762 }
4763 else
4764 // MemU[address,4] = bits(32) UNKNOWN;
4765 WriteBits32UnknownToMemory (address);
4766
4767 // if wback then R[n] = offset_addr;
4768 if (wback)
4769 {
4770 context.type = eContextRegisterLoad;
4771 context.SetAddress (offset_addr);
4772 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4773 return false;
4774 }
4775
4776 }
4777 return true;
4778}
Caroline Tice73a29de2011-02-16 20:22:22 +00004779
4780bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004781EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004782{
4783#if 0
4784 if ConditionPassed() then
4785 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4786 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4787 address = if index then offset_addr else R[n];
4788 MemU[address,1] = R[t]<7:0>;
4789 if wback then R[n] = offset_addr;
4790#endif
4791
4792
4793 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004794
Greg Clayton7bc39082011-03-24 23:53:38 +00004795 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004796 {
4797 uint32_t t;
4798 uint32_t n;
4799 uint32_t imm32;
4800 bool index;
4801 bool add;
4802 bool wback;
4803 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4804 switch (encoding)
4805 {
4806 case eEncodingT1:
4807 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4808 t = Bits32 (opcode, 2, 0);
4809 n = Bits32 (opcode, 5, 3);
4810 imm32 = Bits32 (opcode, 10, 6);
4811
4812 // index = TRUE; add = TRUE; wback = FALSE;
4813 index = true;
4814 add = true;
4815 wback = false;
4816 break;
4817
4818 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004819 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004820 if (Bits32 (opcode, 19, 16) == 15)
4821 return false;
4822
4823 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4824 t = Bits32 (opcode, 15, 12);
4825 n = Bits32 (opcode, 19, 16);
4826 imm32 = Bits32 (opcode, 11, 0);
4827
4828 // index = TRUE; add = TRUE; wback = FALSE;
4829 index = true;
4830 add = true;
4831 wback = false;
4832
4833 // if BadReg(t) then UNPREDICTABLE;
4834 if (BadReg (t))
4835 return false;
4836 break;
4837
4838 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004839 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4840 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004841 if (Bits32 (opcode, 19, 16) == 15)
4842 return false;
4843
4844 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4845 t = Bits32 (opcode, 15, 12);
4846 n = Bits32 (opcode, 19, 16);
4847 imm32 = Bits32 (opcode, 7, 0);
4848
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004849 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004850 index = BitIsSet (opcode, 10);
4851 add = BitIsSet (opcode, 9);
4852 wback = BitIsSet (opcode, 8);
4853
4854 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4855 if ((BadReg (t)) || (wback && (n == t)))
4856 return false;
4857 break;
4858
4859 default:
4860 return false;
4861 }
4862
4863 addr_t offset_addr;
4864 addr_t address;
4865 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4866 if (!success)
4867 return false;
4868
4869 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4870 if (add)
4871 offset_addr = base_address + imm32;
4872 else
4873 offset_addr = base_address - imm32;
4874
4875 // address = if index then offset_addr else R[n];
4876 if (index)
4877 address = offset_addr;
4878 else
4879 address = base_address;
4880
Caroline Ticecc96eb52011-02-17 19:20:40 +00004881 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004882 Register base_reg;
4883 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4884
4885 Register data_reg;
4886 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4887
4888 EmulateInstruction::Context context;
4889 context.type = eContextRegisterStore;
4890 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4891
4892 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4893 if (!success)
4894 return false;
4895
4896 data = Bits32 (data, 7, 0);
4897
Caroline Ticecc96eb52011-02-17 19:20:40 +00004898 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004899 return false;
4900
4901 // if wback then R[n] = offset_addr;
4902 if (wback)
4903 {
4904 context.type = eContextRegisterLoad;
4905 context.SetAddress (offset_addr);
4906 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4907 return false;
4908 }
4909
4910 }
4911
4912 return true;
4913}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004914
4915// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4916// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4917bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004918EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004919{
4920#if 0
4921 if ConditionPassed() then
4922 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4923 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4924 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4925 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004926 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004927 MemU[address,2] = R[t]<15:0>;
4928 else // Can only occur before ARMv7
4929 MemU[address,2] = bits(16) UNKNOWN;
4930 if wback then R[n] = offset_addr;
4931#endif
4932
4933 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004934
Greg Clayton7bc39082011-03-24 23:53:38 +00004935 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004936 {
4937 uint32_t t;
4938 uint32_t n;
4939 uint32_t m;
4940 bool index;
4941 bool add;
4942 bool wback;
4943 ARM_ShifterType shift_t;
4944 uint32_t shift_n;
4945
4946 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4947 switch (encoding)
4948 {
4949 case eEncodingT1:
4950 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4951 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4952 t = Bits32 (opcode, 2, 0);
4953 n = Bits32 (opcode, 5, 3);
4954 m = Bits32 (opcode, 8, 6);
4955
4956 // index = TRUE; add = TRUE; wback = FALSE;
4957 index = true;
4958 add = true;
4959 wback = false;
4960
4961 // (shift_t, shift_n) = (SRType_LSL, 0);
4962 shift_t = SRType_LSL;
4963 shift_n = 0;
4964
4965 break;
4966
4967 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004968 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004969 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4970 t = Bits32 (opcode, 15, 12);
4971 n = Bits32 (opcode, 19, 16);
4972 m = Bits32 (opcode, 3, 0);
4973 if (n == 15)
4974 return false;
4975
4976 // index = TRUE; add = TRUE; wback = FALSE;
4977 index = true;
4978 add = true;
4979 wback = false;
4980
4981 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4982 shift_t = SRType_LSL;
4983 shift_n = Bits32 (opcode, 5, 4);
4984
4985 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4986 if (BadReg (t) || BadReg (m))
4987 return false;
4988
4989 break;
4990
4991 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004992 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004993 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4994 t = Bits32 (opcode, 15, 12);
4995 n = Bits32 (opcode, 19, 16);
4996 m = Bits32 (opcode, 3, 0);
4997
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004998 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00004999 index = BitIsSet (opcode, 24);
5000 add = BitIsSet (opcode, 23);
5001 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5002
5003 // (shift_t, shift_n) = (SRType_LSL, 0);
5004 shift_t = SRType_LSL;
5005 shift_n = 0;
5006
5007 // if t == 15 || m == 15 then UNPREDICTABLE;
5008 if ((t == 15) || (m == 15))
5009 return false;
5010
5011 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5012 if (wback && ((n == 15) || (n == t)))
5013 return false;
5014
5015 break;
5016
5017 default:
5018 return false;
5019 }
5020
5021 uint32_t Rm = ReadCoreReg (m, &success);
5022 if (!success)
5023 return false;
5024
5025 uint32_t Rn = ReadCoreReg (n, &success);
5026 if (!success)
5027 return false;
5028
5029 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5030 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5031
5032 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5033 addr_t offset_addr;
5034 if (add)
5035 offset_addr = Rn + offset;
5036 else
5037 offset_addr = Rn - offset;
5038
5039 // address = if index then offset_addr else R[n];
5040 addr_t address;
5041 if (index)
5042 address = offset_addr;
5043 else
5044 address = Rn;
5045
5046 EmulateInstruction::Context context;
5047 context.type = eContextRegisterStore;
5048 Register base_reg;
5049 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5050 Register offset_reg;
5051 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5052
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005053 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005054 if (UnalignedSupport() || BitIsClear (address, 0))
5055 {
5056 // MemU[address,2] = R[t]<15:0>;
5057 uint32_t Rt = ReadCoreReg (t, &success);
5058 if (!success)
5059 return false;
5060
5061 EmulateInstruction::Context context;
5062 context.type = eContextRegisterStore;
5063 Register base_reg;
5064 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5065 Register offset_reg;
5066 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5067 Register data_reg;
5068 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5069 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5070
5071 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5072 return false;
5073 }
5074 else // Can only occur before ARMv7
5075 {
5076 // MemU[address,2] = bits(16) UNKNOWN;
5077 }
5078
5079 // if wback then R[n] = offset_addr;
5080 if (wback)
5081 {
5082 context.type = eContextAdjustBaseRegister;
5083 context.SetAddress (offset_addr);
5084 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5085 return false;
5086 }
5087 }
5088
5089 return true;
5090}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005091
Johnny Chen157b9592011-02-18 21:13:05 +00005092// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5093// and writes the result to the destination register. It can optionally update the condition flags
5094// based on the result.
5095bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005096EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005097{
5098#if 0
5099 // ARM pseudo code...
5100 if ConditionPassed() then
5101 EncodingSpecificOperations();
5102 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5103 if d == 15 then // Can only occur for ARM encoding
5104 ALUWritePC(result); // setflags is always FALSE here
5105 else
5106 R[d] = result;
5107 if setflags then
5108 APSR.N = result<31>;
5109 APSR.Z = IsZeroBit(result);
5110 APSR.C = carry;
5111 APSR.V = overflow;
5112#endif
5113
5114 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005115
Greg Clayton7bc39082011-03-24 23:53:38 +00005116 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005117 {
5118 uint32_t Rd, Rn;
5119 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5120 bool setflags;
5121 switch (encoding)
5122 {
5123 case eEncodingT1:
5124 Rd = Bits32(opcode, 11, 8);
5125 Rn = Bits32(opcode, 19, 16);
5126 setflags = BitIsSet(opcode, 20);
5127 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5128 if (BadReg(Rd) || BadReg(Rn))
5129 return false;
5130 break;
5131 case eEncodingA1:
5132 Rd = Bits32(opcode, 15, 12);
5133 Rn = Bits32(opcode, 19, 16);
5134 setflags = BitIsSet(opcode, 20);
5135 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005136
Johnny Chen157b9592011-02-18 21:13:05 +00005137 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005138 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005139 break;
5140 default:
5141 return false;
5142 }
5143
5144 // Read the first operand.
5145 int32_t val1 = ReadCoreReg(Rn, &success);
5146 if (!success)
5147 return false;
5148
5149 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5150
5151 EmulateInstruction::Context context;
5152 context.type = EmulateInstruction::eContextImmediate;
5153 context.SetNoArgs ();
5154
5155 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5156 return false;
5157 }
5158 return true;
5159}
5160
5161// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5162// register value, and writes the result to the destination register. It can optionally update the
5163// condition flags based on the result.
5164bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005165EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005166{
5167#if 0
5168 // ARM pseudo code...
5169 if ConditionPassed() then
5170 EncodingSpecificOperations();
5171 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5172 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5173 if d == 15 then // Can only occur for ARM encoding
5174 ALUWritePC(result); // setflags is always FALSE here
5175 else
5176 R[d] = result;
5177 if setflags then
5178 APSR.N = result<31>;
5179 APSR.Z = IsZeroBit(result);
5180 APSR.C = carry;
5181 APSR.V = overflow;
5182#endif
5183
5184 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005185
Greg Clayton7bc39082011-03-24 23:53:38 +00005186 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005187 {
5188 uint32_t Rd, Rn, Rm;
5189 ARM_ShifterType shift_t;
5190 uint32_t shift_n; // the shift applied to the value read from Rm
5191 bool setflags;
5192 switch (encoding)
5193 {
5194 case eEncodingT1:
5195 Rd = Rn = Bits32(opcode, 2, 0);
5196 Rm = Bits32(opcode, 5, 3);
5197 setflags = !InITBlock();
5198 shift_t = SRType_LSL;
5199 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005200 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005201 case eEncodingT2:
5202 Rd = Bits32(opcode, 11, 8);
5203 Rn = Bits32(opcode, 19, 16);
5204 Rm = Bits32(opcode, 3, 0);
5205 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005206 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005207 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5208 return false;
5209 break;
5210 case eEncodingA1:
5211 Rd = Bits32(opcode, 15, 12);
5212 Rn = Bits32(opcode, 19, 16);
5213 Rm = Bits32(opcode, 3, 0);
5214 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005215 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005216
Johnny Chen157b9592011-02-18 21:13:05 +00005217 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005218 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005219 break;
5220 default:
5221 return false;
5222 }
5223
5224 // Read the first operand.
5225 int32_t val1 = ReadCoreReg(Rn, &success);
5226 if (!success)
5227 return false;
5228
5229 // Read the second operand.
5230 int32_t val2 = ReadCoreReg(Rm, &success);
5231 if (!success)
5232 return false;
5233
5234 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5235 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5236
5237 EmulateInstruction::Context context;
5238 context.type = EmulateInstruction::eContextImmediate;
5239 context.SetNoArgs ();
5240
5241 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5242 return false;
5243 }
5244 return true;
5245}
5246
Johnny Chena695f952011-02-23 21:24:25 +00005247// This instruction adds an immediate value to the PC value to form a PC-relative address,
5248// and writes the result to the destination register.
5249bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005250EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005251{
5252#if 0
5253 // ARM pseudo code...
5254 if ConditionPassed() then
5255 EncodingSpecificOperations();
5256 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5257 if d == 15 then // Can only occur for ARM encodings
5258 ALUWritePC(result);
5259 else
5260 R[d] = result;
5261#endif
5262
5263 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005264
Greg Clayton7bc39082011-03-24 23:53:38 +00005265 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005266 {
5267 uint32_t Rd;
5268 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5269 bool add;
5270 switch (encoding)
5271 {
5272 case eEncodingT1:
5273 Rd = Bits32(opcode, 10, 8);
5274 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5275 break;
5276 case eEncodingT2:
5277 case eEncodingT3:
5278 Rd = Bits32(opcode, 11, 8);
5279 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5280 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5281 if (BadReg(Rd))
5282 return false;
5283 break;
5284 case eEncodingA1:
5285 case eEncodingA2:
5286 Rd = Bits32(opcode, 15, 12);
5287 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5288 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5289 break;
5290 default:
5291 return false;
5292 }
5293
5294 // Read the PC value.
5295 uint32_t pc = ReadCoreReg(PC_REG, &success);
5296 if (!success)
5297 return false;
5298
5299 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5300
5301 EmulateInstruction::Context context;
5302 context.type = EmulateInstruction::eContextImmediate;
5303 context.SetNoArgs ();
5304
5305 if (!WriteCoreReg(context, result, Rd))
5306 return false;
5307 }
5308 return true;
5309}
5310
Johnny Chene97c0d52011-02-18 19:32:20 +00005311// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5312// to the destination register. It can optionally update the condition flags based on the result.
5313bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005314EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005315{
5316#if 0
5317 // ARM pseudo code...
5318 if ConditionPassed() then
5319 EncodingSpecificOperations();
5320 result = R[n] AND imm32;
5321 if d == 15 then // Can only occur for ARM encoding
5322 ALUWritePC(result); // setflags is always FALSE here
5323 else
5324 R[d] = result;
5325 if setflags then
5326 APSR.N = result<31>;
5327 APSR.Z = IsZeroBit(result);
5328 APSR.C = carry;
5329 // APSR.V unchanged
5330#endif
5331
5332 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005333
Greg Clayton7bc39082011-03-24 23:53:38 +00005334 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005335 {
5336 uint32_t Rd, Rn;
5337 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5338 bool setflags;
5339 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5340 switch (encoding)
5341 {
5342 case eEncodingT1:
5343 Rd = Bits32(opcode, 11, 8);
5344 Rn = Bits32(opcode, 19, 16);
5345 setflags = BitIsSet(opcode, 20);
5346 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005347 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005348 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005349 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005350 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5351 return false;
5352 break;
5353 case eEncodingA1:
5354 Rd = Bits32(opcode, 15, 12);
5355 Rn = Bits32(opcode, 19, 16);
5356 setflags = BitIsSet(opcode, 20);
5357 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005358
Johnny Chene97c0d52011-02-18 19:32:20 +00005359 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005360 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005361 break;
5362 default:
5363 return false;
5364 }
5365
Johnny Chene97c0d52011-02-18 19:32:20 +00005366 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005367 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005368 if (!success)
5369 return false;
5370
5371 uint32_t result = val1 & imm32;
5372
5373 EmulateInstruction::Context context;
5374 context.type = EmulateInstruction::eContextImmediate;
5375 context.SetNoArgs ();
5376
5377 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5378 return false;
5379 }
5380 return true;
5381}
5382
5383// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5384// and writes the result to the destination register. It can optionally update the condition flags
5385// based on the result.
5386bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005387EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005388{
5389#if 0
5390 // ARM pseudo code...
5391 if ConditionPassed() then
5392 EncodingSpecificOperations();
5393 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5394 result = R[n] AND shifted;
5395 if d == 15 then // Can only occur for ARM encoding
5396 ALUWritePC(result); // setflags is always FALSE here
5397 else
5398 R[d] = result;
5399 if setflags then
5400 APSR.N = result<31>;
5401 APSR.Z = IsZeroBit(result);
5402 APSR.C = carry;
5403 // APSR.V unchanged
5404#endif
5405
5406 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005407
Greg Clayton7bc39082011-03-24 23:53:38 +00005408 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005409 {
5410 uint32_t Rd, Rn, Rm;
5411 ARM_ShifterType shift_t;
5412 uint32_t shift_n; // the shift applied to the value read from Rm
5413 bool setflags;
5414 uint32_t carry;
5415 switch (encoding)
5416 {
5417 case eEncodingT1:
5418 Rd = Rn = Bits32(opcode, 2, 0);
5419 Rm = Bits32(opcode, 5, 3);
5420 setflags = !InITBlock();
5421 shift_t = SRType_LSL;
5422 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005423 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005424 case eEncodingT2:
5425 Rd = Bits32(opcode, 11, 8);
5426 Rn = Bits32(opcode, 19, 16);
5427 Rm = Bits32(opcode, 3, 0);
5428 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005429 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005430 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005431 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005432 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005433 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5434 return false;
5435 break;
5436 case eEncodingA1:
5437 Rd = Bits32(opcode, 15, 12);
5438 Rn = Bits32(opcode, 19, 16);
5439 Rm = Bits32(opcode, 3, 0);
5440 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005441 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005442
Johnny Chene97c0d52011-02-18 19:32:20 +00005443 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005444 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005445 break;
5446 default:
5447 return false;
5448 }
5449
Johnny Chene97c0d52011-02-18 19:32:20 +00005450 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005451 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005452 if (!success)
5453 return false;
5454
5455 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005456 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005457 if (!success)
5458 return false;
5459
5460 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5461 uint32_t result = val1 & shifted;
5462
5463 EmulateInstruction::Context context;
5464 context.type = EmulateInstruction::eContextImmediate;
5465 context.SetNoArgs ();
5466
5467 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5468 return false;
5469 }
5470 return true;
5471}
5472
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005473// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5474// immediate value, and writes the result to the destination register. It can optionally update the
5475// condition flags based on the result.
5476bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005477EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005478{
5479#if 0
5480 // ARM pseudo code...
5481 if ConditionPassed() then
5482 EncodingSpecificOperations();
5483 result = R[n] AND NOT(imm32);
5484 if d == 15 then // Can only occur for ARM encoding
5485 ALUWritePC(result); // setflags is always FALSE here
5486 else
5487 R[d] = result;
5488 if setflags then
5489 APSR.N = result<31>;
5490 APSR.Z = IsZeroBit(result);
5491 APSR.C = carry;
5492 // APSR.V unchanged
5493#endif
5494
5495 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005496
Greg Clayton7bc39082011-03-24 23:53:38 +00005497 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005498 {
5499 uint32_t Rd, Rn;
5500 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5501 bool setflags;
5502 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5503 switch (encoding)
5504 {
5505 case eEncodingT1:
5506 Rd = Bits32(opcode, 11, 8);
5507 Rn = Bits32(opcode, 19, 16);
5508 setflags = BitIsSet(opcode, 20);
5509 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5510 if (BadReg(Rd) || BadReg(Rn))
5511 return false;
5512 break;
5513 case eEncodingA1:
5514 Rd = Bits32(opcode, 15, 12);
5515 Rn = Bits32(opcode, 19, 16);
5516 setflags = BitIsSet(opcode, 20);
5517 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005518
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005519 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005520 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005521 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005522 break;
5523 default:
5524 return false;
5525 }
5526
5527 // Read the first operand.
5528 uint32_t val1 = ReadCoreReg(Rn, &success);
5529 if (!success)
5530 return false;
5531
5532 uint32_t result = val1 & ~imm32;
5533
5534 EmulateInstruction::Context context;
5535 context.type = EmulateInstruction::eContextImmediate;
5536 context.SetNoArgs ();
5537
5538 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5539 return false;
5540 }
5541 return true;
5542}
5543
5544// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5545// optionally-shifted register value, and writes the result to the destination register.
5546// It can optionally update the condition flags based on the result.
5547bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005548EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005549{
5550#if 0
5551 // ARM pseudo code...
5552 if ConditionPassed() then
5553 EncodingSpecificOperations();
5554 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5555 result = R[n] AND NOT(shifted);
5556 if d == 15 then // Can only occur for ARM encoding
5557 ALUWritePC(result); // setflags is always FALSE here
5558 else
5559 R[d] = result;
5560 if setflags then
5561 APSR.N = result<31>;
5562 APSR.Z = IsZeroBit(result);
5563 APSR.C = carry;
5564 // APSR.V unchanged
5565#endif
5566
5567 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005568
Greg Clayton7bc39082011-03-24 23:53:38 +00005569 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005570 {
5571 uint32_t Rd, Rn, Rm;
5572 ARM_ShifterType shift_t;
5573 uint32_t shift_n; // the shift applied to the value read from Rm
5574 bool setflags;
5575 uint32_t carry;
5576 switch (encoding)
5577 {
5578 case eEncodingT1:
5579 Rd = Rn = Bits32(opcode, 2, 0);
5580 Rm = Bits32(opcode, 5, 3);
5581 setflags = !InITBlock();
5582 shift_t = SRType_LSL;
5583 shift_n = 0;
5584 break;
5585 case eEncodingT2:
5586 Rd = Bits32(opcode, 11, 8);
5587 Rn = Bits32(opcode, 19, 16);
5588 Rm = Bits32(opcode, 3, 0);
5589 setflags = BitIsSet(opcode, 20);
5590 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5591 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5592 return false;
5593 break;
5594 case eEncodingA1:
5595 Rd = Bits32(opcode, 15, 12);
5596 Rn = Bits32(opcode, 19, 16);
5597 Rm = Bits32(opcode, 3, 0);
5598 setflags = BitIsSet(opcode, 20);
5599 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005600
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005601 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005602 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005603 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005604 break;
5605 default:
5606 return false;
5607 }
5608
5609 // Read the first operand.
5610 uint32_t val1 = ReadCoreReg(Rn, &success);
5611 if (!success)
5612 return false;
5613
5614 // Read the second operand.
5615 uint32_t val2 = ReadCoreReg(Rm, &success);
5616 if (!success)
5617 return false;
5618
5619 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5620 uint32_t result = val1 & ~shifted;
5621
5622 EmulateInstruction::Context context;
5623 context.type = EmulateInstruction::eContextImmediate;
5624 context.SetNoArgs ();
5625
5626 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5627 return false;
5628 }
5629 return true;
5630}
5631
Caroline Tice4d729c52011-02-18 00:55:53 +00005632// 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 +00005633// 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 +00005634bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005635EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005636{
5637#if 0
5638 if ConditionPassed() then
5639 EncodingSpecificOperations();
5640 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5641 address = if index then offset_addr else R[n];
5642 data = MemU[address,4];
5643 if wback then R[n] = offset_addr;
5644 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005645 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5646 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005647 R[t] = data;
5648 else // Can only apply before ARMv7
5649 R[t] = ROR(data, 8*UInt(address<1:0>));
5650#endif
5651
5652 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005653
Greg Clayton7bc39082011-03-24 23:53:38 +00005654 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005655 {
5656 const uint32_t addr_byte_size = GetAddressByteSize();
5657
5658 uint32_t t;
5659 uint32_t n;
5660 uint32_t imm32;
5661 bool index;
5662 bool add;
5663 bool wback;
5664
5665 switch (encoding)
5666 {
5667 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005668 // if Rn == '1111' then SEE LDR (literal);
5669 // if P == '0' && W == '1' then SEE LDRT;
5670 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005671 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5672 t = Bits32 (opcode, 15, 12);
5673 n = Bits32 (opcode, 19, 16);
5674 imm32 = Bits32 (opcode, 11, 0);
5675
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005676 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5677 index = BitIsSet (opcode, 24);
5678 add = BitIsSet (opcode, 23);
5679 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005680
5681 // if wback && n == t then UNPREDICTABLE;
5682 if (wback && (n == t))
5683 return false;
5684
5685 break;
5686
5687 default:
5688 return false;
5689 }
5690
5691 addr_t address;
5692 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005693 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005694 if (!success)
5695 return false;
5696
5697 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5698 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005699 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005700 else
5701 offset_addr = base_address - imm32;
5702
5703 // address = if index then offset_addr else R[n];
5704 if (index)
5705 address = offset_addr;
5706 else
5707 address = base_address;
5708
5709 // data = MemU[address,4];
5710
5711 Register base_reg;
5712 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5713
5714 EmulateInstruction::Context context;
5715 context.type = eContextRegisterLoad;
5716 context.SetRegisterPlusOffset (base_reg, address - base_address);
5717
5718 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5719 if (!success)
5720 return false;
5721
5722 // if wback then R[n] = offset_addr;
5723 if (wback)
5724 {
5725 context.type = eContextAdjustBaseRegister;
5726 context.SetAddress (offset_addr);
5727 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5728 return false;
5729 }
5730
5731 // if t == 15 then
5732 if (t == 15)
5733 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005734 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005735 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5736 {
5737 // LoadWritePC (data);
5738 context.type = eContextRegisterLoad;
5739 context.SetRegisterPlusOffset (base_reg, address - base_address);
5740 LoadWritePC (context, data);
5741 }
5742 else
5743 return false;
5744 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005745 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005746 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5747 {
5748 // R[t] = data;
5749 context.type = eContextRegisterLoad;
5750 context.SetRegisterPlusOffset (base_reg, address - base_address);
5751 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5752 return false;
5753 }
5754 // else // Can only apply before ARMv7
5755 else
5756 {
5757 // R[t] = ROR(data, 8*UInt(address<1:0>));
5758 data = ROR (data, Bits32 (address, 1, 0));
5759 context.type = eContextRegisterLoad;
5760 context.SetImmediate (data);
5761 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5762 return false;
5763 }
5764
5765 }
5766 return true;
5767}
5768
Caroline Ticefe479112011-02-18 18:52:37 +00005769// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5770// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5771bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005772EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005773{
5774#if 0
5775 if ConditionPassed() then
5776 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5777 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5778 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5779 address = if index then offset_addr else R[n];
5780 data = MemU[address,4];
5781 if wback then R[n] = offset_addr;
5782 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005783 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5784 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005785 R[t] = data;
5786 else // Can only apply before ARMv7
5787 if CurrentInstrSet() == InstrSet_ARM then
5788 R[t] = ROR(data, 8*UInt(address<1:0>));
5789 else
5790 R[t] = bits(32) UNKNOWN;
5791#endif
5792
5793 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005794
Greg Clayton7bc39082011-03-24 23:53:38 +00005795 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005796 {
5797 const uint32_t addr_byte_size = GetAddressByteSize();
5798
5799 uint32_t t;
5800 uint32_t n;
5801 uint32_t m;
5802 bool index;
5803 bool add;
5804 bool wback;
5805 ARM_ShifterType shift_t;
5806 uint32_t shift_n;
5807
5808 switch (encoding)
5809 {
5810 case eEncodingT1:
5811 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5812 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5813 t = Bits32 (opcode, 2, 0);
5814 n = Bits32 (opcode, 5, 3);
5815 m = Bits32 (opcode, 8, 6);
5816
5817 // index = TRUE; add = TRUE; wback = FALSE;
5818 index = true;
5819 add = true;
5820 wback = false;
5821
5822 // (shift_t, shift_n) = (SRType_LSL, 0);
5823 shift_t = SRType_LSL;
5824 shift_n = 0;
5825
5826 break;
5827
5828 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005829 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005830 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5831 t = Bits32 (opcode, 15, 12);
5832 n = Bits32 (opcode, 19, 16);
5833 m = Bits32 (opcode, 3, 0);
5834
5835 // index = TRUE; add = TRUE; wback = FALSE;
5836 index = true;
5837 add = true;
5838 wback = false;
5839
5840 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5841 shift_t = SRType_LSL;
5842 shift_n = Bits32 (opcode, 5, 4);
5843
5844 // if BadReg(m) then UNPREDICTABLE;
5845 if (BadReg (m))
5846 return false;
5847
5848 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5849 if ((t == 15) && InITBlock() && !LastInITBlock())
5850 return false;
5851
5852 break;
5853
5854 case eEncodingA1:
5855 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005856 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005857 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5858 t = Bits32 (opcode, 15, 12);
5859 n = Bits32 (opcode, 19, 16);
5860 m = Bits32 (opcode, 3, 0);
5861
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005862 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005863 index = BitIsSet (opcode, 24);
5864 add = BitIsSet (opcode, 23);
5865 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5866
5867 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5868 uint32_t type = Bits32 (opcode, 6, 5);
5869 uint32_t imm5 = Bits32 (opcode, 11, 7);
5870 shift_n = DecodeImmShift (type, imm5, shift_t);
5871
5872 // if m == 15 then UNPREDICTABLE;
5873 if (m == 15)
5874 return false;
5875
5876 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5877 if (wback && ((n == 15) || (n == t)))
5878 return false;
5879 }
5880 break;
5881
5882
5883 default:
5884 return false;
5885 }
5886
5887 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5888 if (!success)
5889 return false;
5890
5891 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5892 if (!success)
5893 return false;
5894
5895 addr_t offset_addr;
5896 addr_t address;
5897
5898 // 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 +00005899 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005900
5901 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5902 if (add)
5903 offset_addr = Rn + offset;
5904 else
5905 offset_addr = Rn - offset;
5906
5907 // address = if index then offset_addr else R[n];
5908 if (index)
5909 address = offset_addr;
5910 else
5911 address = Rn;
5912
5913 // data = MemU[address,4];
5914 Register base_reg;
5915 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5916
5917 EmulateInstruction::Context context;
5918 context.type = eContextRegisterLoad;
5919 context.SetRegisterPlusOffset (base_reg, address - Rn);
5920
5921 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5922 if (!success)
5923 return false;
5924
5925 // if wback then R[n] = offset_addr;
5926 if (wback)
5927 {
5928 context.type = eContextAdjustBaseRegister;
5929 context.SetAddress (offset_addr);
5930 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5931 return false;
5932 }
5933
5934 // if t == 15 then
5935 if (t == 15)
5936 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005937 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005938 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5939 {
5940 context.type = eContextRegisterLoad;
5941 context.SetRegisterPlusOffset (base_reg, address - Rn);
5942 LoadWritePC (context, data);
5943 }
5944 else
5945 return false;
5946 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005947 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005948 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5949 {
5950 // R[t] = data;
5951 context.type = eContextRegisterLoad;
5952 context.SetRegisterPlusOffset (base_reg, address - Rn);
5953 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5954 return false;
5955 }
5956 else // Can only apply before ARMv7
5957 {
5958 // if CurrentInstrSet() == InstrSet_ARM then
5959 if (CurrentInstrSet () == eModeARM)
5960 {
5961 // R[t] = ROR(data, 8*UInt(address<1:0>));
5962 data = ROR (data, Bits32 (address, 1, 0));
5963 context.type = eContextRegisterLoad;
5964 context.SetImmediate (data);
5965 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5966 return false;
5967 }
5968 else
5969 {
5970 // R[t] = bits(32) UNKNOWN;
5971 WriteBits32Unknown (t);
5972 }
5973 }
5974 }
5975 return true;
5976}
Caroline Tice21b604b2011-02-18 21:06:04 +00005977
5978// LDRB (immediate, Thumb)
5979bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005980EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00005981{
5982#if 0
5983 if ConditionPassed() then
5984 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5985 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5986 address = if index then offset_addr else R[n];
5987 R[t] = ZeroExtend(MemU[address,1], 32);
5988 if wback then R[n] = offset_addr;
5989#endif
5990
5991 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00005992
Greg Clayton7bc39082011-03-24 23:53:38 +00005993 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00005994 {
5995 uint32_t t;
5996 uint32_t n;
5997 uint32_t imm32;
5998 bool index;
5999 bool add;
6000 bool wback;
6001
6002 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6003 switch (encoding)
6004 {
6005 case eEncodingT1:
6006 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6007 t = Bits32 (opcode, 2, 0);
6008 n = Bits32 (opcode, 5, 3);
6009 imm32 = Bits32 (opcode, 10, 6);
6010
6011 // index = TRUE; add = TRUE; wback = FALSE;
6012 index = true;
6013 add = true;
6014 wback= false;
6015
6016 break;
6017
6018 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006019 // if Rt == '1111' then SEE PLD;
6020 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006021 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6022 t = Bits32 (opcode, 15, 12);
6023 n = Bits32 (opcode, 19, 16);
6024 imm32 = Bits32 (opcode, 11, 0);
6025
6026 // index = TRUE; add = TRUE; wback = FALSE;
6027 index = true;
6028 add = true;
6029 wback = false;
6030
6031 // if t == 13 then UNPREDICTABLE;
6032 if (t == 13)
6033 return false;
6034
6035 break;
6036
6037 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006038 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6039 // if Rn == '1111' then SEE LDRB (literal);
6040 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6041 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006042 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6043 return false;
6044
6045 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6046 t = Bits32 (opcode, 15, 12);
6047 n = Bits32 (opcode, 19, 16);
6048 imm32 = Bits32 (opcode, 7, 0);
6049
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006050 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006051 index = BitIsSet (opcode, 10);
6052 add = BitIsSet (opcode, 9);
6053 wback = BitIsSet (opcode, 8);
6054
6055 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6056 if (BadReg (t) || (wback && (n == t)))
6057 return false;
6058
6059 break;
6060
6061 default:
6062 return false;
6063 }
6064
6065 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6066 if (!success)
6067 return false;
6068
6069 addr_t address;
6070 addr_t offset_addr;
6071
6072 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6073 if (add)
6074 offset_addr = Rn + imm32;
6075 else
6076 offset_addr = Rn - imm32;
6077
6078 // address = if index then offset_addr else R[n];
6079 if (index)
6080 address = offset_addr;
6081 else
6082 address = Rn;
6083
6084 // R[t] = ZeroExtend(MemU[address,1], 32);
6085 Register base_reg;
6086 Register data_reg;
6087 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6088 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6089
6090 EmulateInstruction::Context context;
6091 context.type = eContextRegisterLoad;
6092 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6093
6094 uint64_t data = MemURead (context, address, 1, 0, &success);
6095 if (!success)
6096 return false;
6097
6098 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6099 return false;
6100
6101 // if wback then R[n] = offset_addr;
6102 if (wback)
6103 {
6104 context.type = eContextAdjustBaseRegister;
6105 context.SetAddress (offset_addr);
6106 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6107 return false;
6108 }
6109 }
6110 return true;
6111}
Caroline Ticef55261f2011-02-18 22:24:22 +00006112
6113// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6114// zero-extends it to form a 32-bit word and writes it to a register.
6115bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006116EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006117{
6118#if 0
6119 if ConditionPassed() then
6120 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6121 base = Align(PC,4);
6122 address = if add then (base + imm32) else (base - imm32);
6123 R[t] = ZeroExtend(MemU[address,1], 32);
6124#endif
6125
6126 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006127
Greg Clayton7bc39082011-03-24 23:53:38 +00006128 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006129 {
6130 uint32_t t;
6131 uint32_t imm32;
6132 bool add;
6133 switch (encoding)
6134 {
6135 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006136 // if Rt == '1111' then SEE PLD;
6137 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006138 t = Bits32 (opcode, 15, 12);
6139 imm32 = Bits32 (opcode, 11, 0);
6140 add = BitIsSet (opcode, 23);
6141
6142 // if t == 13 then UNPREDICTABLE;
6143 if (t == 13)
6144 return false;
6145
6146 break;
6147
6148 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006149 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006150 t = Bits32 (opcode, 15, 12);
6151 imm32 = Bits32 (opcode, 11, 0);
6152 add = BitIsSet (opcode, 23);
6153
6154 // if t == 15 then UNPREDICTABLE;
6155 if (t == 15)
6156 return false;
6157 break;
6158
6159 default:
6160 return false;
6161 }
6162
6163 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006164 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006165 if (!success)
6166 return false;
6167
6168 uint32_t base = AlignPC (pc_val);
6169
6170 addr_t address;
6171 // address = if add then (base + imm32) else (base - imm32);
6172 if (add)
6173 address = base + imm32;
6174 else
6175 address = base - imm32;
6176
6177 // R[t] = ZeroExtend(MemU[address,1], 32);
6178 EmulateInstruction::Context context;
6179 context.type = eContextRelativeBranchImmediate;
6180 context.SetImmediate (address - base);
6181
6182 uint64_t data = MemURead (context, address, 1, 0, &success);
6183 if (!success)
6184 return false;
6185
6186 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6187 return false;
6188 }
6189 return true;
6190}
Caroline Tice30fec122011-02-18 23:52:21 +00006191
6192// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6193// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6194// optionally be shifted.
6195bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006196EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006197{
6198#if 0
6199 if ConditionPassed() then
6200 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6201 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6202 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6203 address = if index then offset_addr else R[n];
6204 R[t] = ZeroExtend(MemU[address,1],32);
6205 if wback then R[n] = offset_addr;
6206#endif
6207
6208 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006209
Greg Clayton7bc39082011-03-24 23:53:38 +00006210 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006211 {
6212 uint32_t t;
6213 uint32_t n;
6214 uint32_t m;
6215 bool index;
6216 bool add;
6217 bool wback;
6218 ARM_ShifterType shift_t;
6219 uint32_t shift_n;
6220
6221 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6222 switch (encoding)
6223 {
6224 case eEncodingT1:
6225 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6226 t = Bits32 (opcode, 2, 0);
6227 n = Bits32 (opcode, 5, 3);
6228 m = Bits32 (opcode, 8, 6);
6229
6230 // index = TRUE; add = TRUE; wback = FALSE;
6231 index = true;
6232 add = true;
6233 wback = false;
6234
6235 // (shift_t, shift_n) = (SRType_LSL, 0);
6236 shift_t = SRType_LSL;
6237 shift_n = 0;
6238 break;
6239
6240 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006241 // if Rt == '1111' then SEE PLD;
6242 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006243 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6244 t = Bits32 (opcode, 15, 12);
6245 n = Bits32 (opcode, 19, 16);
6246 m = Bits32 (opcode, 3, 0);
6247
6248 // index = TRUE; add = TRUE; wback = FALSE;
6249 index = true;
6250 add = true;
6251 wback = false;
6252
6253 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6254 shift_t = SRType_LSL;
6255 shift_n = Bits32 (opcode, 5, 4);
6256
6257 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6258 if ((t == 13) || BadReg (m))
6259 return false;
6260 break;
6261
6262 case eEncodingA1:
6263 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006264 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006265 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6266 t = Bits32 (opcode, 15, 12);
6267 n = Bits32 (opcode, 19, 16);
6268 m = Bits32 (opcode, 3, 0);
6269
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006270 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006271 index = BitIsSet (opcode, 24);
6272 add = BitIsSet (opcode, 23);
6273 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6274
6275 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6276 uint32_t type = Bits32 (opcode, 6, 5);
6277 uint32_t imm5 = Bits32 (opcode, 11, 7);
6278 shift_n = DecodeImmShift (type, imm5, shift_t);
6279
6280 // if t == 15 || m == 15 then UNPREDICTABLE;
6281 if ((t == 15) || (m == 15))
6282 return false;
6283
6284 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6285 if (wback && ((n == 15) || (n == t)))
6286 return false;
6287 }
6288 break;
6289
6290 default:
6291 return false;
6292 }
6293
6294 addr_t offset_addr;
6295 addr_t address;
6296
6297 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6298 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6299 if (!success)
6300 return false;
6301
6302 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6303
6304 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6305 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6306 if (!success)
6307 return false;
6308
6309 if (add)
6310 offset_addr = Rn + offset;
6311 else
6312 offset_addr = Rn - offset;
6313
6314 // address = if index then offset_addr else R[n];
6315 if (index)
6316 address = offset_addr;
6317 else
6318 address = Rn;
6319
6320 // R[t] = ZeroExtend(MemU[address,1],32);
6321 Register base_reg;
6322 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6323
6324 EmulateInstruction::Context context;
6325 context.type = eContextRegisterLoad;
6326 context.SetRegisterPlusOffset (base_reg, address - Rn);
6327
6328 uint64_t data = MemURead (context, address, 1, 0, &success);
6329 if (!success)
6330 return false;
6331
6332 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6333 return false;
6334
6335 // if wback then R[n] = offset_addr;
6336 if (wback)
6337 {
6338 context.type = eContextAdjustBaseRegister;
6339 context.SetAddress (offset_addr);
6340 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6341 return false;
6342 }
6343 }
6344 return true;
6345}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006346
6347// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6348// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6349// post-indexed, or pre-indexed addressing.
6350bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006351EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006352{
6353#if 0
6354 if ConditionPassed() then
6355 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6356 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6357 address = if index then offset_addr else R[n];
6358 data = MemU[address,2];
6359 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006360 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006361 R[t] = ZeroExtend(data, 32);
6362 else // Can only apply before ARMv7
6363 R[t] = bits(32) UNKNOWN;
6364#endif
6365
6366
6367 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006368
Greg Clayton7bc39082011-03-24 23:53:38 +00006369 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006370 {
6371 uint32_t t;
6372 uint32_t n;
6373 uint32_t imm32;
6374 bool index;
6375 bool add;
6376 bool wback;
6377
6378 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6379 switch (encoding)
6380 {
6381 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006382 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006383 t = Bits32 (opcode, 2, 0);
6384 n = Bits32 (opcode, 5, 3);
6385 imm32 = Bits32 (opcode, 10, 6) << 1;
6386
6387 // index = TRUE; add = TRUE; wback = FALSE;
6388 index = true;
6389 add = true;
6390 wback = false;
6391
6392 break;
6393
6394 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006395 // if Rt == '1111' then SEE "Unallocated memory hints";
6396 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006397 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6398 t = Bits32 (opcode, 15, 12);
6399 n = Bits32 (opcode, 19, 16);
6400 imm32 = Bits32 (opcode, 11, 0);
6401
6402 // index = TRUE; add = TRUE; wback = FALSE;
6403 index = true;
6404 add = true;
6405 wback = false;
6406
6407 // if t == 13 then UNPREDICTABLE;
6408 if (t == 13)
6409 return false;
6410 break;
6411
6412 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006413 // if Rn == '1111' then SEE LDRH (literal);
6414 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6415 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6416 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006417 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6418 return false;
6419
6420 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6421 t = Bits32 (opcode, 15, 12);
6422 n = Bits32 (opcode, 19, 16);
6423 imm32 = Bits32 (opcode, 7, 0);
6424
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006425 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006426 index = BitIsSet (opcode, 10);
6427 add = BitIsSet (opcode, 9);
6428 wback = BitIsSet (opcode, 8);
6429
6430 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6431 if (BadReg (t) || (wback && (n == t)))
6432 return false;
6433 break;
6434
6435 default:
6436 return false;
6437 }
6438
6439 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6440 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6441 if (!success)
6442 return false;
6443
6444 addr_t offset_addr;
6445 addr_t address;
6446
6447 if (add)
6448 offset_addr = Rn + imm32;
6449 else
6450 offset_addr = Rn - imm32;
6451
6452 // address = if index then offset_addr else R[n];
6453 if (index)
6454 address = offset_addr;
6455 else
6456 address = Rn;
6457
6458 // data = MemU[address,2];
6459 Register base_reg;
6460 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6461
6462 EmulateInstruction::Context context;
6463 context.type = eContextRegisterLoad;
6464 context.SetRegisterPlusOffset (base_reg, address - Rn);
6465
6466 uint64_t data = MemURead (context, address, 2, 0, &success);
6467 if (!success)
6468 return false;
6469
6470 // if wback then R[n] = offset_addr;
6471 if (wback)
6472 {
6473 context.type = eContextAdjustBaseRegister;
6474 context.SetAddress (offset_addr);
6475 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6476 return false;
6477 }
6478
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006479 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006480 if (UnalignedSupport () || BitIsClear (address, 0))
6481 {
6482 // R[t] = ZeroExtend(data, 32);
6483 context.type = eContextRegisterLoad;
6484 context.SetRegisterPlusOffset (base_reg, address - Rn);
6485 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6486 return false;
6487 }
6488 else // Can only apply before ARMv7
6489 {
6490 // R[t] = bits(32) UNKNOWN;
6491 WriteBits32Unknown (t);
6492 }
6493 }
6494 return true;
6495}
Caroline Ticefe479112011-02-18 18:52:37 +00006496
Caroline Tice952b5382011-02-28 23:15:24 +00006497// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6498// zero-extends it to form a 32-bit word, and writes it to a register.
6499bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006500EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006501{
6502#if 0
6503 if ConditionPassed() then
6504 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6505 base = Align(PC,4);
6506 address = if add then (base + imm32) else (base - imm32);
6507 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006508 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006509 R[t] = ZeroExtend(data, 32);
6510 else // Can only apply before ARMv7
6511 R[t] = bits(32) UNKNOWN;
6512#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006513
Caroline Tice952b5382011-02-28 23:15:24 +00006514 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006515
Greg Clayton7bc39082011-03-24 23:53:38 +00006516 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006517 {
6518 uint32_t t;
6519 uint32_t imm32;
6520 bool add;
6521
6522 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6523 switch (encoding)
6524 {
6525 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006526 // if Rt == '1111' then SEE "Unallocated memory hints";
6527 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006528 t = Bits32 (opcode, 15, 12);
6529 imm32 = Bits32 (opcode, 11, 0);
6530 add = BitIsSet (opcode, 23);
6531
6532 // if t == 13 then UNPREDICTABLE;
6533 if (t == 13)
6534 return false;
6535
6536 break;
6537
6538 case eEncodingA1:
6539 {
6540 uint32_t imm4H = Bits32 (opcode, 11, 8);
6541 uint32_t imm4L = Bits32 (opcode, 3, 0);
6542
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006543 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006544 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006545 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006546 add = BitIsSet (opcode, 23);
6547
6548 // if t == 15 then UNPREDICTABLE;
6549 if (t == 15)
6550 return false;
6551 break;
6552 }
6553
6554 default:
6555 return false;
6556 }
6557
6558 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006559 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006560 if (!success)
6561 return false;
6562
6563 addr_t base = AlignPC (pc_value);
6564 addr_t address;
6565
6566 // address = if add then (base + imm32) else (base - imm32);
6567 if (add)
6568 address = base + imm32;
6569 else
6570 address = base - imm32;
6571
6572 // data = MemU[address,2];
6573 Register base_reg;
6574 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6575
6576 EmulateInstruction::Context context;
6577 context.type = eContextRegisterLoad;
6578 context.SetRegisterPlusOffset (base_reg, address - base);
6579
6580 uint64_t data = MemURead (context, address, 2, 0, &success);
6581 if (!success)
6582 return false;
6583
6584
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006585 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006586 if (UnalignedSupport () || BitIsClear (address, 0))
6587 {
6588 // R[t] = ZeroExtend(data, 32);
6589 context.type = eContextRegisterLoad;
6590 context.SetRegisterPlusOffset (base_reg, address - base);
6591 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6592 return false;
6593
6594 }
6595 else // Can only apply before ARMv7
6596 {
6597 // R[t] = bits(32) UNKNOWN;
6598 WriteBits32Unknown (t);
6599 }
6600 }
6601 return true;
6602}
6603
Caroline Tice0e6bc952011-03-01 18:00:42 +00006604// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6605// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6606// be shifted left by 0, 1, 2, or 3 bits.
6607bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006608EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006609{
6610#if 0
6611 if ConditionPassed() then
6612 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6613 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6614 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6615 address = if index then offset_addr else R[n];
6616 data = MemU[address,2];
6617 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006618 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006619 R[t] = ZeroExtend(data, 32);
6620 else // Can only apply before ARMv7
6621 R[t] = bits(32) UNKNOWN;
6622#endif
6623
6624 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006625
Greg Clayton7bc39082011-03-24 23:53:38 +00006626 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006627 {
6628 uint32_t t;
6629 uint32_t n;
6630 uint32_t m;
6631 bool index;
6632 bool add;
6633 bool wback;
6634 ARM_ShifterType shift_t;
6635 uint32_t shift_n;
6636
6637 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6638 switch (encoding)
6639 {
6640 case eEncodingT1:
6641 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6642 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6643 t = Bits32 (opcode, 2, 0);
6644 n = Bits32 (opcode, 5, 3);
6645 m = Bits32 (opcode, 8, 6);
6646
6647 // index = TRUE; add = TRUE; wback = FALSE;
6648 index = true;
6649 add = true;
6650 wback = false;
6651
6652 // (shift_t, shift_n) = (SRType_LSL, 0);
6653 shift_t = SRType_LSL;
6654 shift_n = 0;
6655
6656 break;
6657
6658 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006659 // if Rn == '1111' then SEE LDRH (literal);
6660 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006661 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6662 t = Bits32 (opcode, 15, 12);
6663 n = Bits32 (opcode, 19, 16);
6664 m = Bits32 (opcode, 3, 0);
6665
6666 // index = TRUE; add = TRUE; wback = FALSE;
6667 index = true;
6668 add = true;
6669 wback = false;
6670
6671 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6672 shift_t = SRType_LSL;
6673 shift_n = Bits32 (opcode, 5, 4);
6674
6675 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6676 if ((t == 13) || BadReg (m))
6677 return false;
6678 break;
6679
6680 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006681 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006682 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6683 t = Bits32 (opcode, 15, 12);
6684 n = Bits32 (opcode, 19, 16);
6685 m = Bits32 (opcode, 3, 0);
6686
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006687 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006688 index = BitIsSet (opcode, 24);
6689 add = BitIsSet (opcode, 23);
6690 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6691
6692 // (shift_t, shift_n) = (SRType_LSL, 0);
6693 shift_t = SRType_LSL;
6694 shift_n = 0;
6695
6696 // if t == 15 || m == 15 then UNPREDICTABLE;
6697 if ((t == 15) || (m == 15))
6698 return false;
6699
6700 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6701 if (wback && ((n == 15) || (n == t)))
6702 return false;
6703
6704 break;
6705
6706 default:
6707 return false;
6708 }
6709
6710 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6711
6712 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6713 if (!success)
6714 return false;
6715
6716 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6717
6718 addr_t offset_addr;
6719 addr_t address;
6720
6721 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6722 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6723 if (!success)
6724 return false;
6725
6726 if (add)
6727 offset_addr = Rn + offset;
6728 else
6729 offset_addr = Rn - offset;
6730
6731 // address = if index then offset_addr else R[n];
6732 if (index)
6733 address = offset_addr;
6734 else
6735 address = Rn;
6736
6737 // data = MemU[address,2];
6738 Register base_reg;
6739 Register offset_reg;
6740 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6741 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6742
6743 EmulateInstruction::Context context;
6744 context.type = eContextRegisterLoad;
6745 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6746 uint64_t data = MemURead (context, address, 2, 0, &success);
6747 if (!success)
6748 return false;
6749
6750 // if wback then R[n] = offset_addr;
6751 if (wback)
6752 {
6753 context.type = eContextAdjustBaseRegister;
6754 context.SetAddress (offset_addr);
6755 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6756 return false;
6757 }
6758
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006759 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006760 if (UnalignedSupport() || BitIsClear (address, 0))
6761 {
6762 // R[t] = ZeroExtend(data, 32);
6763 context.type = eContextRegisterLoad;
6764 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6765 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6766 return false;
6767 }
6768 else // Can only apply before ARMv7
6769 {
6770 // R[t] = bits(32) UNKNOWN;
6771 WriteBits32Unknown (t);
6772 }
6773 }
6774 return true;
6775}
6776
Caroline Ticea5e28af2011-03-01 21:53:03 +00006777// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6778// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6779// or pre-indexed addressing.
6780bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006781EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006782{
6783#if 0
6784 if ConditionPassed() then
6785 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6786 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6787 address = if index then offset_addr else R[n];
6788 R[t] = SignExtend(MemU[address,1], 32);
6789 if wback then R[n] = offset_addr;
6790#endif
6791
6792 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006793
Greg Clayton7bc39082011-03-24 23:53:38 +00006794 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006795 {
6796 uint32_t t;
6797 uint32_t n;
6798 uint32_t imm32;
6799 bool index;
6800 bool add;
6801 bool wback;
6802
6803 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6804 switch (encoding)
6805 {
6806 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006807 // if Rt == '1111' then SEE PLI;
6808 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006809 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6810 t = Bits32 (opcode, 15, 12);
6811 n = Bits32 (opcode, 19, 16);
6812 imm32 = Bits32 (opcode, 11, 0);
6813
6814 // index = TRUE; add = TRUE; wback = FALSE;
6815 index = true;
6816 add = true;
6817 wback = false;
6818
6819 // if t == 13 then UNPREDICTABLE;
6820 if (t == 13)
6821 return false;
6822
6823 break;
6824
6825 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006826 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6827 // if Rn == '1111' then SEE LDRSB (literal);
6828 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6829 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006830 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6831 return false;
6832
6833 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6834 t = Bits32 (opcode, 15, 12);
6835 n = Bits32 (opcode, 19, 16);
6836 imm32 = Bits32 (opcode, 7, 0);
6837
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006838 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006839 index = BitIsSet (opcode, 10);
6840 add = BitIsSet (opcode, 9);
6841 wback = BitIsSet (opcode, 8);
6842
6843 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006844 if (((t == 13) || ((t == 15)
6845 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6846 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006847 return false;
6848
6849 break;
6850
6851 case eEncodingA1:
6852 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006853 // if Rn == '1111' then SEE LDRSB (literal);
6854 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006855 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6856 t = Bits32 (opcode, 15, 12);
6857 n = Bits32 (opcode, 19, 16);
6858
6859 uint32_t imm4H = Bits32 (opcode, 11, 8);
6860 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006861 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006862
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006863 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006864 index = BitIsSet (opcode, 24);
6865 add = BitIsSet (opcode, 23);
6866 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6867
6868 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6869 if ((t == 15) || (wback && (n == t)))
6870 return false;
6871
6872 break;
6873 }
6874
6875 default:
6876 return false;
6877 }
6878
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006879 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006880 if (!success)
6881 return false;
6882
6883 addr_t offset_addr;
6884 addr_t address;
6885
6886 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6887 if (add)
6888 offset_addr = Rn + imm32;
6889 else
6890 offset_addr = Rn - imm32;
6891
6892 // address = if index then offset_addr else R[n];
6893 if (index)
6894 address = offset_addr;
6895 else
6896 address = Rn;
6897
6898 // R[t] = SignExtend(MemU[address,1], 32);
6899 Register base_reg;
6900 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6901
6902 EmulateInstruction::Context context;
6903 context.type = eContextRegisterLoad;
6904 context.SetRegisterPlusOffset (base_reg, address - Rn);
6905
6906 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6907 if (!success)
6908 return false;
6909
6910 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6911 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6912 return false;
6913
6914 // if wback then R[n] = offset_addr;
6915 if (wback)
6916 {
6917 context.type = eContextAdjustBaseRegister;
6918 context.SetAddress (offset_addr);
6919 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6920 return false;
6921 }
6922 }
6923
6924 return true;
6925}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006926
Caroline Tice5f593912011-03-01 22:25:17 +00006927// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6928// sign-extends it to form a 32-bit word, and writes tit to a register.
6929bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006930EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006931{
6932#if 0
6933 if ConditionPassed() then
6934 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6935 base = Align(PC,4);
6936 address = if add then (base + imm32) else (base - imm32);
6937 R[t] = SignExtend(MemU[address,1], 32);
6938#endif
6939
6940 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006941
Greg Clayton7bc39082011-03-24 23:53:38 +00006942 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006943 {
6944 uint32_t t;
6945 uint32_t imm32;
6946 bool add;
6947
6948 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6949 switch (encoding)
6950 {
6951 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006952 // if Rt == '1111' then SEE PLI;
6953 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006954 t = Bits32 (opcode, 15, 12);
6955 imm32 = Bits32 (opcode, 11, 0);
6956 add = BitIsSet (opcode, 23);
6957
6958 // if t == 13 then UNPREDICTABLE;
6959 if (t == 13)
6960 return false;
6961
6962 break;
6963
6964 case eEncodingA1:
6965 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006966 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006967 t = Bits32 (opcode, 15, 12);
6968 uint32_t imm4H = Bits32 (opcode, 11, 8);
6969 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006970 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006971 add = BitIsSet (opcode, 23);
6972
6973 // if t == 15 then UNPREDICTABLE;
6974 if (t == 15)
6975 return false;
6976
6977 break;
6978 }
6979
6980 default:
6981 return false;
6982 }
6983
6984 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006985 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006986 if (!success)
6987 return false;
6988 uint64_t base = AlignPC (pc_value);
6989
6990 // address = if add then (base + imm32) else (base - imm32);
6991 addr_t address;
6992 if (add)
6993 address = base + imm32;
6994 else
6995 address = base - imm32;
6996
6997 // R[t] = SignExtend(MemU[address,1], 32);
6998 Register base_reg;
6999 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7000
7001 EmulateInstruction::Context context;
7002 context.type = eContextRegisterLoad;
7003 context.SetRegisterPlusOffset (base_reg, address - base);
7004
7005 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7006 if (!success)
7007 return false;
7008
7009 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7010 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7011 return false;
7012 }
7013 return true;
7014}
7015
Caroline Tice672f3112011-03-01 23:55:59 +00007016// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7017// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7018// shifted left by 0, 1, 2, or 3 bits.
7019bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007020EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007021{
7022#if 0
7023 if ConditionPassed() then
7024 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7025 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7026 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7027 address = if index then offset_addr else R[n];
7028 R[t] = SignExtend(MemU[address,1], 32);
7029 if wback then R[n] = offset_addr;
7030#endif
7031
7032 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007033
Greg Clayton7bc39082011-03-24 23:53:38 +00007034 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007035 {
7036 uint32_t t;
7037 uint32_t n;
7038 uint32_t m;
7039 bool index;
7040 bool add;
7041 bool wback;
7042 ARM_ShifterType shift_t;
7043 uint32_t shift_n;
7044
7045 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7046 switch (encoding)
7047 {
7048 case eEncodingT1:
7049 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7050 t = Bits32 (opcode, 2, 0);
7051 n = Bits32 (opcode, 5, 3);
7052 m = Bits32 (opcode, 8, 6);
7053
7054 // index = TRUE; add = TRUE; wback = FALSE;
7055 index = true;
7056 add = true;
7057 wback = false;
7058
7059 // (shift_t, shift_n) = (SRType_LSL, 0);
7060 shift_t = SRType_LSL;
7061 shift_n = 0;
7062
7063 break;
7064
7065 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007066 // if Rt == '1111' then SEE PLI;
7067 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007068 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7069 t = Bits32 (opcode, 15, 12);
7070 n = Bits32 (opcode, 19, 16);
7071 m = Bits32 (opcode, 3, 0);
7072
7073 // index = TRUE; add = TRUE; wback = FALSE;
7074 index = true;
7075 add = true;
7076 wback = false;
7077
7078 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7079 shift_t = SRType_LSL;
7080 shift_n = Bits32 (opcode, 5, 4);
7081
7082 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7083 if ((t == 13) || BadReg (m))
7084 return false;
7085 break;
7086
7087 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007088 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007089 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7090 t = Bits32 (opcode, 15, 12);
7091 n = Bits32 (opcode, 19, 16);
7092 m = Bits32 (opcode, 3, 0);
7093
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007094 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007095 index = BitIsSet (opcode, 24);
7096 add = BitIsSet (opcode, 23);
7097 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7098
7099 // (shift_t, shift_n) = (SRType_LSL, 0);
7100 shift_t = SRType_LSL;
7101 shift_n = 0;
7102
7103 // if t == 15 || m == 15 then UNPREDICTABLE;
7104 if ((t == 15) || (m == 15))
7105 return false;
7106
7107 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7108 if (wback && ((n == 15) || (n == t)))
7109 return false;
7110 break;
7111
7112 default:
7113 return false;
7114 }
7115
7116 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7117 if (!success)
7118 return false;
7119
7120 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7121 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7122
7123 addr_t offset_addr;
7124 addr_t address;
7125
7126 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7127 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7128 if (!success)
7129 return false;
7130
7131 if (add)
7132 offset_addr = Rn + offset;
7133 else
7134 offset_addr = Rn - offset;
7135
7136 // address = if index then offset_addr else R[n];
7137 if (index)
7138 address = offset_addr;
7139 else
7140 address = Rn;
7141
7142 // R[t] = SignExtend(MemU[address,1], 32);
7143 Register base_reg;
7144 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7145 Register offset_reg;
7146 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7147
7148 EmulateInstruction::Context context;
7149 context.type = eContextRegisterLoad;
7150 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7151
7152 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7153 if (!success)
7154 return false;
7155
7156 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7157 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7158 return false;
7159
7160 // if wback then R[n] = offset_addr;
7161 if (wback)
7162 {
7163 context.type = eContextAdjustBaseRegister;
7164 context.SetAddress (offset_addr);
7165 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7166 return false;
7167 }
7168 }
7169 return true;
7170}
7171
Caroline Tice78fb5632011-03-02 00:39:42 +00007172// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7173// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7174// pre-indexed addressing.
7175bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007176EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007177{
7178#if 0
7179 if ConditionPassed() then
7180 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7181 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7182 address = if index then offset_addr else R[n];
7183 data = MemU[address,2];
7184 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007185 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007186 R[t] = SignExtend(data, 32);
7187 else // Can only apply before ARMv7
7188 R[t] = bits(32) UNKNOWN;
7189#endif
7190
7191 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007192
Greg Clayton7bc39082011-03-24 23:53:38 +00007193 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007194 {
7195 uint32_t t;
7196 uint32_t n;
7197 uint32_t imm32;
7198 bool index;
7199 bool add;
7200 bool wback;
7201
7202 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7203 switch (encoding)
7204 {
7205 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007206 // if Rn == '1111' then SEE LDRSH (literal);
7207 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007208 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7209 t = Bits32 (opcode, 15, 12);
7210 n = Bits32 (opcode, 19, 16);
7211 imm32 = Bits32 (opcode, 11, 0);
7212
7213 // index = TRUE; add = TRUE; wback = FALSE;
7214 index = true;
7215 add = true;
7216 wback = false;
7217
7218 // if t == 13 then UNPREDICTABLE;
7219 if (t == 13)
7220 return false;
7221
7222 break;
7223
7224 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007225 // if Rn == '1111' then SEE LDRSH (literal);
7226 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7227 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7228 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007229 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7230 return false;
7231
7232 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7233 t = Bits32 (opcode, 15, 12);
7234 n = Bits32 (opcode, 19, 16);
7235 imm32 = Bits32 (opcode, 7, 0);
7236
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007237 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007238 index = BitIsSet (opcode, 10);
7239 add = BitIsSet (opcode, 9);
7240 wback = BitIsSet (opcode, 8);
7241
7242 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7243 if (BadReg (t) || (wback && (n == t)))
7244 return false;
7245
7246 break;
7247
7248 case eEncodingA1:
7249 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007250 // if Rn == '1111' then SEE LDRSH (literal);
7251 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007252 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7253 t = Bits32 (opcode, 15, 12);
7254 n = Bits32 (opcode, 19, 16);
7255 uint32_t imm4H = Bits32 (opcode, 11,8);
7256 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007257 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007258
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007259 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007260 index = BitIsSet (opcode, 24);
7261 add = BitIsSet (opcode, 23);
7262 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7263
7264 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7265 if ((t == 15) || (wback && (n == t)))
7266 return false;
7267
7268 break;
7269 }
7270
7271 default:
7272 return false;
7273 }
7274
7275 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7276 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7277 if (!success)
7278 return false;
7279
7280 addr_t offset_addr;
7281 if (add)
7282 offset_addr = Rn + imm32;
7283 else
7284 offset_addr = Rn - imm32;
7285
7286 // address = if index then offset_addr else R[n];
7287 addr_t address;
7288 if (index)
7289 address = offset_addr;
7290 else
7291 address = Rn;
7292
7293 // data = MemU[address,2];
7294 Register base_reg;
7295 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7296
7297 EmulateInstruction::Context context;
7298 context.type = eContextRegisterLoad;
7299 context.SetRegisterPlusOffset (base_reg, address - Rn);
7300
7301 uint64_t data = MemURead (context, address, 2, 0, &success);
7302 if (!success)
7303 return false;
7304
7305 // if wback then R[n] = offset_addr;
7306 if (wback)
7307 {
7308 context.type = eContextAdjustBaseRegister;
7309 context.SetAddress (offset_addr);
7310 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7311 return false;
7312 }
7313
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007314 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007315 if (UnalignedSupport() || BitIsClear (address, 0))
7316 {
7317 // R[t] = SignExtend(data, 32);
7318 int64_t signed_data = llvm::SignExtend64<16>(data);
7319 context.type = eContextRegisterLoad;
7320 context.SetRegisterPlusOffset (base_reg, address - Rn);
7321 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7322 return false;
7323 }
7324 else // Can only apply before ARMv7
7325 {
7326 // R[t] = bits(32) UNKNOWN;
7327 WriteBits32Unknown (t);
7328 }
7329 }
7330 return true;
7331}
7332
Caroline Ticed2fac092011-03-02 19:45:34 +00007333// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7334// sign-extends it to from a 32-bit word, and writes it to a register.
7335bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007336EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007337{
7338#if 0
7339 if ConditionPassed() then
7340 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7341 base = Align(PC,4);
7342 address = if add then (base + imm32) else (base - imm32);
7343 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007344 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007345 R[t] = SignExtend(data, 32);
7346 else // Can only apply before ARMv7
7347 R[t] = bits(32) UNKNOWN;
7348#endif
7349
7350 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007351
Greg Clayton7bc39082011-03-24 23:53:38 +00007352 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007353 {
7354 uint32_t t;
7355 uint32_t imm32;
7356 bool add;
7357
7358 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7359 switch (encoding)
7360 {
7361 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007362 // if Rt == '1111' then SEE "Unallocated memory hints";
7363 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007364 t = Bits32 (opcode, 15, 12);
7365 imm32 = Bits32 (opcode, 11, 0);
7366 add = BitIsSet (opcode, 23);
7367
7368 // if t == 13 then UNPREDICTABLE;
7369 if (t == 13)
7370 return false;
7371
7372 break;
7373
7374 case eEncodingA1:
7375 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007376 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007377 t = Bits32 (opcode, 15, 12);
7378 uint32_t imm4H = Bits32 (opcode, 11, 8);
7379 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007380 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007381 add = BitIsSet (opcode, 23);
7382
7383 // if t == 15 then UNPREDICTABLE;
7384 if (t == 15)
7385 return false;
7386
7387 break;
7388 }
7389 default:
7390 return false;
7391 }
7392
7393 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007394 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007395 if (!success)
7396 return false;
7397
7398 uint64_t base = AlignPC (pc_value);
7399
7400 addr_t address;
7401 // address = if add then (base + imm32) else (base - imm32);
7402 if (add)
7403 address = base + imm32;
7404 else
7405 address = base - imm32;
7406
7407 // data = MemU[address,2];
7408 Register base_reg;
7409 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7410
7411 EmulateInstruction::Context context;
7412 context.type = eContextRegisterLoad;
7413 context.SetRegisterPlusOffset (base_reg, imm32);
7414
7415 uint64_t data = MemURead (context, address, 2, 0, &success);
7416 if (!success)
7417 return false;
7418
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007419 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007420 if (UnalignedSupport() || BitIsClear (address, 0))
7421 {
7422 // R[t] = SignExtend(data, 32);
7423 int64_t signed_data = llvm::SignExtend64<16>(data);
7424 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7425 return false;
7426 }
7427 else // Can only apply before ARMv7
7428 {
7429 // R[t] = bits(32) UNKNOWN;
7430 WriteBits32Unknown (t);
7431 }
7432 }
7433 return true;
7434}
7435
Caroline Tice291a3e92011-03-02 21:13:44 +00007436// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7437// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7438// shifted left by 0, 1, 2, or 3 bits.
7439bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007440EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007441{
7442#if 0
7443 if ConditionPassed() then
7444 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7445 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7446 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7447 address = if index then offset_addr else R[n];
7448 data = MemU[address,2];
7449 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007450 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007451 R[t] = SignExtend(data, 32);
7452 else // Can only apply before ARMv7
7453 R[t] = bits(32) UNKNOWN;
7454#endif
7455
7456 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007457
Greg Clayton7bc39082011-03-24 23:53:38 +00007458 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007459 {
7460 uint32_t t;
7461 uint32_t n;
7462 uint32_t m;
7463 bool index;
7464 bool add;
7465 bool wback;
7466 ARM_ShifterType shift_t;
7467 uint32_t shift_n;
7468
7469 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7470 switch (encoding)
7471 {
7472 case eEncodingT1:
7473 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7474 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7475 t = Bits32 (opcode, 2, 0);
7476 n = Bits32 (opcode, 5, 3);
7477 m = Bits32 (opcode, 8, 6);
7478
7479 // index = TRUE; add = TRUE; wback = FALSE;
7480 index = true;
7481 add = true;
7482 wback = false;
7483
7484 // (shift_t, shift_n) = (SRType_LSL, 0);
7485 shift_t = SRType_LSL;
7486 shift_n = 0;
7487
7488 break;
7489
7490 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007491 // if Rn == '1111' then SEE LDRSH (literal);
7492 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007493 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7494 t = Bits32 (opcode, 15, 12);
7495 n = Bits32 (opcode, 19, 16);
7496 m = Bits32 (opcode, 3, 0);
7497
7498 // index = TRUE; add = TRUE; wback = FALSE;
7499 index = true;
7500 add = true;
7501 wback = false;
7502
7503 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7504 shift_t = SRType_LSL;
7505 shift_n = Bits32 (opcode, 5, 4);
7506
7507 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7508 if ((t == 13) || BadReg (m))
7509 return false;
7510
7511 break;
7512
7513 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007514 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007515 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7516 t = Bits32 (opcode, 15, 12);
7517 n = Bits32 (opcode, 19, 16);
7518 m = Bits32 (opcode, 3, 0);
7519
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007520 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007521 index = BitIsSet (opcode, 24);
7522 add = BitIsSet (opcode, 23);
7523 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7524
7525 // (shift_t, shift_n) = (SRType_LSL, 0);
7526 shift_t = SRType_LSL;
7527 shift_n = 0;
7528
7529 // if t == 15 || m == 15 then UNPREDICTABLE;
7530 if ((t == 15) || (m == 15))
7531 return false;
7532
7533 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7534 if (wback && ((n == 15) || (n == t)))
7535 return false;
7536
7537 break;
7538
7539 default:
7540 break;
7541 }
7542
7543 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7544 if (!success)
7545 return false;
7546
7547 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7548 if (!success)
7549 return false;
7550
7551 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7552 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7553
7554 addr_t offset_addr;
7555 addr_t address;
7556
7557 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7558 if (add)
7559 offset_addr = Rn + offset;
7560 else
7561 offset_addr = Rn - offset;
7562
7563 // address = if index then offset_addr else R[n];
7564 if (index)
7565 address = offset_addr;
7566 else
7567 address = Rn;
7568
7569 // data = MemU[address,2];
7570 Register base_reg;
7571 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7572
7573 Register offset_reg;
7574 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7575
7576 EmulateInstruction::Context context;
7577 context.type = eContextRegisterLoad;
7578 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7579
7580 uint64_t data = MemURead (context, address, 2, 0, &success);
7581 if (!success)
7582 return false;
7583
7584 // if wback then R[n] = offset_addr;
7585 if (wback)
7586 {
7587 context.type = eContextAdjustBaseRegister;
7588 context.SetAddress (offset_addr);
7589 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7590 return false;
7591 }
7592
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007593 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007594 if (UnalignedSupport() || BitIsClear (address, 0))
7595 {
7596 // R[t] = SignExtend(data, 32);
7597 context.type = eContextRegisterLoad;
7598 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7599
7600 int64_t signed_data = llvm::SignExtend64<16>(data);
7601 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7602 return false;
7603 }
7604 else // Can only apply before ARMv7
7605 {
7606 // R[t] = bits(32) UNKNOWN;
7607 WriteBits32Unknown (t);
7608 }
7609 }
7610 return true;
7611}
Caroline Tice6bf65162011-03-03 17:42:58 +00007612
7613// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7614// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7615bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007616EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007617{
7618#if 0
7619 if ConditionPassed() then
7620 EncodingSpecificOperations();
7621 rotated = ROR(R[m], rotation);
7622 R[d] = SignExtend(rotated<7:0>, 32);
7623#endif
7624
7625 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007626
Greg Clayton7bc39082011-03-24 23:53:38 +00007627 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007628 {
7629 uint32_t d;
7630 uint32_t m;
7631 uint32_t rotation;
7632
7633 // EncodingSpecificOperations();
7634 switch (encoding)
7635 {
7636 case eEncodingT1:
7637 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7638 d = Bits32 (opcode, 2, 0);
7639 m = Bits32 (opcode, 5, 3);
7640 rotation = 0;
7641
7642 break;
7643
7644 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007645 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007646 d = Bits32 (opcode, 11, 8);
7647 m = Bits32 (opcode, 3, 0);
7648 rotation = Bits32 (opcode, 5, 4) << 3;
7649
7650 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7651 if (BadReg (d) || BadReg (m))
7652 return false;
7653
7654 break;
7655
7656 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007657 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007658 d = Bits32 (opcode, 15, 12);
7659 m = Bits32 (opcode, 3, 0);
7660 rotation = Bits32 (opcode, 11, 10) << 3;
7661
7662 // if d == 15 || m == 15 then UNPREDICTABLE;
7663 if ((d == 15) || (m == 15))
7664 return false;
7665
7666 break;
7667
7668 default:
7669 return false;
7670 }
7671
Caroline Tice868198b2011-03-03 18:04:49 +00007672 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7673 if (!success)
7674 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007675
7676 // rotated = ROR(R[m], rotation);
7677 uint64_t rotated = ROR (Rm, rotation);
7678
7679 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007680 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007681
7682 Register source_reg;
7683 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7684
7685 EmulateInstruction::Context context;
7686 context.type = eContextRegisterLoad;
7687 context.SetRegister (source_reg);
7688
Caroline Tice8ce96d92011-03-03 18:27:17 +00007689 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007690 return false;
7691 }
7692 return true;
7693}
Caroline Tice291a3e92011-03-02 21:13:44 +00007694
Caroline Tice868198b2011-03-03 18:04:49 +00007695// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7696// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7697bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007698EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007699{
7700#if 0
7701 if ConditionPassed() then
7702 EncodingSpecificOperations();
7703 rotated = ROR(R[m], rotation);
7704 R[d] = SignExtend(rotated<15:0>, 32);
7705#endif
7706
7707 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007708
Greg Clayton7bc39082011-03-24 23:53:38 +00007709 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007710 {
7711 uint32_t d;
7712 uint32_t m;
7713 uint32_t rotation;
7714
7715 // EncodingSpecificOperations();
7716 switch (encoding)
7717 {
7718 case eEncodingT1:
7719 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7720 d = Bits32 (opcode, 2, 0);
7721 m = Bits32 (opcode, 5, 3);
7722 rotation = 0;
7723
7724 break;
7725
7726 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007727 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007728 d = Bits32 (opcode, 11, 8);
7729 m = Bits32 (opcode, 3, 0);
7730 rotation = Bits32 (opcode, 5, 4) << 3;
7731
7732 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7733 if (BadReg (d) || BadReg (m))
7734 return false;
7735
7736 break;
7737
7738 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007739 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007740 d = Bits32 (opcode, 15, 12);
7741 m = Bits32 (opcode, 3, 0);
7742 rotation = Bits32 (opcode, 11, 10) << 3;
7743
7744 // if d == 15 || m == 15 then UNPREDICTABLE;
7745 if ((d == 15) || (m == 15))
7746 return false;
7747
7748 break;
7749
7750 default:
7751 return false;
7752 }
7753
7754 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7755 if (!success)
7756 return false;
7757
7758 // rotated = ROR(R[m], rotation);
7759 uint64_t rotated = ROR (Rm, rotation);
7760
7761 // R[d] = SignExtend(rotated<15:0>, 32);
7762 Register source_reg;
7763 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7764
7765 EmulateInstruction::Context context;
7766 context.type = eContextRegisterLoad;
7767 context.SetRegister (source_reg);
7768
Caroline Tice8ce96d92011-03-03 18:27:17 +00007769 int64_t data = llvm::SignExtend64<16> (rotated);
7770 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007771 return false;
7772 }
7773
7774 return true;
7775}
7776
Caroline Tice8ce96d92011-03-03 18:27:17 +00007777// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7778// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7779bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007780EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007781{
7782#if 0
7783 if ConditionPassed() then
7784 EncodingSpecificOperations();
7785 rotated = ROR(R[m], rotation);
7786 R[d] = ZeroExtend(rotated<7:0>, 32);
7787#endif
7788
7789 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007790
Greg Clayton7bc39082011-03-24 23:53:38 +00007791 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007792 {
7793 uint32_t d;
7794 uint32_t m;
7795 uint32_t rotation;
7796
7797 // EncodingSpecificOperations();
7798 switch (encoding)
7799 {
7800 case eEncodingT1:
7801 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7802 d = Bits32 (opcode, 2, 0);
7803 m = Bits32 (opcode, 5, 3);
7804 rotation = 0;
7805
7806 break;
7807
7808 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007809 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007810 d = Bits32 (opcode, 11, 8);
7811 m = Bits32 (opcode, 3, 0);
7812 rotation = Bits32 (opcode, 5, 4) << 3;
7813
7814 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7815 if (BadReg (d) || BadReg (m))
7816 return false;
7817
7818 break;
7819
7820 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007821 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007822 d = Bits32 (opcode, 15, 12);
7823 m = Bits32 (opcode, 3, 0);
7824 rotation = Bits32 (opcode, 11, 10) << 3;
7825
7826 // if d == 15 || m == 15 then UNPREDICTABLE;
7827 if ((d == 15) || (m == 15))
7828 return false;
7829
7830 break;
7831
7832 default:
7833 return false;
7834 }
7835
7836 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7837 if (!success)
7838 return false;
7839
7840 // rotated = ROR(R[m], rotation);
7841 uint64_t rotated = ROR (Rm, rotation);
7842
7843 // R[d] = ZeroExtend(rotated<7:0>, 32);
7844 Register source_reg;
7845 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7846
7847 EmulateInstruction::Context context;
7848 context.type = eContextRegisterLoad;
7849 context.SetRegister (source_reg);
7850
7851 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7852 return false;
7853 }
7854 return true;
7855}
7856
Caroline Tice11555f22011-03-03 18:48:58 +00007857// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7858// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7859bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007860EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007861{
7862#if 0
7863 if ConditionPassed() then
7864 EncodingSpecificOperations();
7865 rotated = ROR(R[m], rotation);
7866 R[d] = ZeroExtend(rotated<15:0>, 32);
7867#endif
7868
7869 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007870
Greg Clayton7bc39082011-03-24 23:53:38 +00007871 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007872 {
7873 uint32_t d;
7874 uint32_t m;
7875 uint32_t rotation;
7876
7877 switch (encoding)
7878 {
7879 case eEncodingT1:
7880 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7881 d = Bits32 (opcode, 2, 0);
7882 m = Bits32 (opcode, 5, 3);
7883 rotation = 0;
7884
7885 break;
7886
7887 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007888 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007889 d = Bits32 (opcode, 11, 8);
7890 m = Bits32 (opcode, 3, 0);
7891 rotation = Bits32 (opcode, 5, 4) << 3;
7892
7893 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7894 if (BadReg (d) || BadReg (m))
7895 return false;
7896
7897 break;
7898
7899 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007900 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007901 d = Bits32 (opcode, 15, 12);
7902 m = Bits32 (opcode, 3, 0);
7903 rotation = Bits32 (opcode, 11, 10) << 3;
7904
7905 // if d == 15 || m == 15 then UNPREDICTABLE;
7906 if ((d == 15) || (m == 15))
7907 return false;
7908
7909 break;
7910
7911 default:
7912 return false;
7913 }
7914
7915 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7916 if (!success)
7917 return false;
7918
7919 // rotated = ROR(R[m], rotation);
7920 uint64_t rotated = ROR (Rm, rotation);
7921
7922 // R[d] = ZeroExtend(rotated<15:0>, 32);
7923 Register source_reg;
7924 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7925
7926 EmulateInstruction::Context context;
7927 context.type = eContextRegisterLoad;
7928 context.SetRegister (source_reg);
7929
7930 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7931 return false;
7932 }
7933 return true;
7934}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007935
7936// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7937// word respectively.
7938bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007939EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007940{
7941#if 0
7942 if ConditionPassed() then
7943 EncodingSpecificOperations();
7944 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7945 UNPREDICTABLE;
7946 else
7947 address = if increment then R[n] else R[n]-8;
7948 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007949 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007950 BranchWritePC(MemA[address,4]);
7951 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7952#endif
7953
7954 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007955
Greg Clayton7bc39082011-03-24 23:53:38 +00007956 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007957 {
7958 uint32_t n;
7959 bool wback;
7960 bool increment;
7961 bool wordhigher;
7962
7963 // EncodingSpecificOperations();
7964 switch (encoding)
7965 {
7966 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007967 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007968 n = Bits32 (opcode, 19, 16);
7969 wback = BitIsSet (opcode, 21);
7970 increment = false;
7971 wordhigher = false;
7972
7973 // if n == 15 then UNPREDICTABLE;
7974 if (n == 15)
7975 return false;
7976
7977 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7978 if (InITBlock() && !LastInITBlock())
7979 return false;
7980
7981 break;
7982
7983 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007984 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007985 n = Bits32 (opcode, 19, 16);
7986 wback = BitIsSet (opcode, 21);
7987 increment = true;
7988 wordhigher = false;
7989
7990 // if n == 15 then UNPREDICTABLE;
7991 if (n == 15)
7992 return false;
7993
7994 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7995 if (InITBlock() && !LastInITBlock())
7996 return false;
7997
7998 break;
7999
8000 case eEncodingA1:
8001 // n = UInt(Rn);
8002 n = Bits32 (opcode, 19, 16);
8003
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008004 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008005 wback = BitIsSet (opcode, 21);
8006 increment = BitIsSet (opcode, 23);
8007 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8008
8009 // if n == 15 then UNPREDICTABLE;
8010 if (n == 15)
8011 return false;
8012
8013 break;
8014
8015 default:
8016 return false;
8017 }
8018
8019 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8020 if (!CurrentModeIsPrivileged ())
8021 // UNPREDICTABLE;
8022 return false;
8023 else
8024 {
8025 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8026 if (!success)
8027 return false;
8028
8029 addr_t address;
8030 // address = if increment then R[n] else R[n]-8;
8031 if (increment)
8032 address = Rn;
8033 else
8034 address = Rn - 8;
8035
8036 // if wordhigher then address = address+4;
8037 if (wordhigher)
8038 address = address + 4;
8039
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008040 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008041 Register base_reg;
8042 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8043
8044 EmulateInstruction::Context context;
8045 context.type = eContextReturnFromException;
8046 context.SetRegisterPlusOffset (base_reg, address - Rn);
8047
8048 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8049 if (!success)
8050 return false;
8051
8052 CPSRWriteByInstr (data, 15, true);
8053
8054 // BranchWritePC(MemA[address,4]);
8055 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8056 if (!success)
8057 return false;
8058
8059 BranchWritePC (context, data2);
8060
8061 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8062 if (wback)
8063 {
8064 context.type = eContextAdjustBaseRegister;
8065 if (increment)
8066 {
8067 context.SetOffset (8);
8068 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8069 return false;
8070 }
8071 else
8072 {
8073 context.SetOffset (-8);
8074 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8075 return false;
8076 }
8077 } // if wback
8078 }
8079 } // if ConditionPassed()
8080 return true;
8081}
Caroline Tice11555f22011-03-03 18:48:58 +00008082
Johnny Chen2115b412011-02-21 23:42:44 +00008083// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8084// and writes the result to the destination register. It can optionally update the condition flags based on
8085// the result.
8086bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008087EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008088{
8089#if 0
8090 // ARM pseudo code...
8091 if ConditionPassed() then
8092 EncodingSpecificOperations();
8093 result = R[n] EOR imm32;
8094 if d == 15 then // Can only occur for ARM encoding
8095 ALUWritePC(result); // setflags is always FALSE here
8096 else
8097 R[d] = result;
8098 if setflags then
8099 APSR.N = result<31>;
8100 APSR.Z = IsZeroBit(result);
8101 APSR.C = carry;
8102 // APSR.V unchanged
8103#endif
8104
8105 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008106
Greg Clayton7bc39082011-03-24 23:53:38 +00008107 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008108 {
8109 uint32_t Rd, Rn;
8110 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8111 bool setflags;
8112 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8113 switch (encoding)
8114 {
8115 case eEncodingT1:
8116 Rd = Bits32(opcode, 11, 8);
8117 Rn = Bits32(opcode, 19, 16);
8118 setflags = BitIsSet(opcode, 20);
8119 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8120 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8121 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008122 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008123 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8124 return false;
8125 break;
8126 case eEncodingA1:
8127 Rd = Bits32(opcode, 15, 12);
8128 Rn = Bits32(opcode, 19, 16);
8129 setflags = BitIsSet(opcode, 20);
8130 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008131
Johnny Chen2115b412011-02-21 23:42:44 +00008132 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008133 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008134 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008135 break;
8136 default:
8137 return false;
8138 }
8139
8140 // Read the first operand.
8141 uint32_t val1 = ReadCoreReg(Rn, &success);
8142 if (!success)
8143 return false;
8144
8145 uint32_t result = val1 ^ imm32;
8146
8147 EmulateInstruction::Context context;
8148 context.type = EmulateInstruction::eContextImmediate;
8149 context.SetNoArgs ();
8150
8151 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8152 return false;
8153 }
8154 return true;
8155}
8156
8157// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8158// optionally-shifted register value, and writes the result to the destination register.
8159// It can optionally update the condition flags based on the result.
8160bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008161EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008162{
8163#if 0
8164 // ARM pseudo code...
8165 if ConditionPassed() then
8166 EncodingSpecificOperations();
8167 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8168 result = R[n] EOR shifted;
8169 if d == 15 then // Can only occur for ARM encoding
8170 ALUWritePC(result); // setflags is always FALSE here
8171 else
8172 R[d] = result;
8173 if setflags then
8174 APSR.N = result<31>;
8175 APSR.Z = IsZeroBit(result);
8176 APSR.C = carry;
8177 // APSR.V unchanged
8178#endif
8179
8180 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008181
Greg Clayton7bc39082011-03-24 23:53:38 +00008182 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008183 {
8184 uint32_t Rd, Rn, Rm;
8185 ARM_ShifterType shift_t;
8186 uint32_t shift_n; // the shift applied to the value read from Rm
8187 bool setflags;
8188 uint32_t carry;
8189 switch (encoding)
8190 {
8191 case eEncodingT1:
8192 Rd = Rn = Bits32(opcode, 2, 0);
8193 Rm = Bits32(opcode, 5, 3);
8194 setflags = !InITBlock();
8195 shift_t = SRType_LSL;
8196 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008197 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008198 case eEncodingT2:
8199 Rd = Bits32(opcode, 11, 8);
8200 Rn = Bits32(opcode, 19, 16);
8201 Rm = Bits32(opcode, 3, 0);
8202 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008203 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8204 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008205 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008206 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008207 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8208 return false;
8209 break;
8210 case eEncodingA1:
8211 Rd = Bits32(opcode, 15, 12);
8212 Rn = Bits32(opcode, 19, 16);
8213 Rm = Bits32(opcode, 3, 0);
8214 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008215 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008216
Johnny Chen2115b412011-02-21 23:42:44 +00008217 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008218 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008219 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008220 break;
8221 default:
8222 return false;
8223 }
8224
8225 // Read the first operand.
8226 uint32_t val1 = ReadCoreReg(Rn, &success);
8227 if (!success)
8228 return false;
8229
8230 // Read the second operand.
8231 uint32_t val2 = ReadCoreReg(Rm, &success);
8232 if (!success)
8233 return false;
8234
8235 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8236 uint32_t result = val1 ^ shifted;
8237
8238 EmulateInstruction::Context context;
8239 context.type = EmulateInstruction::eContextImmediate;
8240 context.SetNoArgs ();
8241
8242 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8243 return false;
8244 }
8245 return true;
8246}
8247
Johnny Chen7c5234d2011-02-18 23:41:11 +00008248// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8249// writes the result to the destination register. It can optionally update the condition flags based
8250// on the result.
8251bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008252EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008253{
8254#if 0
8255 // ARM pseudo code...
8256 if ConditionPassed() then
8257 EncodingSpecificOperations();
8258 result = R[n] OR imm32;
8259 if d == 15 then // Can only occur for ARM encoding
8260 ALUWritePC(result); // setflags is always FALSE here
8261 else
8262 R[d] = result;
8263 if setflags then
8264 APSR.N = result<31>;
8265 APSR.Z = IsZeroBit(result);
8266 APSR.C = carry;
8267 // APSR.V unchanged
8268#endif
8269
8270 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008271
Greg Clayton7bc39082011-03-24 23:53:38 +00008272 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008273 {
8274 uint32_t Rd, Rn;
8275 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8276 bool setflags;
8277 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8278 switch (encoding)
8279 {
8280 case eEncodingT1:
8281 Rd = Bits32(opcode, 11, 8);
8282 Rn = Bits32(opcode, 19, 16);
8283 setflags = BitIsSet(opcode, 20);
8284 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008285 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008286 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008287 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008288 if (BadReg(Rd) || Rn == 13)
8289 return false;
8290 break;
8291 case eEncodingA1:
8292 Rd = Bits32(opcode, 15, 12);
8293 Rn = Bits32(opcode, 19, 16);
8294 setflags = BitIsSet(opcode, 20);
8295 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008296
Johnny Chen7c5234d2011-02-18 23:41:11 +00008297 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008298 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008299 break;
8300 default:
8301 return false;
8302 }
8303
8304 // Read the first operand.
8305 uint32_t val1 = ReadCoreReg(Rn, &success);
8306 if (!success)
8307 return false;
8308
8309 uint32_t result = val1 | imm32;
8310
8311 EmulateInstruction::Context context;
8312 context.type = EmulateInstruction::eContextImmediate;
8313 context.SetNoArgs ();
8314
8315 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8316 return false;
8317 }
8318 return true;
8319}
8320
8321// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8322// value, and writes the result to the destination register. It can optionally update the condition flags based
8323// on the result.
8324bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008325EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008326{
8327#if 0
8328 // ARM pseudo code...
8329 if ConditionPassed() then
8330 EncodingSpecificOperations();
8331 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8332 result = R[n] OR shifted;
8333 if d == 15 then // Can only occur for ARM encoding
8334 ALUWritePC(result); // setflags is always FALSE here
8335 else
8336 R[d] = result;
8337 if setflags then
8338 APSR.N = result<31>;
8339 APSR.Z = IsZeroBit(result);
8340 APSR.C = carry;
8341 // APSR.V unchanged
8342#endif
8343
8344 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008345
Greg Clayton7bc39082011-03-24 23:53:38 +00008346 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008347 {
8348 uint32_t Rd, Rn, Rm;
8349 ARM_ShifterType shift_t;
8350 uint32_t shift_n; // the shift applied to the value read from Rm
8351 bool setflags;
8352 uint32_t carry;
8353 switch (encoding)
8354 {
8355 case eEncodingT1:
8356 Rd = Rn = Bits32(opcode, 2, 0);
8357 Rm = Bits32(opcode, 5, 3);
8358 setflags = !InITBlock();
8359 shift_t = SRType_LSL;
8360 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008361 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008362 case eEncodingT2:
8363 Rd = Bits32(opcode, 11, 8);
8364 Rn = Bits32(opcode, 19, 16);
8365 Rm = Bits32(opcode, 3, 0);
8366 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008367 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8368 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008369 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008370 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008371 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8372 return false;
8373 break;
8374 case eEncodingA1:
8375 Rd = Bits32(opcode, 15, 12);
8376 Rn = Bits32(opcode, 19, 16);
8377 Rm = Bits32(opcode, 3, 0);
8378 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008379 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008380
Johnny Chen7c5234d2011-02-18 23:41:11 +00008381 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008382 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008383 break;
8384 default:
8385 return false;
8386 }
8387
8388 // Read the first operand.
8389 uint32_t val1 = ReadCoreReg(Rn, &success);
8390 if (!success)
8391 return false;
8392
8393 // Read the second operand.
8394 uint32_t val2 = ReadCoreReg(Rm, &success);
8395 if (!success)
8396 return false;
8397
8398 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008399 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008400
8401 EmulateInstruction::Context context;
8402 context.type = EmulateInstruction::eContextImmediate;
8403 context.SetNoArgs ();
8404
8405 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8406 return false;
8407 }
8408 return true;
8409}
8410
Johnny Chened32e7c2011-02-22 23:42:58 +00008411// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8412// the destination register. It can optionally update the condition flags based on the result.
8413bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008414EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008415{
8416#if 0
8417 // ARM pseudo code...
8418 if ConditionPassed() then
8419 EncodingSpecificOperations();
8420 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8421 if d == 15 then // Can only occur for ARM encoding
8422 ALUWritePC(result); // setflags is always FALSE here
8423 else
8424 R[d] = result;
8425 if setflags then
8426 APSR.N = result<31>;
8427 APSR.Z = IsZeroBit(result);
8428 APSR.C = carry;
8429 APSR.V = overflow;
8430#endif
8431
8432 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008433
8434 uint32_t Rd; // the destination register
8435 uint32_t Rn; // the first operand
8436 bool setflags;
8437 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8438 switch (encoding) {
8439 case eEncodingT1:
8440 Rd = Bits32(opcode, 2, 0);
8441 Rn = Bits32(opcode, 5, 3);
8442 setflags = !InITBlock();
8443 imm32 = 0;
8444 break;
8445 case eEncodingT2:
8446 Rd = Bits32(opcode, 11, 8);
8447 Rn = Bits32(opcode, 19, 16);
8448 setflags = BitIsSet(opcode, 20);
8449 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8450 if (BadReg(Rd) || BadReg(Rn))
8451 return false;
8452 break;
8453 case eEncodingA1:
8454 Rd = Bits32(opcode, 15, 12);
8455 Rn = Bits32(opcode, 19, 16);
8456 setflags = BitIsSet(opcode, 20);
8457 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008458
Johnny Chened32e7c2011-02-22 23:42:58 +00008459 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008460 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008461 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008462 break;
8463 default:
8464 return false;
8465 }
8466 // Read the register value from the operand register Rn.
8467 uint32_t reg_val = ReadCoreReg(Rn, &success);
8468 if (!success)
8469 return false;
8470
8471 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8472
8473 EmulateInstruction::Context context;
8474 context.type = EmulateInstruction::eContextImmediate;
8475 context.SetNoArgs ();
8476
8477 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8478 return false;
8479
8480 return true;
8481}
8482
8483// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8484// result to the destination register. It can optionally update the condition flags based on the result.
8485bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008486EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008487{
8488#if 0
8489 // ARM pseudo code...
8490 if ConditionPassed() then
8491 EncodingSpecificOperations();
8492 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8493 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8494 if d == 15 then // Can only occur for ARM encoding
8495 ALUWritePC(result); // setflags is always FALSE here
8496 else
8497 R[d] = result;
8498 if setflags then
8499 APSR.N = result<31>;
8500 APSR.Z = IsZeroBit(result);
8501 APSR.C = carry;
8502 APSR.V = overflow;
8503#endif
8504
8505 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008506
8507 uint32_t Rd; // the destination register
8508 uint32_t Rn; // the first operand
8509 uint32_t Rm; // the second operand
8510 bool setflags;
8511 ARM_ShifterType shift_t;
8512 uint32_t shift_n; // the shift applied to the value read from Rm
8513 switch (encoding) {
8514 case eEncodingT1:
8515 Rd = Bits32(opcode, 11, 8);
8516 Rn = Bits32(opcode, 19, 16);
8517 Rm = Bits32(opcode, 3, 0);
8518 setflags = BitIsSet(opcode, 20);
8519 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8520 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8521 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8522 return false;
8523 break;
8524 case eEncodingA1:
8525 Rd = Bits32(opcode, 15, 12);
8526 Rn = Bits32(opcode, 19, 16);
8527 Rm = Bits32(opcode, 3, 0);
8528 setflags = BitIsSet(opcode, 20);
8529 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008530
Johnny Chened32e7c2011-02-22 23:42:58 +00008531 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008532 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008533 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008534 break;
8535 default:
8536 return false;
8537 }
8538 // Read the register value from register Rn.
8539 uint32_t val1 = ReadCoreReg(Rn, &success);
8540 if (!success)
8541 return false;
8542
8543 // Read the register value from register Rm.
8544 uint32_t val2 = ReadCoreReg(Rm, &success);
8545 if (!success)
8546 return false;
8547
8548 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8549 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8550
8551 EmulateInstruction::Context context;
8552 context.type = EmulateInstruction::eContextImmediate;
8553 context.SetNoArgs();
8554 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8555 return false;
8556
8557 return true;
8558}
8559
Johnny Chen90e607b2011-02-23 00:07:09 +00008560// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8561// an immediate value, and writes the result to the destination register. It can optionally update the condition
8562// flags based on the result.
8563bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008564EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008565{
8566#if 0
8567 // ARM pseudo code...
8568 if ConditionPassed() then
8569 EncodingSpecificOperations();
8570 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8571 if d == 15 then
8572 ALUWritePC(result); // setflags is always FALSE here
8573 else
8574 R[d] = result;
8575 if setflags then
8576 APSR.N = result<31>;
8577 APSR.Z = IsZeroBit(result);
8578 APSR.C = carry;
8579 APSR.V = overflow;
8580#endif
8581
8582 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008583
8584 uint32_t Rd; // the destination register
8585 uint32_t Rn; // the first operand
8586 bool setflags;
8587 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8588 switch (encoding) {
8589 case eEncodingA1:
8590 Rd = Bits32(opcode, 15, 12);
8591 Rn = Bits32(opcode, 19, 16);
8592 setflags = BitIsSet(opcode, 20);
8593 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008594
Johnny Chen90e607b2011-02-23 00:07:09 +00008595 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008596 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008597 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008598 break;
8599 default:
8600 return false;
8601 }
8602 // Read the register value from the operand register Rn.
8603 uint32_t reg_val = ReadCoreReg(Rn, &success);
8604 if (!success)
8605 return false;
8606
8607 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8608
8609 EmulateInstruction::Context context;
8610 context.type = EmulateInstruction::eContextImmediate;
8611 context.SetNoArgs ();
8612
8613 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8614 return false;
8615
8616 return true;
8617}
8618
8619// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8620// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8621// condition flags based on the result.
8622bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008623EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008624{
8625#if 0
8626 // ARM pseudo code...
8627 if ConditionPassed() then
8628 EncodingSpecificOperations();
8629 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8630 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8631 if d == 15 then
8632 ALUWritePC(result); // setflags is always FALSE here
8633 else
8634 R[d] = result;
8635 if setflags then
8636 APSR.N = result<31>;
8637 APSR.Z = IsZeroBit(result);
8638 APSR.C = carry;
8639 APSR.V = overflow;
8640#endif
8641
8642 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008643
8644 uint32_t Rd; // the destination register
8645 uint32_t Rn; // the first operand
8646 uint32_t Rm; // the second operand
8647 bool setflags;
8648 ARM_ShifterType shift_t;
8649 uint32_t shift_n; // the shift applied to the value read from Rm
8650 switch (encoding) {
8651 case eEncodingA1:
8652 Rd = Bits32(opcode, 15, 12);
8653 Rn = Bits32(opcode, 19, 16);
8654 Rm = Bits32(opcode, 3, 0);
8655 setflags = BitIsSet(opcode, 20);
8656 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008657
Johnny Chen90e607b2011-02-23 00:07:09 +00008658 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008659 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008660 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008661 break;
8662 default:
8663 return false;
8664 }
8665 // Read the register value from register Rn.
8666 uint32_t val1 = ReadCoreReg(Rn, &success);
8667 if (!success)
8668 return false;
8669
8670 // Read the register value from register Rm.
8671 uint32_t val2 = ReadCoreReg(Rm, &success);
8672 if (!success)
8673 return false;
8674
8675 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8676 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8677
8678 EmulateInstruction::Context context;
8679 context.type = EmulateInstruction::eContextImmediate;
8680 context.SetNoArgs();
8681 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8682 return false;
8683
8684 return true;
8685}
8686
Johnny Chen9b381772011-02-23 01:01:21 +00008687// Subtract with Carry (immediate) subtracts an immediate value and the value of
8688// NOT (Carry flag) from a register value, and writes the result to the destination register.
8689// It can optionally update the condition flags based on the result.
8690bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008691EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008692{
8693#if 0
8694 // ARM pseudo code...
8695 if ConditionPassed() then
8696 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008697 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008698 if d == 15 then // Can only occur for ARM encoding
8699 ALUWritePC(result); // setflags is always FALSE here
8700 else
8701 R[d] = result;
8702 if setflags then
8703 APSR.N = result<31>;
8704 APSR.Z = IsZeroBit(result);
8705 APSR.C = carry;
8706 APSR.V = overflow;
8707#endif
8708
8709 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008710
8711 uint32_t Rd; // the destination register
8712 uint32_t Rn; // the first operand
8713 bool setflags;
8714 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8715 switch (encoding) {
8716 case eEncodingT1:
8717 Rd = Bits32(opcode, 11, 8);
8718 Rn = Bits32(opcode, 19, 16);
8719 setflags = BitIsSet(opcode, 20);
8720 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8721 if (BadReg(Rd) || BadReg(Rn))
8722 return false;
8723 break;
8724 case eEncodingA1:
8725 Rd = Bits32(opcode, 15, 12);
8726 Rn = Bits32(opcode, 19, 16);
8727 setflags = BitIsSet(opcode, 20);
8728 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008729
Johnny Chen9b381772011-02-23 01:01:21 +00008730 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008731 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008732 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008733 break;
8734 default:
8735 return false;
8736 }
8737 // Read the register value from the operand register Rn.
8738 uint32_t reg_val = ReadCoreReg(Rn, &success);
8739 if (!success)
8740 return false;
8741
8742 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8743
8744 EmulateInstruction::Context context;
8745 context.type = EmulateInstruction::eContextImmediate;
8746 context.SetNoArgs ();
8747
8748 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8749 return false;
8750
8751 return true;
8752}
8753
8754// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8755// NOT (Carry flag) from a register value, and writes the result to the destination register.
8756// It can optionally update the condition flags based on the result.
8757bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008758EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008759{
8760#if 0
8761 // ARM pseudo code...
8762 if ConditionPassed() then
8763 EncodingSpecificOperations();
8764 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8765 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8766 if d == 15 then // Can only occur for ARM encoding
8767 ALUWritePC(result); // setflags is always FALSE here
8768 else
8769 R[d] = result;
8770 if setflags then
8771 APSR.N = result<31>;
8772 APSR.Z = IsZeroBit(result);
8773 APSR.C = carry;
8774 APSR.V = overflow;
8775#endif
8776
8777 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008778
8779 uint32_t Rd; // the destination register
8780 uint32_t Rn; // the first operand
8781 uint32_t Rm; // the second operand
8782 bool setflags;
8783 ARM_ShifterType shift_t;
8784 uint32_t shift_n; // the shift applied to the value read from Rm
8785 switch (encoding) {
8786 case eEncodingT1:
8787 Rd = Rn = Bits32(opcode, 2, 0);
8788 Rm = Bits32(opcode, 5, 3);
8789 setflags = !InITBlock();
8790 shift_t = SRType_LSL;
8791 shift_n = 0;
8792 break;
8793 case eEncodingT2:
8794 Rd = Bits32(opcode, 11, 8);
8795 Rn = Bits32(opcode, 19, 16);
8796 Rm = Bits32(opcode, 3, 0);
8797 setflags = BitIsSet(opcode, 20);
8798 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8799 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8800 return false;
8801 break;
8802 case eEncodingA1:
8803 Rd = Bits32(opcode, 15, 12);
8804 Rn = Bits32(opcode, 19, 16);
8805 Rm = Bits32(opcode, 3, 0);
8806 setflags = BitIsSet(opcode, 20);
8807 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008808
Johnny Chen9b381772011-02-23 01:01:21 +00008809 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008810 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008811 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008812 break;
8813 default:
8814 return false;
8815 }
8816 // Read the register value from register Rn.
8817 uint32_t val1 = ReadCoreReg(Rn, &success);
8818 if (!success)
8819 return false;
8820
8821 // Read the register value from register Rm.
8822 uint32_t val2 = ReadCoreReg(Rm, &success);
8823 if (!success)
8824 return false;
8825
8826 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8827 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8828
8829 EmulateInstruction::Context context;
8830 context.type = EmulateInstruction::eContextImmediate;
8831 context.SetNoArgs();
8832 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8833 return false;
8834
8835 return true;
8836}
8837
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008838// This instruction subtracts an immediate value from a register value, and writes the result
8839// to the destination register. It can optionally update the condition flags based on the result.
8840bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008841EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008842{
8843#if 0
8844 // ARM pseudo code...
8845 if ConditionPassed() then
8846 EncodingSpecificOperations();
8847 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8848 R[d] = result;
8849 if setflags then
8850 APSR.N = result<31>;
8851 APSR.Z = IsZeroBit(result);
8852 APSR.C = carry;
8853 APSR.V = overflow;
8854#endif
8855
8856 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008857
8858 uint32_t Rd; // the destination register
8859 uint32_t Rn; // the first operand
8860 bool setflags;
8861 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8862 switch (encoding) {
8863 case eEncodingT1:
8864 Rd = Bits32(opcode, 2, 0);
8865 Rn = Bits32(opcode, 5, 3);
8866 setflags = !InITBlock();
8867 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8868 break;
8869 case eEncodingT2:
8870 Rd = Rn = Bits32(opcode, 10, 8);
8871 setflags = !InITBlock();
8872 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8873 break;
8874 case eEncodingT3:
8875 Rd = Bits32(opcode, 11, 8);
8876 Rn = Bits32(opcode, 19, 16);
8877 setflags = BitIsSet(opcode, 20);
8878 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8879
8880 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8881 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008882 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008883
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008884 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008885 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008886 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008887
8888 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8889 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8890 return false;
8891 break;
8892 case eEncodingT4:
8893 Rd = Bits32(opcode, 11, 8);
8894 Rn = Bits32(opcode, 19, 16);
8895 setflags = BitIsSet(opcode, 20);
8896 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8897
8898 // if Rn == '1111' then SEE ADR;
8899 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008900 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008901
8902 // if Rn == '1101' then SEE SUB (SP minus immediate);
8903 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008904 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008905
8906 if (BadReg(Rd))
8907 return false;
8908 break;
8909 default:
8910 return false;
8911 }
8912 // Read the register value from the operand register Rn.
8913 uint32_t reg_val = ReadCoreReg(Rn, &success);
8914 if (!success)
8915 return false;
8916
8917 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8918
8919 EmulateInstruction::Context context;
8920 context.type = EmulateInstruction::eContextImmediate;
8921 context.SetNoArgs ();
8922
8923 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8924 return false;
8925
8926 return true;
8927}
8928
8929// This instruction subtracts an immediate value from a register value, and writes the result
8930// to the destination register. It can optionally update the condition flags based on the result.
8931bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008932EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008933{
8934#if 0
8935 // ARM pseudo code...
8936 if ConditionPassed() then
8937 EncodingSpecificOperations();
8938 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8939 if d == 15 then
8940 ALUWritePC(result); // setflags is always FALSE here
8941 else
8942 R[d] = result;
8943 if setflags then
8944 APSR.N = result<31>;
8945 APSR.Z = IsZeroBit(result);
8946 APSR.C = carry;
8947 APSR.V = overflow;
8948#endif
8949
8950 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008951
8952 uint32_t Rd; // the destination register
8953 uint32_t Rn; // the first operand
8954 bool setflags;
8955 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8956 switch (encoding) {
8957 case eEncodingA1:
8958 Rd = Bits32(opcode, 15, 12);
8959 Rn = Bits32(opcode, 19, 16);
8960 setflags = BitIsSet(opcode, 20);
8961 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8962
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008963 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008964 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008965 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008966
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008967 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008968 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008969 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008970
8971 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008972 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008973 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008974 break;
8975 default:
8976 return false;
8977 }
8978 // Read the register value from the operand register Rn.
8979 uint32_t reg_val = ReadCoreReg(Rn, &success);
8980 if (!success)
8981 return false;
8982
8983 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8984
8985 EmulateInstruction::Context context;
8986 context.type = EmulateInstruction::eContextImmediate;
8987 context.SetNoArgs ();
8988
8989 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8990 return false;
8991
8992 return true;
8993}
8994
Johnny Chen2115b412011-02-21 23:42:44 +00008995// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8996// immediate value. It updates the condition flags based on the result, and discards the result.
8997bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008998EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008999{
9000#if 0
9001 // ARM pseudo code...
9002 if ConditionPassed() then
9003 EncodingSpecificOperations();
9004 result = R[n] EOR imm32;
9005 APSR.N = result<31>;
9006 APSR.Z = IsZeroBit(result);
9007 APSR.C = carry;
9008 // APSR.V unchanged
9009#endif
9010
9011 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009012
Greg Clayton7bc39082011-03-24 23:53:38 +00009013 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009014 {
9015 uint32_t Rn;
9016 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9017 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9018 switch (encoding)
9019 {
9020 case eEncodingT1:
9021 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009022 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009023 if (BadReg(Rn))
9024 return false;
9025 break;
9026 case eEncodingA1:
9027 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009028 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009029 break;
9030 default:
9031 return false;
9032 }
9033
9034 // Read the first operand.
9035 uint32_t val1 = ReadCoreReg(Rn, &success);
9036 if (!success)
9037 return false;
9038
9039 uint32_t result = val1 ^ imm32;
9040
9041 EmulateInstruction::Context context;
9042 context.type = EmulateInstruction::eContextImmediate;
9043 context.SetNoArgs ();
9044
9045 if (!WriteFlags(context, result, carry))
9046 return false;
9047 }
9048 return true;
9049}
9050
9051// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9052// optionally-shifted register value. It updates the condition flags based on the result, and discards
9053// the result.
9054bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009055EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009056{
9057#if 0
9058 // ARM pseudo code...
9059 if ConditionPassed() then
9060 EncodingSpecificOperations();
9061 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9062 result = R[n] EOR shifted;
9063 APSR.N = result<31>;
9064 APSR.Z = IsZeroBit(result);
9065 APSR.C = carry;
9066 // APSR.V unchanged
9067#endif
9068
9069 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009070
Greg Clayton7bc39082011-03-24 23:53:38 +00009071 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009072 {
9073 uint32_t Rn, Rm;
9074 ARM_ShifterType shift_t;
9075 uint32_t shift_n; // the shift applied to the value read from Rm
9076 uint32_t carry;
9077 switch (encoding)
9078 {
9079 case eEncodingT1:
9080 Rn = Bits32(opcode, 19, 16);
9081 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009082 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009083 if (BadReg(Rn) || BadReg(Rm))
9084 return false;
9085 break;
9086 case eEncodingA1:
9087 Rn = Bits32(opcode, 19, 16);
9088 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009089 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009090 break;
9091 default:
9092 return false;
9093 }
9094
9095 // Read the first operand.
9096 uint32_t val1 = ReadCoreReg(Rn, &success);
9097 if (!success)
9098 return false;
9099
9100 // Read the second operand.
9101 uint32_t val2 = ReadCoreReg(Rm, &success);
9102 if (!success)
9103 return false;
9104
9105 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9106 uint32_t result = val1 ^ shifted;
9107
9108 EmulateInstruction::Context context;
9109 context.type = EmulateInstruction::eContextImmediate;
9110 context.SetNoArgs ();
9111
9112 if (!WriteFlags(context, result, carry))
9113 return false;
9114 }
9115 return true;
9116}
9117
Johnny Chende3cce32011-02-21 21:24:49 +00009118// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9119// It updates the condition flags based on the result, and discards the result.
9120bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009121EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009122{
9123#if 0
9124 // ARM pseudo code...
9125 if ConditionPassed() then
9126 EncodingSpecificOperations();
9127 result = R[n] AND imm32;
9128 APSR.N = result<31>;
9129 APSR.Z = IsZeroBit(result);
9130 APSR.C = carry;
9131 // APSR.V unchanged
9132#endif
9133
9134 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009135
Greg Clayton7bc39082011-03-24 23:53:38 +00009136 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009137 {
9138 uint32_t Rn;
9139 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9140 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9141 switch (encoding)
9142 {
9143 case eEncodingT1:
9144 Rn = Bits32(opcode, 19, 16);
9145 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9146 if (BadReg(Rn))
9147 return false;
9148 break;
9149 case eEncodingA1:
9150 Rn = Bits32(opcode, 19, 16);
9151 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9152 break;
9153 default:
9154 return false;
9155 }
9156
9157 // Read the first operand.
9158 uint32_t val1 = ReadCoreReg(Rn, &success);
9159 if (!success)
9160 return false;
9161
9162 uint32_t result = val1 & imm32;
9163
9164 EmulateInstruction::Context context;
9165 context.type = EmulateInstruction::eContextImmediate;
9166 context.SetNoArgs ();
9167
9168 if (!WriteFlags(context, result, carry))
9169 return false;
9170 }
9171 return true;
9172}
9173
9174// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9175// It updates the condition flags based on the result, and discards the result.
9176bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009177EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009178{
9179#if 0
9180 // ARM pseudo code...
9181 if ConditionPassed() then
9182 EncodingSpecificOperations();
9183 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9184 result = R[n] AND shifted;
9185 APSR.N = result<31>;
9186 APSR.Z = IsZeroBit(result);
9187 APSR.C = carry;
9188 // APSR.V unchanged
9189#endif
9190
9191 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009192
Greg Clayton7bc39082011-03-24 23:53:38 +00009193 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009194 {
9195 uint32_t Rn, Rm;
9196 ARM_ShifterType shift_t;
9197 uint32_t shift_n; // the shift applied to the value read from Rm
9198 uint32_t carry;
9199 switch (encoding)
9200 {
9201 case eEncodingT1:
9202 Rn = Bits32(opcode, 2, 0);
9203 Rm = Bits32(opcode, 5, 3);
9204 shift_t = SRType_LSL;
9205 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009206 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009207 case eEncodingT2:
9208 Rn = Bits32(opcode, 19, 16);
9209 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009210 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009211 if (BadReg(Rn) || BadReg(Rm))
9212 return false;
9213 break;
9214 case eEncodingA1:
9215 Rn = Bits32(opcode, 19, 16);
9216 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009217 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009218 break;
9219 default:
9220 return false;
9221 }
9222
9223 // Read the first operand.
9224 uint32_t val1 = ReadCoreReg(Rn, &success);
9225 if (!success)
9226 return false;
9227
9228 // Read the second operand.
9229 uint32_t val2 = ReadCoreReg(Rm, &success);
9230 if (!success)
9231 return false;
9232
9233 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9234 uint32_t result = val1 & shifted;
9235
9236 EmulateInstruction::Context context;
9237 context.type = EmulateInstruction::eContextImmediate;
9238 context.SetNoArgs ();
9239
9240 if (!WriteFlags(context, result, carry))
9241 return false;
9242 }
9243 return true;
9244}
Caroline Ticed05b4902011-03-29 21:24:06 +00009245
9246// A8.6.216 SUB (SP minus register)
9247bool
9248EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9249{
9250#if 0
9251 if ConditionPassed() then
9252 EncodingSpecificOperations();
9253 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9254 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), 1’);
9255 if d == 15 then // Can only occur for ARM encoding
9256 ALUWritePC(result); // setflags is always FALSE here
9257 else
9258 R[d] = result;
9259 if setflags then
9260 APSR.N = result<31>;
9261 APSR.Z = IsZeroBit(result);
9262 APSR.C = carry;
9263 APSR.V = overflow;
9264#endif
9265
9266 bool success = false;
9267
9268 if (ConditionPassed(opcode))
9269 {
9270 uint32_t d;
9271 uint32_t m;
9272 bool setflags;
9273 ARM_ShifterType shift_t;
9274 uint32_t shift_n;
9275
9276 switch (encoding)
9277 {
9278 case eEncodingT1:
9279 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9280 d = Bits32 (opcode, 11, 8);
9281 m = Bits32 (opcode, 3, 0);
9282 setflags = BitIsSet (opcode, 20);
9283
9284 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9285 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9286
9287 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9288 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9289 return false;
9290
9291 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9292 if ((d == 15) || BadReg (m))
9293 return false;
9294 break;
9295
9296 case eEncodingA1:
Caroline Ticed05b4902011-03-29 21:24:06 +00009297 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9298 d = Bits32 (opcode, 15, 12);
9299 m = Bits32 (opcode, 3, 0);
9300 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009301
9302 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9303 if (d == 15 && setflags)
9304 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009305
9306 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9307 shift_n = DecodeImmShiftARM (opcode, shift_t);
9308 break;
9309
9310 default:
9311 return false;
9312 }
9313
9314 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9315 uint32_t Rm = ReadCoreReg (m, &success);
9316 if (!success)
9317 return false;
9318
9319 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9320
9321 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’);
9322 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9323 if (!success)
9324 return false;
9325
9326 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9327
9328 EmulateInstruction::Context context;
9329 context.type = eContextSubtraction;
9330 Register sp_reg;
9331 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
9332 Register dwarf_reg;
9333 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
9334 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9335
Caroline Ticeef440002011-03-30 05:40:56 +00009336 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009337 return false;
9338 }
9339 return true;
9340}
9341
9342
9343// A8.6.7 ADD (register-shifted register)
9344bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009345EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009346{
9347#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009348 if ConditionPassed() then
9349 EncodingSpecificOperations();
9350 shift_n = UInt(R[s]<7:0>);
9351 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9352 (result, carry, overflow) = AddWithCarry(R[n], shifted, 0’);
9353 R[d] = result;
9354 if setflags then
9355 APSR.N = result<31>;
9356 APSR.Z = IsZeroBit(result);
9357 APSR.C = carry;
9358 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009359#endif
9360
Caroline Ticec08ed382011-03-29 23:03:16 +00009361 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009362
9363 if (ConditionPassed(opcode))
9364 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009365 uint32_t d;
9366 uint32_t n;
9367 uint32_t m;
9368 uint32_t s;
9369 bool setflags;
9370 ARM_ShifterType shift_t;
9371
Caroline Ticed05b4902011-03-29 21:24:06 +00009372 switch (encoding)
9373 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009374 case eEncodingA1:
9375 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9376 d = Bits32 (opcode, 15, 12);
9377 n = Bits32 (opcode, 19, 16);
9378 m = Bits32 (opcode, 3, 0);
9379 s = Bits32 (opcode, 11, 8);
9380
9381 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type);
9382 setflags = BitIsSet (opcode, 20);
9383 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9384
9385 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9386 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9387 return false;
9388 break;
9389
9390 default:
9391 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009392 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009393
9394 // shift_n = UInt(R[s]<7:0>);
9395 uint32_t Rs = ReadCoreReg (s, &success);
9396 if (!success)
9397 return false;
9398
9399 uint32_t shift_n = Bits32 (Rs, 7, 0);
9400
9401 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9402 uint32_t Rm = ReadCoreReg (m, &success);
9403 if (!success)
9404 return false;
9405
9406 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9407
9408 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’);
9409 uint32_t Rn = ReadCoreReg (n, &success);
9410 if (!success)
9411 return false;
9412
9413 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9414
9415 // R[d] = result;
9416 EmulateInstruction::Context context;
9417 context.type = eContextAddition;
9418 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009419 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
Caroline Ticec08ed382011-03-29 23:03:16 +00009420 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009421 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009422
9423 context.SetRegisterRegisterOperands (reg_n, reg_m);
9424
9425 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9426 return false;
9427
9428 // if setflags then
9429 // APSR.N = result<31>;
9430 // APSR.Z = IsZeroBit(result);
9431 // APSR.C = carry;
9432 // APSR.V = overflow;
9433 if (setflags)
9434 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009435 }
9436 return true;
9437}
9438
9439// A8.6.213 SUB (register)
9440bool
9441EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9442{
9443#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009444 if ConditionPassed() then
9445 EncodingSpecificOperations();
9446 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9447 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), 1’);
9448 if d == 15 then // Can only occur for ARM encoding
9449 ALUWritePC(result); // setflags is always FALSE here
9450 else
9451 R[d] = result;
9452 if setflags then
9453 APSR.N = result<31>;
9454 APSR.Z = IsZeroBit(result);
9455 APSR.C = carry;
9456 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009457#endif
9458
Caroline Tice4cccd532011-03-29 23:44:20 +00009459 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009460
9461 if (ConditionPassed(opcode))
9462 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009463 uint32_t d;
9464 uint32_t n;
9465 uint32_t m;
9466 bool setflags;
9467 ARM_ShifterType shift_t;
9468 uint32_t shift_n;
9469
Caroline Ticed05b4902011-03-29 21:24:06 +00009470 switch (encoding)
9471 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009472 case eEncodingT1:
9473 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9474 d = Bits32 (opcode, 2, 0);
9475 n = Bits32 (opcode, 5, 3);
9476 m = Bits32 (opcode, 8, 6);
9477 setflags = !InITBlock();
9478
9479 // (shift_t, shift_n) = (SRType_LSL, 0);
9480 shift_t = SRType_LSL;
9481 shift_n = 0;
9482
9483 break;
9484
9485 case eEncodingT2:
9486 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register);
9487 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9488 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9489 d = Bits32 (opcode, 11, 8);
9490 n = Bits32 (opcode, 19, 16);
9491 m = Bits32 (opcode, 3, 0);
9492 setflags = BitIsSet (opcode, 20);
9493
9494 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9495 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9496
9497 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9498 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9499 return false;
9500
9501 break;
9502
9503 case eEncodingA1:
Caroline Tice4cccd532011-03-29 23:44:20 +00009504 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9505 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9506 d = Bits32 (opcode, 15, 12);
9507 n = Bits32 (opcode, 19, 16);
9508 m = Bits32 (opcode, 3, 0);
9509 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009510
9511 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9512 if ((d == 15) && setflags)
9513 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009514
9515 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9516 shift_n = DecodeImmShiftARM (opcode, shift_t);
9517
9518 break;
9519
9520 default:
9521 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009522 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009523
9524 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9525 uint32_t Rm = ReadCoreReg (m, &success);
9526 if (!success)
9527 return false;
9528
9529 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9530
9531 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’);
9532 uint32_t Rn = ReadCoreReg (n, &success);
9533 if (!success)
9534 return false;
9535
9536 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9537
9538 // if d == 15 then // Can only occur for ARM encoding
9539 // ALUWritePC(result); // setflags is always FALSE here
9540 // else
9541 // R[d] = result;
9542 // if setflags then
9543 // APSR.N = result<31>;
9544 // APSR.Z = IsZeroBit(result);
9545 // APSR.C = carry;
9546 // APSR.V = overflow;
9547
9548 EmulateInstruction::Context context;
9549 context.type = eContextSubtraction;
9550 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009551 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Tice4cccd532011-03-29 23:44:20 +00009552 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009553 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009554 context.SetRegisterRegisterOperands (reg_n, reg_m);
9555
Caroline Ticeef440002011-03-30 05:40:56 +00009556 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009557 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009558 }
9559 return true;
9560}
Caroline Tice4cccd532011-03-29 23:44:20 +00009561
Caroline Ticed05b4902011-03-29 21:24:06 +00009562// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009563// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9564// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009565bool
9566EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9567{
9568#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009569 if ConditionPassed() then
9570 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9571 address = R[n] + imm32;
9572 if ExclusiveMonitorsPass(address,4) then
9573 MemA[address,4] = R[t];
9574 R[d] = 0;
9575 else
9576 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009577#endif
9578
Caroline Tice5168b6c2011-03-30 05:15:46 +00009579 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009580
9581 if (ConditionPassed(opcode))
9582 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009583 uint32_t d;
9584 uint32_t t;
9585 uint32_t n;
9586 uint32_t imm32;
9587 const uint32_t addr_byte_size = GetAddressByteSize();
9588
Caroline Ticed05b4902011-03-29 21:24:06 +00009589 switch (encoding)
9590 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009591 case eEncodingT1:
9592 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9593 d = Bits32 (opcode, 11, 8);
9594 t = Bits32 (opcode, 15, 12);
9595 n = Bits32 (opcode, 19, 16);
9596 imm32 = Bits32 (opcode, 7, 0) << 2;
9597
9598 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9599 if (BadReg (d) || BadReg (t) || (n == 15))
9600 return false;
9601
9602 // if d == n || d == t then UNPREDICTABLE;
9603 if ((d == n) || (d == t))
9604 return false;
9605
9606 break;
9607
9608 case eEncodingA1:
9609 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9610 d = Bits32 (opcode, 15, 12);
9611 t = Bits32 (opcode, 3, 0);
9612 n = Bits32 (opcode, 19, 16);
9613 imm32 = 0;
9614
9615 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9616 if ((d == 15) || (t == 15) || (n == 15))
9617 return false;
9618
9619 // if d == n || d == t then UNPREDICTABLE;
9620 if ((d == n) || (d == t))
9621 return false;
9622
9623 break;
9624
9625 default:
9626 return false;
9627 }
9628
9629 // address = R[n] + imm32;
9630 uint32_t Rn = ReadCoreReg (n, &success);
9631 if (!success)
9632 return false;
9633
9634 addr_t address = Rn + imm32;
9635
9636 Register base_reg;
9637 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9638 Register data_reg;
9639 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
9640 EmulateInstruction::Context context;
9641 context.type = eContextRegisterStore;
9642 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9643
9644 // if ExclusiveMonitorsPass(address,4) then
9645 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9646 // always return true.
9647 if (true)
9648 {
9649 // MemA[address,4] = R[t];
9650 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9651 if (!success)
9652 return false;
9653
9654 if (!MemAWrite (context, address, Rt, addr_byte_size))
9655 return false;
9656
9657 // R[d] = 0;
9658 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9659 return false;
9660 }
9661 else
9662 {
9663 // R[d] = 1;
9664 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9665 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009666 }
9667 }
9668 return true;
9669}
9670
9671// A8.6.197 STRB (immediate, ARM)
9672bool
9673EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9674{
9675#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009676 if ConditionPassed() then
9677 EncodingSpecificOperations();
9678 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9679 address = if index then offset_addr else R[n];
9680 MemU[address,1] = R[t]<7:0>;
9681 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009682#endif
9683
Caroline Ticeef440002011-03-30 05:40:56 +00009684 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009685
9686 if (ConditionPassed(opcode))
9687 {
Caroline Ticeef440002011-03-30 05:40:56 +00009688 uint32_t t;
9689 uint32_t n;
9690 uint32_t imm32;
9691 bool index;
9692 bool add;
9693 bool wback;
9694
Caroline Ticed05b4902011-03-29 21:24:06 +00009695 switch (encoding)
9696 {
Caroline Ticeef440002011-03-30 05:40:56 +00009697 case eEncodingA1:
9698 // if P == ‘0’ && W == ‘1’ then SEE STRBT;
9699 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9700 t = Bits32 (opcode, 15, 12);
9701 n = Bits32 (opcode, 19, 16);
9702 imm32 = Bits32 (opcode, 11, 0);
9703
9704 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9705 index = BitIsSet (opcode, 24);
9706 add = BitIsSet (opcode, 23);
9707 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9708
9709 // if t == 15 then UNPREDICTABLE;
9710 if (t == 15)
9711 return false;
9712
9713 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9714 if (wback && ((n == 15) || (n == t)))
9715 return false;
9716
9717 break;
9718
9719 default:
9720 return false;
9721 }
9722
9723 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9724 uint32_t Rn = ReadCoreReg (n, &success);
9725 if (!success)
9726 return false;
9727
9728 addr_t offset_addr;
9729 if (add)
9730 offset_addr = Rn + imm32;
9731 else
9732 offset_addr = Rn - imm32;
9733
9734 // address = if index then offset_addr else R[n];
9735 addr_t address;
9736 if (index)
9737 address = offset_addr;
9738 else
9739 address = Rn;
9740
9741 // MemU[address,1] = R[t]<7:0>;
9742 uint32_t Rt = ReadCoreReg (t, &success);
9743 if (!success)
9744 return false;
9745
9746 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009747 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticeef440002011-03-30 05:40:56 +00009748 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009749 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticeef440002011-03-30 05:40:56 +00009750 EmulateInstruction::Context context;
9751 context.type = eContextRegisterStore;
9752 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9753
9754 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9755 return false;
9756
9757 // if wback then R[n] = offset_addr;
9758 if (wback)
9759 {
Caroline Tice523c5542011-04-13 00:42:12 +00009760 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009761 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009762 }
9763 }
9764 return true;
9765}
9766
9767// A8.6.194 STR (immediate, ARM)
9768bool
9769EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9770{
9771#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009772 if ConditionPassed() then
9773 EncodingSpecificOperations();
9774 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9775 address = if index then offset_addr else R[n];
9776 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9777 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009778#endif
9779
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009780 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009781
9782 if (ConditionPassed(opcode))
9783 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009784 uint32_t t;
9785 uint32_t n;
9786 uint32_t imm32;
9787 bool index;
9788 bool add;
9789 bool wback;
9790
9791 const uint32_t addr_byte_size = GetAddressByteSize();
9792
Caroline Ticed05b4902011-03-29 21:24:06 +00009793 switch (encoding)
9794 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009795 case eEncodingA1:
9796 // if P == ‘0’ && W == ‘1’ then SEE STRT;
9797 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH;
9798 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9799 t = Bits32 (opcode, 15, 12);
9800 n = Bits32 (opcode, 19, 16);
9801 imm32 = Bits32 (opcode, 11, 0);
9802
9803 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9804 index = BitIsSet (opcode, 24);
9805 add = BitIsSet (opcode, 23);
9806 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9807
9808 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9809 if (wback && ((n == 15) || (n == t)))
9810 return false;
9811
9812 break;
9813
9814 default:
9815 return false;
9816 }
9817
9818 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9819 uint32_t Rn = ReadCoreReg (n, &success);
9820 if (!success)
9821 return false;
9822
9823 addr_t offset_addr;
9824 if (add)
9825 offset_addr = Rn + imm32;
9826 else
9827 offset_addr = Rn - imm32;
9828
9829 // address = if index then offset_addr else R[n];
9830 addr_t address;
9831 if (index)
9832 address = offset_addr;
9833 else
9834 address = Rn;
9835
9836 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009837 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009838 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009839 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009840 EmulateInstruction::Context context;
9841 context.type = eContextRegisterStore;
9842 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9843
9844 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9845 uint32_t Rt = ReadCoreReg (t, &success);
9846 if (!success)
9847 return false;
9848
9849 if (t == 15)
9850 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009851 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009852 if (!success)
9853 return false;
9854
9855 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9856 return false;
9857 }
9858 else
9859 {
9860 if (!MemUWrite (context, address, Rt, addr_byte_size))
9861 return false;
9862 }
9863
9864 // if wback then R[n] = offset_addr;
9865 if (wback)
9866 {
9867 context.type = eContextAdjustBaseRegister;
9868 context.SetImmediate (offset_addr);
9869
9870 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9871 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009872 }
9873 }
9874 return true;
9875}
9876
Caroline Ticed05b4902011-03-29 21:24:06 +00009877// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009878// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9879// 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 +00009880bool
9881EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9882{
9883#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009884 if ConditionPassed() then
9885 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9886 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9887 address = if index then offset_addr else R[n];
9888 R[t] = MemA[address,4];
9889 R[t2] = MemA[address+4,4];
9890 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009891#endif
9892
Caroline Tice1697dd72011-03-30 17:11:45 +00009893 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009894
9895 if (ConditionPassed(opcode))
9896 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009897 uint32_t t;
9898 uint32_t t2;
9899 uint32_t n;
9900 uint32_t imm32;
9901 bool index;
9902 bool add;
9903 bool wback;
9904
Caroline Ticed05b4902011-03-29 21:24:06 +00009905 switch (encoding)
9906 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009907 case eEncodingT1:
9908 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
9909 //if Rn == ‘1111’ then SEE LDRD (literal);
9910 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9911 t = Bits32 (opcode, 15, 12);
9912 t2 = Bits32 (opcode, 11, 8);
9913 n = Bits32 (opcode, 19, 16);
9914 imm32 = Bits32 (opcode, 7, 0) << 2;
9915
9916 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
9917 index = BitIsSet (opcode, 24);
9918 add = BitIsSet (opcode, 23);
9919 wback = BitIsSet (opcode, 21);
9920
9921 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9922 if (wback && ((n == t) || (n == t2)))
9923 return false;
9924
9925 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9926 if (BadReg (t) || BadReg (t2) || (t == t2))
9927 return false;
9928
9929 break;
9930
9931 case eEncodingA1:
9932 //if Rn == ‘1111’ then SEE LDRD (literal);
9933 //if Rt<0> == ‘1’ then UNPREDICTABLE;
9934 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9935 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009936 if (BitIsSet (t, 0))
9937 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009938 t2 = t + 1;
9939 n = Bits32 (opcode, 19, 16);
9940 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9941
9942 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9943 index = BitIsSet (opcode, 24);
9944 add = BitIsSet (opcode, 23);
9945 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9946
9947 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
9948 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9949 return false;
9950
9951 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9952 if (wback && ((n == t) || (n == t2)))
9953 return false;
9954
9955 //if t2 == 15 then UNPREDICTABLE;
9956 if (t2 == 15)
9957 return false;
9958
9959 break;
9960
9961 default:
9962 return false;
9963 }
9964
9965 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9966 uint32_t Rn = ReadCoreReg (n, &success);
9967 if (!success)
9968 return false;
9969
9970 addr_t offset_addr;
9971 if (add)
9972 offset_addr = Rn + imm32;
9973 else
9974 offset_addr = Rn - imm32;
9975
9976 //address = if index then offset_addr else R[n];
9977 addr_t address;
9978 if (index)
9979 address = offset_addr;
9980 else
9981 address = Rn;
9982
9983 //R[t] = MemA[address,4];
9984 Register base_reg;
9985 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9986
9987 EmulateInstruction::Context context;
9988 context.type = eContextRegisterLoad;
9989 context.SetRegisterPlusOffset (base_reg, address - Rn);
9990
9991 const uint32_t addr_byte_size = GetAddressByteSize();
9992 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
9993 if (!success)
9994 return false;
9995
9996 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
9997 return false;
9998
9999 //R[t2] = MemA[address+4,4];
10000
10001 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10002 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10003 if (!success)
10004 return false;
10005
10006 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10007 return false;
10008
10009 //if wback then R[n] = offset_addr;
10010 if (wback)
10011 {
10012 context.type = eContextAdjustBaseRegister;
10013 context.SetAddress (offset_addr);
10014
10015 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10016 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010017 }
10018 }
10019 return true;
10020}
10021
Caroline Ticed05b4902011-03-29 21:24:06 +000010022// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010023// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10024// 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 +000010025bool
10026EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10027{
10028#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010029 if ConditionPassed() then
10030 EncodingSpecificOperations();
10031 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10032 address = if index then offset_addr else R[n];
10033 R[t] = MemA[address,4];
10034 R[t2] = MemA[address+4,4];
10035 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010036#endif
10037
Caroline Ticeeab301f2011-03-30 17:54:52 +000010038 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010039
10040 if (ConditionPassed(opcode))
10041 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010042 uint32_t t;
10043 uint32_t t2;
10044 uint32_t n;
10045 uint32_t m;
10046 bool index;
10047 bool add;
10048 bool wback;
10049
Caroline Ticed05b4902011-03-29 21:24:06 +000010050 switch (encoding)
10051 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010052 case eEncodingA1:
10053 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10054 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10055 t = Bits32 (opcode, 15, 12);
10056 if (BitIsSet (t, 0))
10057 return false;
10058 t2 = t + 1;
10059 n = Bits32 (opcode, 19, 16);
10060 m = Bits32 (opcode, 3, 0);
10061
10062 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10063 index = BitIsSet (opcode, 24);
10064 add = BitIsSet (opcode, 23);
10065 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10066
10067 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10068 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10069 return false;
10070
10071 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10072 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10073 return false;
10074
10075 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10076 if (wback && ((n == 15) || (n == t) || (n == t2)))
10077 return false;
10078
10079 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10080 if ((ArchVersion() < 6) && wback && (m == n))
10081 return false;
10082 break;
10083
10084 default:
10085 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010086 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010087
Caroline Ticeeab301f2011-03-30 17:54:52 +000010088 uint32_t Rn = ReadCoreReg (n, &success);
10089 if (!success)
10090 return false;
10091 Register base_reg;
10092 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed05b4902011-03-29 21:24:06 +000010093
Caroline Ticeeab301f2011-03-30 17:54:52 +000010094 uint32_t Rm = ReadCoreReg (m, &success);
10095 if (!success)
10096 return false;
10097 Register offset_reg;
10098 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticed05b4902011-03-29 21:24:06 +000010099
Caroline Ticeeab301f2011-03-30 17:54:52 +000010100 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10101 addr_t offset_addr;
10102 if (add)
10103 offset_addr = Rn + Rm;
10104 else
10105 offset_addr = Rn - Rm;
10106
10107 // address = if index then offset_addr else R[n];
10108 addr_t address;
10109 if (index)
10110 address = offset_addr;
10111 else
10112 address = Rn;
10113
10114 EmulateInstruction::Context context;
10115 context.type = eContextRegisterLoad;
10116 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10117
10118 // R[t] = MemA[address,4];
10119 const uint32_t addr_byte_size = GetAddressByteSize();
10120 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10121 if (!success)
10122 return false;
10123
10124 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10125 return false;
10126
10127 // R[t2] = MemA[address+4,4];
10128
10129 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10130 if (!success)
10131 return false;
10132
10133 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10134 return false;
10135
10136 // if wback then R[n] = offset_addr;
10137 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010138 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010139 context.type = eContextAdjustBaseRegister;
10140 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010141
Caroline Ticeeab301f2011-03-30 17:54:52 +000010142 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10143 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010144 }
10145 }
10146 return true;
10147}
Caroline Ticed05b4902011-03-29 21:24:06 +000010148
10149// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010150// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10151// 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 +000010152bool
10153EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10154{
10155#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010156 if ConditionPassed() then
10157 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10158 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10159 address = if index then offset_addr else R[n];
10160 MemA[address,4] = R[t];
10161 MemA[address+4,4] = R[t2];
10162 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010163#endif
10164
Caroline Tice74467fe2011-03-30 19:02:56 +000010165 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010166
Caroline Tice74467fe2011-03-30 19:02:56 +000010167 if (ConditionPassed(opcode))
10168 {
10169 uint32_t t;
10170 uint32_t t2;
10171 uint32_t n;
10172 uint32_t imm32;
10173 bool index;
10174 bool add;
10175 bool wback;
10176
10177 switch (encoding)
10178 {
10179 case eEncodingT1:
10180 // if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10181 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10182 t = Bits32 (opcode, 15, 12);
10183 t2 = Bits32 (opcode, 11, 8);
10184 n = Bits32 (opcode, 19, 16);
10185 imm32 = Bits32 (opcode, 7, 0) << 2;
10186
10187 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
10188 index = BitIsSet (opcode, 24);
10189 add = BitIsSet (opcode, 23);
10190 wback = BitIsSet (opcode, 21);
10191
10192 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10193 if (wback && ((n == t) || (n == t2)))
10194 return false;
10195
10196 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10197 if ((n == 15) || BadReg (t) || BadReg (t2))
10198 return false;
10199
10200 break;
10201
10202 case eEncodingA1:
10203 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10204 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10205 t = Bits32 (opcode, 15, 12);
10206 if (BitIsSet (t, 0))
10207 return false;
10208
10209 t2 = t + 1;
10210 n = Bits32 (opcode, 19, 16);
10211 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10212
10213 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10214 index = BitIsSet (opcode, 24);
10215 add = BitIsSet (opcode, 23);
10216 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10217
10218 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10219 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10220 return false;
10221
10222 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10223 if (wback && ((n == 15) || (n == t) || (n == t2)))
10224 return false;
10225
10226 // if t2 == 15 then UNPREDICTABLE;
10227 if (t2 == 15)
10228 return false;
10229
10230 break;
10231
10232 default:
10233 return false;
10234 }
10235
10236 Register base_reg;
10237 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10238
10239 uint32_t Rn = ReadCoreReg (n, &success);
10240 if (!success)
10241 return false;
10242
10243 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10244 addr_t offset_addr;
10245 if (add)
10246 offset_addr = Rn + imm32;
10247 else
10248 offset_addr = Rn - imm32;
10249
10250 //address = if index then offset_addr else R[n];
10251 addr_t address;
10252 if (index)
10253 address = offset_addr;
10254 else
10255 address = Rn;
10256
10257 //MemA[address,4] = R[t];
10258 Register data_reg;
10259 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10260
10261 uint32_t data = ReadCoreReg (t, &success);
10262 if (!success)
10263 return false;
10264
10265 EmulateInstruction::Context context;
10266 context.type = eContextRegisterStore;
10267 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10268
10269 const uint32_t addr_byte_size = GetAddressByteSize();
10270
10271 if (!MemAWrite (context, address, data, addr_byte_size))
10272 return false;
10273
10274 //MemA[address+4,4] = R[t2];
10275 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t2);
10276 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10277
10278 data = ReadCoreReg (t2, &success);
10279 if (!success)
10280 return false;
10281
10282 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10283 return false;
10284
10285 //if wback then R[n] = offset_addr;
10286 if (wback)
10287 {
10288 context.type = eContextAdjustBaseRegister;
10289 context.SetAddress (offset_addr);
10290
10291 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10292 return false;
10293 }
10294 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010295 return true;
10296}
10297
10298
10299// A8.6.201 STRD (register)
10300bool
10301EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10302{
10303#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010304 if ConditionPassed() then
10305 EncodingSpecificOperations();
10306 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10307 address = if index then offset_addr else R[n];
10308 MemA[address,4] = R[t];
10309 MemA[address+4,4] = R[t2];
10310 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010311#endif
10312
Caroline Tice74467fe2011-03-30 19:02:56 +000010313 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010314
Caroline Tice74467fe2011-03-30 19:02:56 +000010315 if (ConditionPassed(opcode))
10316 {
10317 uint32_t t;
10318 uint32_t t2;
10319 uint32_t n;
10320 uint32_t m;
10321 bool index;
10322 bool add;
10323 bool wback;
10324
10325 switch (encoding)
10326 {
10327 case eEncodingA1:
10328 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10329 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10330 t = Bits32 (opcode, 15, 12);
10331 if (BitIsSet (t, 0))
10332 return false;
10333
10334 t2 = t+1;
10335 n = Bits32 (opcode, 19, 16);
10336 m = Bits32 (opcode, 3, 0);
10337
10338 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10339 index = BitIsSet (opcode, 24);
10340 add = BitIsSet (opcode, 23);
10341 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10342
10343 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10344 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10345 return false;
10346
10347 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10348 if ((t2 == 15) || (m == 15))
10349 return false;
10350
10351 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10352 if (wback && ((n == 15) || (n == t) || (n == t2)))
10353 return false;
10354
10355 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010356 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010357 return false;
10358
10359 break;
10360
10361 default:
10362 return false;
10363 }
10364
10365 Register base_reg;
10366 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10367 Register offset_reg;
10368 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
10369 Register data_reg;
10370 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10371
10372 uint32_t Rn = ReadCoreReg (n, &success);
10373 if (!success)
10374 return false;
10375
10376 uint32_t Rm = ReadCoreReg (m, &success);
10377 if (!success)
10378 return false;
10379
10380 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10381 addr_t offset_addr;
10382 if (add)
10383 offset_addr = Rn + Rm;
10384 else
10385 offset_addr = Rn - Rm;
10386
10387 // address = if index then offset_addr else R[n];
10388 addr_t address;
10389 if (index)
10390 address = offset_addr;
10391 else
10392 address = Rn;
10393 // MemA[address,4] = R[t];
10394 uint32_t Rt = ReadCoreReg (t, &success);
10395 if (!success)
10396 return false;
10397
10398 EmulateInstruction::Context context;
10399 context.type = eContextRegisterStore;
10400 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10401
10402 const uint32_t addr_byte_size = GetAddressByteSize();
10403
10404 if (!MemAWrite (context, address, Rt, addr_byte_size))
10405 return false;
10406
10407 // MemA[address+4,4] = R[t2];
10408 uint32_t Rt2 = ReadCoreReg (t2, &success);
10409 if (!success)
10410 return false;
10411
10412 data_reg.num = dwarf_r0 + t2;
10413
10414 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10415
10416 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10417 return false;
10418
10419 // if wback then R[n] = offset_addr;
10420 if (wback)
10421 {
10422 context.type = eContextAdjustBaseRegister;
10423 context.SetAddress (offset_addr);
10424
10425 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10426 return false;
10427
10428 }
10429 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010430 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010431}
10432
Caroline Tice4f605582011-03-31 00:02:51 +000010433// A8.6.319 VLDM
10434// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10435// an ARM core register.
10436bool
10437EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10438{
10439#if 0
10440 if ConditionPassed() then
10441 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10442 address = if add then R[n] else R[n]-imm32;
10443 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10444 for r = 0 to regs-1
10445 if single_regs then
10446 S[d+r] = MemA[address,4]; address = address+4;
10447 else
10448 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10449 // Combine the word-aligned words in the correct order for current endianness.
10450 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10451#endif
10452
10453 bool success = false;
10454
10455 if (ConditionPassed(opcode))
10456 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010457 bool single_regs;
10458 bool add;
10459 bool wback;
10460 uint32_t d;
10461 uint32_t n;
10462 uint32_t imm32;
10463 uint32_t regs;
10464
Caroline Tice4f605582011-03-31 00:02:51 +000010465 switch (encoding)
10466 {
10467 case eEncodingT1:
10468 case eEncodingA1:
10469 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10470 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10471 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10472 // if P == U && W == ‘1’ then UNDEFINED;
10473 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10474 return false;
10475
10476 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10477 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10478 single_regs = false;
10479 add = BitIsSet (opcode, 23);
10480 wback = BitIsSet (opcode, 21);
10481
10482 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10483 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10484 n = Bits32 (opcode, 19, 16);
10485 imm32 = Bits32 (opcode, 7, 0) << 2;
10486
10487 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FLDMX”.
10488 regs = Bits32 (opcode, 7, 0) / 2;
10489
10490 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10491 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10492 return false;
10493
10494 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10495 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10496 return false;
10497
10498 break;
10499
10500 case eEncodingT2:
10501 case eEncodingA2:
10502 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10503 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10504 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10505 // if P == U && W == ‘1’ then UNDEFINED;
10506 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10507 return false;
10508
10509 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10510 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10511 single_regs = true;
10512 add = BitIsSet (opcode, 23);
10513 wback = BitIsSet (opcode, 21);
10514 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10515 n = Bits32 (opcode, 19, 16);
10516
10517 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10518 imm32 = Bits32 (opcode, 7, 0) << 2;
10519 regs = Bits32 (opcode, 7, 0);
10520
10521 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10522 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10523 return false;
10524
10525 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10526 if ((regs == 0) || ((d + regs) > 32))
10527 return false;
10528 break;
10529
10530 default:
10531 return false;
10532 }
10533
10534 Register base_reg;
10535 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10536
10537 uint32_t Rn = ReadCoreReg (n, &success);
10538 if (!success)
10539 return false;
10540
10541 // address = if add then R[n] else R[n]-imm32;
10542 addr_t address;
10543 if (add)
10544 address = Rn;
10545 else
10546 address = Rn - imm32;
10547
10548 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10549 EmulateInstruction::Context context;
10550
10551 if (wback)
10552 {
10553 uint32_t value;
10554 if (add)
10555 value = Rn + imm32;
10556 else
10557 value = Rn - imm32;
10558
10559 context.type = eContextAdjustBaseRegister;
10560 context.SetImmediateSigned (value - Rn);
10561 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10562 return false;
10563
10564 }
10565
10566 const uint32_t addr_byte_size = GetAddressByteSize();
10567 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10568
10569 context.type = eContextRegisterLoad;
10570
10571 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010572 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010573 {
10574 if (single_regs)
10575 {
10576 // S[d+r] = MemA[address,4]; address = address+4;
10577 context.SetRegisterPlusOffset (base_reg, address - Rn);
10578
10579 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10580 if (!success)
10581 return false;
10582
10583 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10584 return false;
10585
10586 address = address + 4;
10587 }
10588 else
10589 {
10590 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10591 context.SetRegisterPlusOffset (base_reg, address - Rn);
10592 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10593 if (!success)
10594 return false;
10595
10596 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10597 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10598 if (!success)
10599 return false;
10600
10601 address = address + 8;
10602 // // Combine the word-aligned words in the correct order for current endianness.
10603 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10604 uint64_t data;
10605 if (m_byte_order == eByteOrderBig)
10606 {
10607 data = word1;
10608 data = (data << 32) | word2;
10609 }
10610 else
10611 {
10612 data = word2;
10613 data = (data << 32) | word1;
10614 }
10615
10616 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10617 return false;
10618 }
10619 }
10620 }
10621 return true;
10622}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010623
10624// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010625// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10626// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010627bool
10628EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10629{
10630#if 0
10631 if ConditionPassed() then
10632 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10633 address = if add then R[n] else R[n]-imm32;
10634 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10635 for r = 0 to regs-1
10636 if single_regs then
10637 MemA[address,4] = S[d+r]; address = address+4;
10638 else
10639 // Store as two word-aligned words in the correct order for current endianness.
10640 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10641 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10642 address = address+8;
10643#endif
10644
10645 bool success = false;
10646
10647 if (ConditionPassed (opcode))
10648 {
10649 bool single_regs;
10650 bool add;
10651 bool wback;
10652 uint32_t d;
10653 uint32_t n;
10654 uint32_t imm32;
10655 uint32_t regs;
10656
10657 switch (encoding)
10658 {
10659 case eEncodingT1:
10660 case eEncodingA1:
10661 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10662 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10663 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10664 // if P == U && W == ‘1’ then UNDEFINED;
10665 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10666 return false;
10667
10668 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10669 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10670 single_regs = false;
10671 add = BitIsSet (opcode, 23);
10672 wback = BitIsSet (opcode, 21);
10673
10674 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10675 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10676 n = Bits32 (opcode, 19, 16);
10677 imm32 = Bits32 (opcode, 7, 0) << 2;
10678
10679 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FSTMX”.
10680 regs = Bits32 (opcode, 7, 0) / 2;
10681
10682 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10683 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10684 return false;
10685
10686 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10687 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10688 return false;
10689
10690 break;
10691
10692 case eEncodingT2:
10693 case eEncodingA2:
10694 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10695 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10696 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10697 // if P == U && W == ‘1’ then UNDEFINED;
10698 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10699 return false;
10700
10701 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10702 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10703 single_regs = true;
10704 add = BitIsSet (opcode, 23);
10705 wback = BitIsSet (opcode, 21);
10706 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10707 n = Bits32 (opcode, 19, 16);
10708
10709 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10710 imm32 = Bits32 (opcode, 7, 0) << 2;
10711 regs = Bits32 (opcode, 7, 0);
10712
10713 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10714 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10715 return false;
10716
10717 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10718 if ((regs == 0) || ((d + regs) > 32))
10719 return false;
10720
10721 break;
10722
10723 default:
10724 return false;
10725 }
10726
10727 Register base_reg;
10728 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10729
10730 uint32_t Rn = ReadCoreReg (n, &success);
10731 if (!success)
10732 return false;
10733
10734 // address = if add then R[n] else R[n]-imm32;
10735 addr_t address;
10736 if (add)
10737 address = Rn;
10738 else
10739 address = Rn - imm32;
10740
10741 EmulateInstruction::Context context;
10742 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10743 if (wback)
10744 {
10745 uint32_t value;
10746 if (add)
10747 value = Rn + imm32;
10748 else
10749 value = Rn - imm32;
10750
10751 context.type = eContextAdjustBaseRegister;
10752 context.SetRegisterPlusOffset (base_reg, value - Rn);
10753
10754 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10755 return false;
10756 }
10757
10758 const uint32_t addr_byte_size = GetAddressByteSize();
10759 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10760
10761 context.type = eContextRegisterStore;
10762 // for r = 0 to regs-1
10763 for (int r = 0; r < regs; ++r)
10764 {
10765 Register data_reg;
10766 data_reg.SetRegister (eRegisterKindDWARF, 0);
10767 if (single_regs)
10768 {
10769 // MemA[address,4] = S[d+r]; address = address+4;
10770 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10771 if (!success)
10772 return false;
10773
10774 data_reg.num = start_reg + d + r;
10775 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10776 if (!MemAWrite (context, address, data, addr_byte_size))
10777 return false;
10778
10779 address = address + 4;
10780 }
10781 else
10782 {
10783 // // Store as two word-aligned words in the correct order for current endianness.
10784 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10785 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10786 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10787 if (!success)
10788 return false;
10789
10790 data_reg.num = start_reg + d + r;
10791
10792 if (m_byte_order == eByteOrderBig)
10793 {
10794 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10795 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10796 return false;
10797
10798 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10799 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10800 return false;
10801 }
10802 else
10803 {
10804 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10805 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10806 return false;
10807
10808 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10809 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10810 return false;
10811 }
10812 // address = address+8;
10813 address = address + 8;
10814 }
10815 }
10816 }
10817 return true;
10818}
10819
Caroline Tice917ad352011-03-31 05:05:30 +000010820// A8.6.320
10821// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10822// an optional offset.
10823bool
10824EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10825{
10826#if 0
10827 if ConditionPassed() then
10828 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10829 base = if n == 15 then Align(PC,4) else R[n];
10830 address = if add then (base + imm32) else (base - imm32);
10831 if single_reg then
10832 S[d] = MemA[address,4];
10833 else
10834 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10835 // Combine the word-aligned words in the correct order for current endianness.
10836 D[d] = if BigEndian() then word1:word2 else word2:word1;
10837#endif
10838
10839 bool success = false;
10840
10841 if (ConditionPassed (opcode))
10842 {
10843 bool single_reg;
10844 bool add;
10845 uint32_t imm32;
10846 uint32_t d;
10847 uint32_t n;
10848
10849 switch (encoding)
10850 {
10851 case eEncodingT1:
10852 case eEncodingA1:
10853 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10854 single_reg = false;
10855 add = BitIsSet (opcode, 23);
10856 imm32 = Bits32 (opcode, 7, 0) << 2;
10857
10858 // d = UInt(D:Vd); n = UInt(Rn);
10859 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10860 n = Bits32 (opcode, 19, 16);
10861
10862 break;
10863
10864 case eEncodingT2:
10865 case eEncodingA2:
10866 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10867 single_reg = true;
10868 add = BitIsSet (opcode, 23);
10869 imm32 = Bits32 (opcode, 7, 0) << 2;
10870
10871 // d = UInt(Vd:D); n = UInt(Rn);
10872 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10873 n = Bits32 (opcode, 19, 16);
10874
10875 break;
10876
10877 default:
10878 return false;
10879 }
10880 Register base_reg;
10881 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10882
10883 uint32_t Rn = ReadCoreReg (n, &success);
10884 if (!success)
10885 return false;
10886
10887 // base = if n == 15 then Align(PC,4) else R[n];
10888 uint32_t base;
10889 if (n == 15)
10890 base = AlignPC (Rn);
10891 else
10892 base = Rn;
10893
10894 // address = if add then (base + imm32) else (base - imm32);
10895 addr_t address;
10896 if (add)
10897 address = base + imm32;
10898 else
10899 address = base - imm32;
10900
10901 const uint32_t addr_byte_size = GetAddressByteSize();
10902 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
10903
10904 EmulateInstruction::Context context;
10905 context.type = eContextRegisterLoad;
10906 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010907
Caroline Tice917ad352011-03-31 05:05:30 +000010908 if (single_reg)
10909 {
10910 // S[d] = MemA[address,4];
10911 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10912 if (!success)
10913 return false;
10914
10915 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
10916 return false;
10917 }
10918 else
10919 {
10920 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
10921 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10922 if (!success)
10923 return false;
10924
10925 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
10926 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10927 if (!success)
10928 return false;
10929 // // Combine the word-aligned words in the correct order for current endianness.
10930 // D[d] = if BigEndian() then word1:word2 else word2:word1;
10931 uint64_t data64;
10932 if (m_byte_order == eByteOrderBig)
10933 {
10934 data64 = word1;
10935 data64 = (data64 << 32) | word2;
10936 }
10937 else
10938 {
10939 data64 = word2;
10940 data64 = (data64 << 32) | word1;
10941 }
10942
10943 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
10944 return false;
10945 }
10946 }
10947 return true;
10948}
Caroline Tice424652f2011-03-31 05:38:36 +000010949
10950// A8.6.400 VSTR
10951// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
10952// optional offset.
10953bool
10954EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
10955{
10956#if 0
10957 if ConditionPassed() then
10958 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10959 address = if add then (R[n] + imm32) else (R[n] - imm32);
10960 if single_reg then
10961 MemA[address,4] = S[d];
10962 else
10963 // Store as two word-aligned words in the correct order for current endianness.
10964 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
10965 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
10966#endif
10967
10968 bool success = false;
10969
10970 if (ConditionPassed (opcode))
10971 {
10972 bool single_reg;
10973 bool add;
10974 uint32_t imm32;
10975 uint32_t d;
10976 uint32_t n;
10977
10978 switch (encoding)
10979 {
10980 case eEncodingT1:
10981 case eEncodingA1:
10982 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10983 single_reg = false;
10984 add = BitIsSet (opcode, 23);
10985 imm32 = Bits32 (opcode, 7, 0) << 2;
10986
10987 // d = UInt(D:Vd); n = UInt(Rn);
10988 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10989 n = Bits32 (opcode, 19, 16);
10990
10991 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
10992 if ((n == 15) && (CurrentInstrSet() != eModeARM))
10993 return false;
10994
10995 break;
10996
10997 case eEncodingT2:
10998 case eEncodingA2:
10999 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
11000 single_reg = true;
11001 add = BitIsSet (opcode, 23);
11002 imm32 = Bits32 (opcode, 7, 0) << 2;
11003
11004 // d = UInt(Vd:D); n = UInt(Rn);
11005 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11006 n = Bits32 (opcode, 19, 16);
11007
11008 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11009 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11010 return false;
11011
11012 break;
11013
11014 default:
11015 return false;
11016 }
11017
11018 Register base_reg;
11019 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11020
11021 uint32_t Rn = ReadCoreReg (n, &success);
11022 if (!success)
11023 return false;
11024
11025 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11026 addr_t address;
11027 if (add)
11028 address = Rn + imm32;
11029 else
11030 address = Rn - imm32;
11031
11032 const uint32_t addr_byte_size = GetAddressByteSize();
11033 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11034
11035 Register data_reg;
11036 data_reg.SetRegister (eRegisterKindDWARF, start_reg + d);
11037 EmulateInstruction::Context context;
11038 context.type = eContextRegisterStore;
11039 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11040
11041 if (single_reg)
11042 {
11043 // MemA[address,4] = S[d];
11044 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11045 if (!success)
11046 return false;
11047
11048 if (!MemAWrite (context, address, data, addr_byte_size))
11049 return false;
11050 }
11051 else
11052 {
11053 // // Store as two word-aligned words in the correct order for current endianness.
11054 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11055 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11056 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11057 if (!success)
11058 return false;
11059
11060 if (m_byte_order == eByteOrderBig)
11061 {
11062 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11063 return false;
11064
11065 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11066 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11067 return false;
11068 }
11069 else
11070 {
11071 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11072 return false;
11073
11074 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11075 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11076 return false;
11077 }
11078 }
11079 }
11080 return true;
11081}
Caroline Tice9121b352011-03-31 16:41:19 +000011082
11083// A8.6.307 VLDI1 (multiple single elements)
11084// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11085// element of each register is loaded.
11086bool
11087EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11088{
11089#if 0
11090 if ConditionPassed() then
11091 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11092 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11093 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11094 for r = 0 to regs-1
11095 for e = 0 to elements-1
11096 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11097 address = address + ebytes;
11098#endif
11099
11100 bool success = false;
11101
11102 if (ConditionPassed (opcode))
11103 {
11104 uint32_t regs;
11105 uint32_t alignment;
11106 uint32_t ebytes;
11107 uint32_t esize;
11108 uint32_t elements;
11109 uint32_t d;
11110 uint32_t n;
11111 uint32_t m;
11112 bool wback;
11113 bool register_index;
11114
11115 switch (encoding)
11116 {
11117 case eEncodingT1:
11118 case eEncodingA1:
11119 {
11120 // case type of
11121 // when ‘0111’
11122 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11123 // when ‘1010’
11124 // regs = 2; if align == ‘11’ then UNDEFINED;
11125 // when ‘0110’
11126 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11127 // when ‘0010’
11128 // regs = 4;
11129 // otherwise
11130 // SEE “Related encodings”;
11131 uint32_t type = Bits32 (opcode, 11, 8);
11132 uint32_t align = Bits32 (opcode, 5, 4);
11133 if (type == 7) // '0111'
11134 {
11135 regs = 1;
11136 if (BitIsSet (align, 1))
11137 return false;
11138 }
11139 else if (type == 10) // '1010'
11140 {
11141 regs = 2;
11142 if (align == 3)
11143 return false;
11144
11145 }
11146 else if (type == 6) // '0110'
11147 {
11148 regs = 3;
11149 if (BitIsSet (align, 1))
11150 return false;
11151 }
11152 else if (type == 2) // '0010'
11153 {
11154 regs = 4;
11155 }
11156 else
11157 return false;
11158
11159 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11160 if (align == 0)
11161 alignment = 1;
11162 else
11163 alignment = 4 << align;
11164
11165 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11166 ebytes = 1 << Bits32 (opcode, 7, 6);
11167 esize = 8 * ebytes;
11168 elements = 8 / ebytes;
11169
11170 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11171 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11172 n = Bits32 (opcode, 19, 15);
11173 m = Bits32 (opcode, 3, 0);
11174
11175 // wback = (m != 15); register_index = (m != 15 && m != 13);
11176 wback = (m != 15);
11177 register_index = ((m != 15) && (m != 13));
11178
11179 // if d+regs > 32 then UNPREDICTABLE;
11180 if ((d + regs) > 32)
11181 return false;
11182 }
11183 break;
11184
11185 default:
11186 return false;
11187 }
11188
11189 Register base_reg;
11190 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11191
11192 uint32_t Rn = ReadCoreReg (n, &success);
11193 if (!success)
11194 return false;
11195
11196 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11197 addr_t address = Rn;
11198 if ((address % alignment) != 0)
11199 return false;
11200
11201 EmulateInstruction::Context context;
11202 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11203 if (wback)
11204 {
11205 uint32_t Rm = ReadCoreReg (m, &success);
11206 if (!success)
11207 return false;
11208
11209 uint32_t offset;
11210 if (register_index)
11211 offset = Rm;
11212 else
11213 offset = 8 * regs;
11214
11215 uint32_t value = Rn + offset;
11216 context.type = eContextAdjustBaseRegister;
11217 context.SetRegisterPlusOffset (base_reg, offset);
11218
11219 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11220 return false;
11221
11222 }
11223
11224 // for r = 0 to regs-1
11225 for (int r = 0; r < regs; ++r)
11226 {
11227 // for e = 0 to elements-1
11228 uint64_t assembled_data = 0;
11229 for (int e = 0; e < elements; ++e)
11230 {
11231 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11232 context.type = eContextRegisterLoad;
11233 context.SetRegisterPlusOffset (base_reg, address - Rn);
11234 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11235 if (!success)
11236 return false;
11237
11238 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11239
11240 // address = address + ebytes;
11241 address = address + ebytes;
11242 }
11243 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11244 return false;
11245 }
11246 }
11247 return true;
11248}
11249
Caroline Ticeb6281b12011-03-31 17:58:23 +000011250// A8.6.308 VLD1 (single element to one lane)
11251//
11252bool
11253EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11254{
11255#if 0
11256 if ConditionPassed() then
11257 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11258 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11259 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11260 Elem[D[d],index,esize] = MemU[address,ebytes];
11261#endif
11262
11263 bool success = false;
11264
11265 if (ConditionPassed (opcode))
11266 {
11267 uint32_t ebytes;
11268 uint32_t esize;
11269 uint32_t index;
11270 uint32_t alignment;
11271 uint32_t d;
11272 uint32_t n;
11273 uint32_t m;
11274 bool wback;
11275 bool register_index;
11276
11277 switch (encoding)
11278 {
11279 case eEncodingT1:
11280 case eEncodingA1:
11281 {
11282 uint32_t size = Bits32 (opcode, 11, 10);
11283 uint32_t index_align = Bits32 (opcode, 7, 4);
11284 // if size == ‘11’ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011285 if (size == 3)
11286 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011287 // case size of
11288 if (size == 0) // when '00'
11289 {
11290 // if index_align<0> != ‘0’ then UNDEFINED;
11291 if (BitIsClear (index_align, 0))
11292 return false;
11293
11294 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11295 ebytes = 1;
11296 esize = 8;
11297 index = Bits32 (index_align, 3, 1);
11298 alignment = 1;
11299 }
11300 else if (size == 1) // when ‘01’
11301 {
11302 // if index_align<1> != ‘0’ then UNDEFINED;
11303 if (BitIsClear (index_align, 1))
11304 return false;
11305
11306 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11307 ebytes = 2;
11308 esize = 16;
11309 index = Bits32 (index_align, 3, 2);
11310
11311 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11312 if (BitIsClear (index_align, 0))
11313 alignment = 1;
11314 else
11315 alignment = 2;
11316 }
11317 else if (size == 2) // when ‘10’
11318 {
11319 // if index_align<2> != ‘0’ then UNDEFINED;
11320 if (BitIsClear (index_align, 2))
11321 return false;
11322
11323 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11324 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11325 return false;
11326
11327 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11328 ebytes = 4;
11329 esize = 32;
11330 index = Bit32 (index_align, 3);
11331
11332 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11333 if (Bits32 (index_align, 1, 0) == 0)
11334 alignment = 1;
11335 else
11336 alignment = 4;
11337 }
11338 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11339 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11340 n = Bits32 (opcode, 19, 16);
11341 m = Bits32 (opcode, 3, 0);
11342
11343 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11344 wback = (m != 15);
11345 register_index = ((m != 15) && (m != 13));
11346
11347 if (n == 15)
11348 return false;
11349
11350 }
11351 break;
11352
11353 default:
11354 return false;
11355 }
11356
11357 Register base_reg;
11358 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11359
11360 uint32_t Rn = ReadCoreReg (n, &success);
11361 if (!success)
11362 return false;
11363
11364 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11365 addr_t address = Rn;
11366 if ((address % alignment) != 0)
11367 return false;
11368
11369 EmulateInstruction::Context context;
11370 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11371 if (wback)
11372 {
11373 uint32_t Rm = ReadCoreReg (m, &success);
11374 if (!success)
11375 return false;
11376
11377 uint32_t offset;
11378 if (register_index)
11379 offset = Rm;
11380 else
11381 offset = ebytes;
11382
11383 uint32_t value = Rn + offset;
11384
11385 context.type = eContextAdjustBaseRegister;
11386 context.SetRegisterPlusOffset (base_reg, offset);
11387
11388 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11389 return false;
11390 }
11391
11392 // Elem[D[d],index,esize] = MemU[address,ebytes];
11393 uint32_t element = MemURead (context, address, esize, 0, &success);
11394 if (!success)
11395 return false;
11396
11397 element = element << (index * esize);
11398
11399 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11400 if (!success)
11401 return false;
11402
11403 uint64_t all_ones = -1;
11404 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11405 // at element & to the right of element.
11406 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011407 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 +000011408 // now mask should be 0's where element goes & 1's
11409 // everywhere else.
11410
11411 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11412 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11413
11414 context.type = eContextRegisterLoad;
11415 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11416 return false;
11417 }
11418 return true;
11419}
11420
Caroline Tice1e542e32011-03-31 18:44:04 +000011421// A8.6.391 VST1 (multiple single elements)
11422// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11423// interleaving. Every element of each register is stored.
11424bool
11425EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11426{
11427#if 0
11428 if ConditionPassed() then
11429 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11430 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11431 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11432 for r = 0 to regs-1
11433 for e = 0 to elements-1
11434 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11435 address = address + ebytes;
11436#endif
11437
11438 bool success = false;
11439
11440 if (ConditionPassed (opcode))
11441 {
11442 uint32_t regs;
11443 uint32_t alignment;
11444 uint32_t ebytes;
11445 uint32_t esize;
11446 uint32_t elements;
11447 uint32_t d;
11448 uint32_t n;
11449 uint32_t m;
11450 bool wback;
11451 bool register_index;
11452
11453 switch (encoding)
11454 {
11455 case eEncodingT1:
11456 case eEncodingA1:
11457 {
11458 uint32_t type = Bits32 (opcode, 11, 8);
11459 uint32_t align = Bits32 (opcode, 5, 4);
11460
11461 // case type of
11462 if (type == 7) // when ‘0111’
11463 {
11464 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11465 regs = 1;
11466 if (BitIsSet (align, 1))
11467 return false;
11468 }
11469 else if (type == 10) // when ‘1010’
11470 {
11471 // regs = 2; if align == ‘11’ then UNDEFINED;
11472 regs = 2;
11473 if (align == 3)
11474 return false;
11475 }
11476 else if (type == 6) // when ‘0110’
11477 {
11478 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11479 regs = 3;
11480 if (BitIsSet (align, 1))
11481 return false;
11482 }
11483 else if (type == 2) // when ‘0010’
11484 // regs = 4;
11485 regs = 4;
11486 else // otherwise
11487 // SEE “Related encodings”;
11488 return false;
11489
11490 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11491 if (align == 0)
11492 alignment = 0;
11493 else
11494 alignment = 4 << align;
11495
11496 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11497 ebytes = 1 << Bits32 (opcode,7, 6);
11498 esize = 8 * ebytes;
11499 elements = 8 / ebytes;
11500
11501 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11502 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11503 n = Bits32 (opcode, 19, 16);
11504 m = Bits32 (opcode, 3, 0);
11505
11506 // wback = (m != 15); register_index = (m != 15 && m != 13);
11507 wback = (m != 15);
11508 register_index = ((m != 15) && (m != 13));
11509
11510 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11511 if ((d + regs) > 32)
11512 return false;
11513
11514 if (n == 15)
11515 return false;
11516
11517 }
11518 break;
11519
11520 default:
11521 return false;
11522 }
11523
11524 Register base_reg;
11525 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11526
11527 uint32_t Rn = ReadCoreReg (n, &success);
11528 if (!success)
11529 return false;
11530
11531 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11532 addr_t address = Rn;
11533 if ((address % alignment) != 0)
11534 return false;
11535
11536 EmulateInstruction::Context context;
11537 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11538 if (wback)
11539 {
11540 uint32_t Rm = ReadCoreReg (m, &success);
11541 if (!success)
11542 return false;
11543
11544 uint32_t offset;
11545 if (register_index)
11546 offset = Rm;
11547 else
11548 offset = 8 * regs;
11549
11550 context.type = eContextAdjustBaseRegister;
11551 context.SetRegisterPlusOffset (base_reg, offset);
11552
11553 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11554 return false;
11555 }
11556
11557 context.type = eContextRegisterStore;
11558 Register data_reg;
11559 data_reg.SetRegister (eRegisterKindDWARF, 0);
11560 // for r = 0 to regs-1
11561 for (int r = 0; r < regs; ++r)
11562 {
11563 data_reg.num = dwarf_d0 + d + r;
11564 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11565 if (!success)
11566 return false;
11567
11568 // for e = 0 to elements-1
11569 for (int e = 0; e < elements; ++e)
11570 {
11571 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011572 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011573
11574 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11575 if (!MemUWrite (context, address, word, ebytes))
11576 return false;
11577
11578 // address = address + ebytes;
11579 address = address + ebytes;
11580 }
11581 }
11582 }
11583 return true;
11584}
11585
Caroline Tice7b880942011-03-31 19:17:12 +000011586// A8.6.392 VST1 (single element from one lane)
11587// This instruction stores one element to memory from one element of a register.
11588bool
11589EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11590{
11591#if 0
11592 if ConditionPassed() then
11593 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11594 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11595 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11596 MemU[address,ebytes] = Elem[D[d],index,esize];
11597#endif
11598
11599 bool success = false;
11600
11601 if (ConditionPassed (opcode))
11602 {
11603 uint32_t ebytes;
11604 uint32_t esize;
11605 uint32_t index;
11606 uint32_t alignment;
11607 uint32_t d;
11608 uint32_t n;
11609 uint32_t m;
11610 bool wback;
11611 bool register_index;
11612
11613 switch (encoding)
11614 {
11615 case eEncodingT1:
11616 case eEncodingA1:
11617 {
11618 uint32_t size = Bits32 (opcode, 11, 10);
11619 uint32_t index_align = Bits32 (opcode, 7, 4);
11620
11621 // if size == ‘11’ then UNDEFINED;
11622 if (size == 3)
11623 return false;
11624
11625 // case size of
11626 if (size == 0) // when ‘00’
11627 {
11628 // if index_align<0> != ‘0’ then UNDEFINED;
11629 if (BitIsClear (index_align, 0))
11630 return false;
11631 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11632 ebytes = 1;
11633 esize = 8;
11634 index = Bits32 (index_align, 3, 1);
11635 alignment = 1;
11636 }
11637 else if (size == 1) // when ‘01’
11638 {
11639 // if index_align<1> != ‘0’ then UNDEFINED;
11640 if (BitIsClear (index_align, 1))
11641 return false;
11642
11643 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11644 ebytes = 2;
11645 esize = 16;
11646 index = Bits32 (index_align, 3, 2);
11647
11648 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11649 if (BitIsClear (index_align, 0))
11650 alignment = 1;
11651 else
11652 alignment = 2;
11653 }
11654 else if (size == 2) // when ‘10’
11655 {
11656 // if index_align<2> != ‘0’ then UNDEFINED;
11657 if (BitIsClear (index_align, 2))
11658 return false;
11659
11660 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11661 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11662 return false;
11663
11664 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11665 ebytes = 4;
11666 esize = 32;
11667 index = Bit32 (index_align, 3);
11668
11669 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11670 if (Bits32 (index_align, 1, 0) == 0)
11671 alignment = 1;
11672 else
11673 alignment = 4;
11674 }
11675 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11676 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11677 n = Bits32 (opcode, 19, 16);
11678 m = Bits32 (opcode, 3, 0);
11679
11680 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11681 wback = (m != 15);
11682 register_index = ((m != 15) && (m != 13));
11683
11684 if (n == 15)
11685 return false;
11686 }
11687 break;
11688
11689 default:
11690 return false;
11691 }
11692
11693 Register base_reg;
11694 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11695
11696 uint32_t Rn = ReadCoreReg (n, &success);
11697 if (!success)
11698 return false;
11699
11700 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11701 addr_t address = Rn;
11702 if ((address % alignment) != 0)
11703 return false;
11704
11705 EmulateInstruction::Context context;
11706 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11707 if (wback)
11708 {
11709 uint32_t Rm = ReadCoreReg (m, &success);
11710 if (!success)
11711 return false;
11712
11713 uint32_t offset;
11714 if (register_index)
11715 offset = Rm;
11716 else
11717 offset = ebytes;
11718
11719 context.type = eContextAdjustBaseRegister;
11720 context.SetRegisterPlusOffset (base_reg, offset);
11721
11722 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11723 return false;
11724 }
11725
11726 // MemU[address,ebytes] = Elem[D[d],index,esize];
11727 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11728 if (!success)
11729 return false;
11730
11731 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11732
11733 Register data_reg;
11734 data_reg.SetRegister (eRegisterKindDWARF, dwarf_d0 + d);
11735 context.type = eContextRegisterStore;
11736 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11737
11738 if (!MemUWrite (context, address, word, ebytes))
11739 return false;
11740 }
11741 return true;
11742}
11743
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011744// A8.6.309 VLD1 (single element to all lanes)
11745// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011746bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011747EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011748{
11749#if 0
11750 if ConditionPassed() then
11751 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11752 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11753 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11754 replicated_element = Replicate(MemU[address,ebytes], elements);
11755 for r = 0 to regs-1
11756 D[d+r] = replicated_element;
11757#endif
11758
11759 bool success = false;
11760
11761 if (ConditionPassed (opcode))
11762 {
11763 uint32_t ebytes;
11764 uint32_t elements;
11765 uint32_t regs;
11766 uint32_t alignment;
11767 uint32_t d;
11768 uint32_t n;
11769 uint32_t m;
11770 bool wback;
11771 bool register_index;
11772
11773 switch (encoding)
11774 {
11775 case eEncodingT1:
11776 case eEncodingA1:
11777 {
11778 //if size == ‘11’ || (size == ‘00’ && a == ‘1’) then UNDEFINED;
11779 uint32_t size = Bits32 (opcode, 7, 6);
11780 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11781 return false;
11782
11783 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == ‘0’ then 1 else 2;
11784 ebytes = 1 << size;
11785 elements = 8 / ebytes;
11786 if (BitIsClear (opcode, 5))
11787 regs = 1;
11788 else
11789 regs = 2;
11790
11791 //alignment = if a == ‘0’ then 1 else ebytes;
11792 if (BitIsClear (opcode, 4))
11793 alignment = 1;
11794 else
11795 alignment = ebytes;
11796
11797 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11798 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11799 n = Bits32 (opcode, 19, 16);
11800 m = Bits32 (opcode, 3, 0);
11801
11802 //wback = (m != 15); register_index = (m != 15 && m != 13);
11803 wback = (m != 15);
11804 register_index = ((m != 15) && (m != 13));
11805
11806 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11807 if ((d + regs) > 32)
11808 return false;
11809
11810 if (n == 15)
11811 return false;
11812 }
11813 break;
11814
11815 default:
11816 break;
11817 }
11818
11819 Register base_reg;
11820 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
11821
11822 uint32_t Rn = ReadCoreReg (n, &success);
11823 if (!success)
11824 return false;
11825
11826 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11827 addr_t address = Rn;
11828 if ((address % alignment) != 0)
11829 return false;
11830
11831 EmulateInstruction::Context context;
11832 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11833 if (wback)
11834 {
11835 uint32_t Rm = ReadCoreReg (m, &success);
11836 if (!success)
11837 return false;
11838
11839 uint32_t offset;
11840 if (register_index)
11841 offset = Rm;
11842 else
11843 offset = ebytes;
11844
11845 context.type = eContextAdjustBaseRegister;
11846 context.SetRegisterPlusOffset (base_reg, offset);
11847
11848 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11849 return false;
11850 }
11851
11852 // replicated_element = Replicate(MemU[address,ebytes], elements);
11853
11854 context.type = eContextRegisterLoad;
11855 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11856 if (!success)
11857 return false;
11858
11859 uint64_t replicated_element;
11860 uint32_t esize = ebytes * 8;
11861 for (int e = 0; e < elements; ++e)
11862 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11863
11864 // for r = 0 to regs-1
11865 for (int r = 0; r < regs; ++r)
11866 {
11867 // D[d+r] = replicated_element;
11868 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11869 return false;
11870 }
11871 }
11872 return true;
11873}
11874
Caroline Tice1f954f52011-04-11 15:51:10 +000011875// B6.2.13 SUBS PC, LR and related instructions
11876//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
11877// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
11878bool
11879EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
11880{
11881#if 0
11882 if ConditionPassed() then
11883 EncodingSpecificOperations();
11884 if CurrentInstrSet() == InstrSet_ThumbEE then
11885 UNPREDICTABLE;
11886 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11887 case opcode of
11888 when 0000 result = R[n] AND operand2; // AND
11889 when 0001 result = R[n] EOR operand2; // EOR
11890 when 0010 (result, -, -) = AddWithCarry(R[n], NOT(operand2), 1’); // SUB
11891 when 0011 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, 1’); // RSB
11892 when 0100 (result, -, -) = AddWithCarry(R[n], operand2, 0’); // ADD
11893 when 0101 (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
11894 when 0110 (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
11895 when 0111 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
11896 when 1100 result = R[n] OR operand2; // ORR
11897 when 1101 result = operand2; // MOV
11898 when 1110 result = R[n] AND NOT(operand2); // BIC
11899 when 1111 result = NOT(operand2); // MVN
11900 CPSRWriteByInstr(SPSR[], 1111’, TRUE);
11901 BranchWritePC(result);
11902#endif
11903
11904 bool success = false;
11905
11906 if (ConditionPassed (opcode))
11907 {
11908 uint32_t n;
11909 uint32_t m;
11910 uint32_t imm32;
11911 bool register_form;
11912 ARM_ShifterType shift_t;
11913 uint32_t shift_n;
11914 uint32_t code;
11915
11916 switch (encoding)
11917 {
11918 case eEncodingT1:
11919 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
11920 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = ‘0010’; // = SUB
11921 n = 14;
11922 imm32 = Bits32 (opcode, 7, 0);
11923 register_form = false;
11924 code = 2;
11925
11926 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
11927 if (InITBlock() && !LastInITBlock())
11928 return false;
11929
11930 break;
11931
11932 case eEncodingA1:
11933 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
11934 n = Bits32 (opcode, 19, 16);
11935 imm32 = ARMExpandImm (opcode);
11936 register_form = false;
11937 code = Bits32 (opcode, 24, 21);
11938
11939 break;
11940
11941 case eEncodingA2:
11942 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
11943 n = Bits32 (opcode, 19, 16);
11944 m = Bits32 (opcode, 3, 0);
11945 register_form = true;
11946
11947 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
11948 shift_n = DecodeImmShiftARM (opcode, shift_t);
11949
11950 break;
11951
11952 default:
11953 return false;
11954 }
11955
11956 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11957 uint32_t operand2;
11958 if (register_form)
11959 {
11960 uint32_t Rm = ReadCoreReg (m, &success);
11961 if (!success)
11962 return false;
11963
11964 operand2 = Shift (Rm, shift_t, shift_n, APSR_C);
11965
11966 }
11967 else
11968 {
11969 operand2 = imm32;
11970 }
11971
11972 uint32_t Rn = ReadCoreReg (n, &success);
11973 if (!success)
11974 return false;
11975
11976 AddWithCarryResult result;
11977
11978 // case opcode of
11979 switch (code)
11980 {
11981 case 0: // when ‘0000’
11982 // result = R[n] AND operand2; // AND
11983 result.result = Rn & operand2;
11984 break;
11985
11986 case 1: // when ‘0001’
11987 // result = R[n] EOR operand2; // EOR
11988 result.result = Rn ^ operand2;
11989 break;
11990
11991 case 2: // when ‘0010’
11992 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), ‘1’); // SUB
11993 result = AddWithCarry (Rn, ~(operand2), 1);
11994 break;
11995
11996 case 3: // when ‘0011’
11997 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, ‘1’); // RSB
11998 result = AddWithCarry (~(Rn), operand2, 1);
11999 break;
12000
12001 case 4: // when ‘0100’
12002 // (result, -, -) = AddWithCarry(R[n], operand2, ‘0’); // ADD
12003 result = AddWithCarry (Rn, operand2, 0);
12004 break;
12005
12006 case 5: // when ‘0101’
12007 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12008 result = AddWithCarry (Rn, operand2, APSR_C);
12009 break;
12010
12011 case 6: // when ‘0110’
12012 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12013 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12014 break;
12015
12016 case 7: // when ‘0111’
12017 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12018 result = AddWithCarry (~(Rn), operand2, APSR_C);
12019 break;
12020
12021 case 10: // when ‘1100’
12022 // result = R[n] OR operand2; // ORR
12023 result.result = Rn | operand2;
12024 break;
12025
12026 case 11: // when ‘1101’
12027 // result = operand2; // MOV
12028 result.result = operand2;
12029 break;
12030
12031 case 12: // when ‘1110’
12032 // result = R[n] AND NOT(operand2); // BIC
12033 result.result = Rn & ~(operand2);
12034 break;
12035
12036 case 15: // when ‘1111’
12037 // result = NOT(operand2); // MVN
12038 result.result = ~(operand2);
12039 break;
12040
12041 default:
12042 return false;
12043 }
12044 // CPSRWriteByInstr(SPSR[], ‘1111’, TRUE);
12045
12046 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12047 // the best.
12048 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12049 if (!success)
12050 return false;
12051
12052 CPSRWriteByInstr (spsr, 15, true);
12053
12054 // BranchWritePC(result);
12055 EmulateInstruction::Context context;
12056 context.type = eContextAdjustPC;
12057 context.SetImmediate (result.result);
12058
12059 BranchWritePC (context, result.result);
12060 }
12061 return true;
12062}
12063
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012064EmulateInstructionARM::ARMOpcode*
12065EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012066{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012067 static ARMOpcode
12068 g_arm_opcodes[] =
12069 {
12070 //----------------------------------------------------------------------
12071 // Prologue instructions
12072 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012073
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012074 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012075 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12076 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012077
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012078 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012079 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12080 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012081 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012082 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12083 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12084 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012085
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012086 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012087 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12088 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012089
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012090 // push one register
12091 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012092 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012093
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012094 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012095 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12096 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012097
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012098 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012099 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012100 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012101
Caroline Tice4f605582011-03-31 00:02:51 +000012102 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12103 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12104 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12105 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012106
12107 //----------------------------------------------------------------------
12108 // Supervisor Call (previously Software Interrupt)
12109 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012110 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012111
12112 //----------------------------------------------------------------------
12113 // Branch instructions
12114 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012115 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012116 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012117 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12118 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12119 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012120 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012121 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012122 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012123 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012124
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012125 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012126 // Data-processing instructions
12127 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012128 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012129 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012130 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012131 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012132 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012133 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012134 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012135 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012136 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012137 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012138 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012139 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12140 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012141 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012142 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012143 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012144 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012145 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012146 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012147 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012148 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012149 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012150 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012151 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012152 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012153 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012154 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012155 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012156 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012157 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012158 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012159 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012160 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012161 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012162 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012163 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012164 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012165 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012166 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012167 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012168 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012169 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012170 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012171 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012172 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012173 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012174 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012175 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012176 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012177 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012178 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012179 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012180 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012181 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012182 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012183
Caroline Tice89c6d582011-03-29 19:53:44 +000012184 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012185 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12186 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012187 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012188 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012189 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012190 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012191 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012192 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012193 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012194 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012195 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012196 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012197 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012198 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012199 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012200 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012201 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012202 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012203 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012204 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012205 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012206 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012207 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012208 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012209 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012210 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012211 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012212 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012213 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012214 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012215 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012216 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012217 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012218 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012219 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012220 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice1f954f52011-04-11 15:51:10 +000012221 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12222 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012223
12224 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012225 // Load instructions
12226 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012227 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12228 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12229 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12230 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12231 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12232 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12233 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12234 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12235 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12236 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12237 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12238 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12239 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12240 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12241 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12242 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12243 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12244 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012245 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12246 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12247 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12248 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012249 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12250 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012251 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012252
12253 //----------------------------------------------------------------------
12254 // Store instructions
12255 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012256 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12257 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12258 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12259 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12260 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12261 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12262 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12263 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12264 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012265 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012266 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012267 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12268 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12269 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12270 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12271 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012272 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012273
Caroline Tice6bf65162011-03-03 17:42:58 +000012274 //----------------------------------------------------------------------
12275 // Other instructions
12276 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012277 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12278 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12279 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12280 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12281 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012282
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012283 };
12284 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12285
12286 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12287 {
12288 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
12289 return &g_arm_opcodes[i];
12290 }
12291 return NULL;
12292}
Greg Clayton64c84432011-01-21 22:02:52 +000012293
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012294
12295EmulateInstructionARM::ARMOpcode*
12296EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +000012297{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012298
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012299 static ARMOpcode
12300 g_thumb_opcodes[] =
12301 {
12302 //----------------------------------------------------------------------
12303 // Prologue instructions
12304 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012305
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012306 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012307 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12308 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12309 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012310
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012311 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012312 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012313 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012314 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012315 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012316 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012317
Johnny Chen864a8e82011-02-18 00:07:39 +000012318 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012319 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012320
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012321 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012322 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12323 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12324 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12325 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12326 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012327
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012328 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012329 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12330 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012331
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012332 //----------------------------------------------------------------------
12333 // Epilogue instructions
12334 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012335
Caroline Tice4f605582011-03-31 00:02:51 +000012336 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12337 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12338 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12339 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12340 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12341 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12342 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012343
12344 //----------------------------------------------------------------------
12345 // Supervisor Call (previously Software Interrupt)
12346 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012347 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012348
12349 //----------------------------------------------------------------------
12350 // If Then makes up to four following instructions conditional.
12351 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012352 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012353
12354 //----------------------------------------------------------------------
12355 // Branch instructions
12356 //----------------------------------------------------------------------
12357 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012358 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12359 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12360 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12361 { 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 +000012362 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012363 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012364 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012365 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12366 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012367 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012368 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012369 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012370 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012371 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012372 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012373 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012374 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012375 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012376 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012377
12378 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012379 // Data-processing instructions
12380 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012381 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012382 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012383 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012384 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12385 { 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 +000012386 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012387 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012388 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012389 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012390 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012391 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12392 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12393 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012394 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012395 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012396 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012397 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12398 { 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 +000012399 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012400 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012401 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012402 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12403 { 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 +000012404 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012405 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012406 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012407 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12408 { 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 +000012409 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012410 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012411 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012412 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12413 { 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 +000012414 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012415 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12416 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012417 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012418 { 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 +000012419 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012420 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012421 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012422 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12423 { 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 +000012424 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012425 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12426 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12427 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12428 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012429 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012430 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12431 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12432 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12433 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012434 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012435 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12436 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012437 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012438 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12439 { 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 +000012440 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012441 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012442 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012443 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012444 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012445 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012446 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012447 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12448 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012449
Johnny Chen7c5234d2011-02-18 23:41:11 +000012450
Johnny Chen338bf542011-02-10 19:29:03 +000012451 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012452 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012453 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012454 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012455 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012456 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012457 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012458 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12459 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12460 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012461 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012462 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012463 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012464 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12465 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012466 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012467 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012468 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012469 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12470 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012471 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012472 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12473 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012474 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012475 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012476 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012477 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012478 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012479 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12480 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012481 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012482 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12483 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012484 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012485 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12486 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012487 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012488 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12489 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012490 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012491 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12492 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012493 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012494 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12495 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012496 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012497 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012498 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012499 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012500 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012501 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12502 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012503 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012504 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012505 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012506 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice1f954f52011-04-11 15:51:10 +000012507 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012508
12509
12510 //----------------------------------------------------------------------
12511 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12512 // otherwise the wrong instructions will be selected.
12513 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012514
Caroline Tice080bf612011-04-05 18:46:00 +000012515 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12516 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12517
Johnny Chen26863dc2011-02-09 23:43:29 +000012518 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012519 // Load instructions
12520 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012521 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12522 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12523 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12524 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12525 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12526 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12527 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012528 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012529 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12530 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12531 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12532 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12533 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012534 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012535 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12536 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12537 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12538 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12539 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12540 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12541 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12542 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12543 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12544 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12545 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12546 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12547 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12548 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12549 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12550 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12551 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12552 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12553 { 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 +000012554 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012555 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12556 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12557 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12558 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012559 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12560 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012561 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012562
12563 //----------------------------------------------------------------------
12564 // Store instructions
12565 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012566 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12567 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12568 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12569 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12570 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12571 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12572 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12573 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12574 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12575 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12576 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12577 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12578 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12579 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12580 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12581 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012582 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12583 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12584 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12585 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12586 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012587 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012588
12589 //----------------------------------------------------------------------
12590 // Other instructions
12591 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012592 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12593 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12594 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12595 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12596 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12597 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12598 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12599 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012600 };
12601
12602 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12603 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12604 {
12605 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
12606 return &g_thumb_opcodes[i];
12607 }
12608 return NULL;
12609}
Greg Clayton64c84432011-01-21 22:02:52 +000012610
Greg Clayton31e2a382011-01-30 20:03:56 +000012611bool
Greg Clayton395fc332011-02-15 21:59:32 +000012612EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012613{
Caroline Tice080bf612011-04-05 18:46:00 +000012614 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012615 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012616 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012617 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012618 {
Greg Clayton395fc332011-02-15 21:59:32 +000012619 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12620 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12621 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12622 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12623 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12624 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12625 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12626 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12627 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12628 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +000012629 }
12630 return m_arm_isa != 0;
12631}
12632
Caroline Tice080bf612011-04-05 18:46:00 +000012633bool
12634EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr)
12635{
12636 m_opcode = insn_opcode;
12637
12638 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12639 m_opcode_mode = eModeThumb;
12640 else
12641 {
12642 AddressClass addr_class = inst_addr.GetAddressClass();
12643
12644 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12645 m_opcode_mode = eModeARM;
12646 else if (addr_class == eAddressClassCodeAlternateISA)
12647 m_opcode_mode = eModeThumb;
12648 else
12649 return false;
12650 }
12651 return true;
12652}
Greg Clayton31e2a382011-01-30 20:03:56 +000012653
Greg Clayton64c84432011-01-21 22:02:52 +000012654bool
12655EmulateInstructionARM::ReadInstruction ()
12656{
12657 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012658 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012659 if (success)
12660 {
12661 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12662 if (success)
12663 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012664 Context read_inst_context;
12665 read_inst_context.type = eContextReadOpcode;
12666 read_inst_context.SetNoArgs ();
12667
Greg Claytonb3448432011-03-24 21:19:54 +000012668 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012669 {
Greg Claytonb3448432011-03-24 21:19:54 +000012670 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012671 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012672
12673 if (success)
12674 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012675 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012676 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012677 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012678 }
12679 else
12680 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012681 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012682 }
12683 }
12684 }
12685 else
12686 {
Greg Claytonb3448432011-03-24 21:19:54 +000012687 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012688 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012689 }
12690 }
12691 }
12692 if (!success)
12693 {
Greg Claytonb3448432011-03-24 21:19:54 +000012694 m_opcode_mode = eModeInvalid;
12695 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012696 }
12697 return success;
12698}
12699
Johnny Chenee9b1f72011-02-09 01:00:31 +000012700uint32_t
12701EmulateInstructionARM::ArchVersion ()
12702{
12703 return m_arm_isa;
12704}
12705
Greg Clayton64c84432011-01-21 22:02:52 +000012706bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012707EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012708{
Greg Clayton64c84432011-01-21 22:02:52 +000012709
Greg Clayton7bc39082011-03-24 23:53:38 +000012710 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012711
12712 if (cond == UINT32_MAX)
12713 return false;
12714
12715 bool result = false;
12716 switch (UnsignedBits(cond, 3, 1))
12717 {
Caroline Tice080bf612011-04-05 18:46:00 +000012718 case 0:
12719 if (m_opcode_cpsr == 0)
12720 return true;
12721 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12722 break;
12723 case 1:
12724 if (m_opcode_cpsr == 0)
12725 return true;
12726 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12727 break;
12728 case 2:
12729 if (m_opcode_cpsr == 0)
12730 return true;
12731 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12732 break;
12733 case 3:
12734 if (m_opcode_cpsr == 0)
12735 return true;
12736 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12737 break;
12738 case 4:
12739 if (m_opcode_cpsr == 0)
12740 return true;
12741 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12742 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012743 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012744 if (m_opcode_cpsr == 0)
12745 return true;
12746 else
12747 {
Greg Claytonb3448432011-03-24 21:19:54 +000012748 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12749 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012750 result = n == v;
12751 }
12752 break;
12753 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012754 if (m_opcode_cpsr == 0)
12755 return true;
12756 else
12757 {
Greg Claytonb3448432011-03-24 21:19:54 +000012758 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12759 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12760 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012761 }
12762 break;
12763 case 7:
12764 result = true;
12765 break;
12766 }
12767
12768 if (cond & 1)
12769 result = !result;
12770 return result;
12771}
12772
Johnny Chen9ee056b2011-02-08 00:06:35 +000012773uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012774EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012775{
Greg Claytonb3448432011-03-24 21:19:54 +000012776 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012777 {
12778 default:
12779 case eModeInvalid:
12780 break;
12781
12782 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012783 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012784
12785 case eModeThumb:
12786 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12787 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012788 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012789 const uint32_t byte_size = m_opcode.GetByteSize();
12790 if (byte_size == 2)
12791 {
12792 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12793 return Bits32(opcode, 11, 7);
12794 }
12795 else
12796 {
12797 assert (byte_size == 4);
12798 if (Bits32(opcode, 31, 27) == 0x1e &&
12799 Bits32(opcode, 15, 14) == 0x02 &&
12800 Bits32(opcode, 12, 12) == 0x00 &&
12801 Bits32(opcode, 25, 22) <= 0x0d)
12802 {
12803 return Bits32(opcode, 25, 22);
12804 }
12805 }
12806
12807 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012808 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012809 }
12810 return UINT32_MAX; // Return invalid value
12811}
12812
Johnny Chen9ee056b2011-02-08 00:06:35 +000012813bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012814EmulateInstructionARM::InITBlock()
12815{
12816 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12817}
12818
12819bool
12820EmulateInstructionARM::LastInITBlock()
12821{
12822 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12823}
12824
Caroline Ticeb27771d2011-03-03 22:37:46 +000012825bool
12826EmulateInstructionARM::BadMode (uint32_t mode)
12827{
12828
12829 switch (mode)
12830 {
12831 case 16: return false; // '10000'
12832 case 17: return false; // '10001'
12833 case 18: return false; // '10010'
12834 case 19: return false; // '10011'
12835 case 22: return false; // '10110'
12836 case 23: return false; // '10111'
12837 case 27: return false; // '11011'
12838 case 31: return false; // '11111'
12839 default: return true;
12840 }
12841 return true;
12842}
12843
12844bool
12845EmulateInstructionARM::CurrentModeIsPrivileged ()
12846{
Greg Claytonb3448432011-03-24 21:19:54 +000012847 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012848
12849 if (BadMode (mode))
12850 return false;
12851
12852 if (mode == 16)
12853 return false;
12854
12855 return true;
12856}
12857
12858void
12859EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
12860{
12861 bool privileged = CurrentModeIsPrivileged();
12862
12863 uint32_t tmp_cpsr = 0;
12864
Greg Claytonb3448432011-03-24 21:19:54 +000012865 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012866
12867 if (BitIsSet (bytemask, 3))
12868 {
12869 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
12870 if (affect_execstate)
12871 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
12872 }
12873
12874 if (BitIsSet (bytemask, 2))
12875 {
12876 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
12877 }
12878
12879 if (BitIsSet (bytemask, 1))
12880 {
12881 if (affect_execstate)
12882 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
12883 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
12884 if (privileged)
12885 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
12886 }
12887
12888 if (BitIsSet (bytemask, 0))
12889 {
12890 if (privileged)
12891 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
12892 if (affect_execstate)
12893 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
12894 if (privileged)
12895 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
12896 }
12897
Greg Claytonb3448432011-03-24 21:19:54 +000012898 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012899}
12900
12901
Johnny Chen098ae2d2011-02-12 00:50:05 +000012902bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000012903EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
12904{
12905 addr_t target;
12906
Johnny Chenee9b1f72011-02-09 01:00:31 +000012907 // Check the current instruction set.
12908 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012909 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012910 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000012911 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012912
Johnny Chen9ee056b2011-02-08 00:06:35 +000012913 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012914 return false;
12915
12916 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012917}
12918
12919// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
12920bool
Johnny Chen668b4512011-02-15 21:08:58 +000012921EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012922{
12923 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000012924 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
12925 // we want to record it and issue a WriteRegister callback so the clients
12926 // can track the mode changes accordingly.
12927 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012928
12929 if (BitIsSet(addr, 0))
12930 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012931 if (CurrentInstrSet() != eModeThumb)
12932 {
12933 SelectInstrSet(eModeThumb);
12934 cpsr_changed = true;
12935 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012936 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000012937 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012938 }
12939 else if (BitIsClear(addr, 1))
12940 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012941 if (CurrentInstrSet() != eModeARM)
12942 {
12943 SelectInstrSet(eModeARM);
12944 cpsr_changed = true;
12945 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012946 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000012947 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012948 }
12949 else
12950 return false; // address<1:0> == '10' => UNPREDICTABLE
12951
Johnny Chen0f309db2011-02-09 19:11:32 +000012952 if (cpsr_changed)
12953 {
Johnny Chen558133b2011-02-09 23:59:17 +000012954 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000012955 return false;
12956 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012957 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012958 return false;
12959
12960 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012961}
Greg Clayton64c84432011-01-21 22:02:52 +000012962
Johnny Chenee9b1f72011-02-09 01:00:31 +000012963// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
12964bool
Johnny Chen668b4512011-02-15 21:08:58 +000012965EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000012966{
12967 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000012968 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000012969 else
12970 return BranchWritePC((const Context)context, addr);
12971}
12972
Johnny Chen26863dc2011-02-09 23:43:29 +000012973// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
12974bool
Johnny Chen668b4512011-02-15 21:08:58 +000012975EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000012976{
12977 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000012978 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000012979 else
12980 return BranchWritePC((const Context)context, addr);
12981}
12982
Johnny Chenee9b1f72011-02-09 01:00:31 +000012983EmulateInstructionARM::Mode
12984EmulateInstructionARM::CurrentInstrSet ()
12985{
Greg Claytonb3448432011-03-24 21:19:54 +000012986 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012987}
12988
Greg Claytonb3448432011-03-24 21:19:54 +000012989// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000012990// ReadInstruction() is performed. This function has a side effect of updating
12991// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000012992bool
12993EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
12994{
Greg Claytonb3448432011-03-24 21:19:54 +000012995 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012996 switch (arm_or_thumb)
12997 {
12998 default:
12999 return false;
13000 eModeARM:
13001 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013002 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013003 break;
13004 eModeThumb:
13005 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013006 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013007 break;
13008 }
13009 return true;
13010}
13011
Johnny Chenef21b592011-02-10 01:52:38 +000013012// This function returns TRUE if the processor currently provides support for
13013// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13014// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13015bool
13016EmulateInstructionARM::UnalignedSupport()
13017{
13018 return (ArchVersion() >= ARMv7);
13019}
13020
Johnny Chenbf6ad172011-02-11 01:29:53 +000013021// The main addition and subtraction instructions can produce status information
13022// about both unsigned carry and signed overflow conditions. This status
13023// information can be used to synthesize multi-word additions and subtractions.
13024EmulateInstructionARM::AddWithCarryResult
13025EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13026{
13027 uint32_t result;
13028 uint8_t carry_out;
13029 uint8_t overflow;
13030
13031 uint64_t unsigned_sum = x + y + carry_in;
13032 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13033
13034 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013035// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013036 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013037
13038 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013039 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013040 else
13041 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013042
13043 AddWithCarryResult res = { result, carry_out, overflow };
13044 return res;
13045}
13046
Johnny Chen157b9592011-02-18 21:13:05 +000013047uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013048EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013049{
Johnny Chene39f22d2011-02-19 01:36:13 +000013050 uint32_t reg_kind, reg_num;
13051 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013052 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013053 case SP_REG:
13054 reg_kind = eRegisterKindGeneric;
13055 reg_num = LLDB_REGNUM_GENERIC_SP;
13056 break;
13057 case LR_REG:
13058 reg_kind = eRegisterKindGeneric;
13059 reg_num = LLDB_REGNUM_GENERIC_RA;
13060 break;
13061 case PC_REG:
13062 reg_kind = eRegisterKindGeneric;
13063 reg_num = LLDB_REGNUM_GENERIC_PC;
13064 break;
13065 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013066 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013067 {
13068 reg_kind = eRegisterKindDWARF;
13069 reg_num = dwarf_r0 + num;
13070 }
Johnny Chen157b9592011-02-18 21:13:05 +000013071 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013072 {
13073 assert(0 && "Invalid register number");
13074 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013075 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013076 }
13077 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013078 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013079
13080 // Read our register.
13081 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13082
13083 // When executing an ARM instruction , PC reads as the address of the current
13084 // instruction plus 8.
13085 // When executing a Thumb instruction , PC reads as the address of the current
13086 // instruction plus 4.
13087 if (num == 15)
13088 {
13089 if (CurrentInstrSet() == eModeARM)
13090 val += 8;
13091 else
13092 val += 4;
13093 }
Johnny Chen157b9592011-02-18 21:13:05 +000013094
13095 return val;
13096}
13097
Johnny Chenca67d1c2011-02-17 01:35:27 +000013098// Write the result to the ARM core register Rd, and optionally update the
13099// condition flags based on the result.
13100//
13101// This helper method tries to encapsulate the following pseudocode from the
13102// ARM Architecture Reference Manual:
13103//
13104// if d == 15 then // Can only occur for encoding A1
13105// ALUWritePC(result); // setflags is always FALSE here
13106// else
13107// R[d] = result;
13108// if setflags then
13109// APSR.N = result<31>;
13110// APSR.Z = IsZeroBit(result);
13111// APSR.C = carry;
13112// // APSR.V unchanged
13113//
13114// In the above case, the API client does not pass in the overflow arg, which
13115// defaults to ~0u.
13116bool
Johnny Chen10530c22011-02-17 22:37:12 +000013117EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13118 const uint32_t result,
13119 const uint32_t Rd,
13120 bool setflags,
13121 const uint32_t carry,
13122 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013123{
13124 if (Rd == 15)
13125 {
13126 if (!ALUWritePC (context, result))
13127 return false;
13128 }
13129 else
13130 {
Johnny Chena695f952011-02-23 21:24:25 +000013131 uint32_t reg_kind, reg_num;
13132 switch (Rd)
13133 {
13134 case SP_REG:
13135 reg_kind = eRegisterKindGeneric;
13136 reg_num = LLDB_REGNUM_GENERIC_SP;
13137 break;
13138 case LR_REG:
13139 reg_kind = eRegisterKindGeneric;
13140 reg_num = LLDB_REGNUM_GENERIC_RA;
13141 break;
13142 default:
13143 reg_kind = eRegisterKindDWARF;
13144 reg_num = dwarf_r0 + Rd;
13145 }
13146 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013147 return false;
13148 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013149 return WriteFlags (context, result, carry, overflow);
13150 }
13151 return true;
13152}
13153
13154// This helper method tries to encapsulate the following pseudocode from the
13155// ARM Architecture Reference Manual:
13156//
13157// APSR.N = result<31>;
13158// APSR.Z = IsZeroBit(result);
13159// APSR.C = carry;
13160// APSR.V = overflow
13161//
13162// Default arguments can be specified for carry and overflow parameters, which means
13163// not to update the respective flags.
13164bool
13165EmulateInstructionARM::WriteFlags (Context &context,
13166 const uint32_t result,
13167 const uint32_t carry,
13168 const uint32_t overflow)
13169{
Greg Claytonb3448432011-03-24 21:19:54 +000013170 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013171 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13172 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013173 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013174 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013175 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013176 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013177 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013178 {
13179 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13180 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013181 }
13182 return true;
13183}
13184
Greg Clayton64c84432011-01-21 22:02:52 +000013185bool
13186EmulateInstructionARM::EvaluateInstruction ()
13187{
Johnny Chenc315f862011-02-05 00:46:10 +000013188 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013189 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013190 m_it_session.ITAdvance();
13191
Caroline Tice080bf612011-04-05 18:46:00 +000013192
13193 ARMOpcode *opcode_data;
13194
13195 if (m_opcode_mode == eModeThumb)
Caroline Tice523c5542011-04-13 00:42:12 +000013196 {
13197 if (m_opcode.GetType() == Opcode::eType32)
13198 {
13199 uint16_t upper_bits = Bits32 (m_opcode.GetOpcode32(), 31, 16);
13200 uint16_t lower_bits = Bits32 (m_opcode.GetOpcode32(), 15, 0);
13201 uint32_t swapped = (lower_bits << 16) | upper_bits;
13202 m_opcode.SetOpcode32 (swapped);
13203 }
Caroline Tice080bf612011-04-05 18:46:00 +000013204 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32());
Caroline Tice523c5542011-04-13 00:42:12 +000013205 }
Caroline Tice080bf612011-04-05 18:46:00 +000013206 else if (m_opcode_mode == eModeARM)
13207 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32());
13208 else
13209 return false;
13210
13211 if (!opcode_data)
13212 return false;
13213 // Verify that we're the right arch for this opcode
13214
13215 switch (m_arm_isa)
13216 {
13217 case ARMv4:
13218 if (opcode_data->variants != ARMvAll)
13219 return false;
13220 break;
13221
13222 case ARMv4T:
13223 if ((opcode_data->variants!= ARMvAll)
13224 && (opcode_data->variants != ARMV4T_ABOVE))
13225 return false;
13226 break;
13227
13228 case ARMv5T:
13229 case ARMv5TE:
13230 if ((opcode_data->variants != ARMvAll)
13231 && (opcode_data->variants != ARMV4T_ABOVE)
13232 && (opcode_data->variants != ARMV5_ABOVE))
13233 return false;
13234 break;
13235
13236 case ARMv5TEJ:
13237 if ((opcode_data->variants != ARMvAll)
13238 && (opcode_data->variants != ARMV4T_ABOVE)
13239 && (opcode_data->variants != ARMV5_ABOVE)
13240 && (opcode_data->variants != ARMV5J_ABOVE))
13241 return false;
13242 break;
13243
13244 case ARMv6:
13245 case ARMv6K:
13246 if ((opcode_data->variants != ARMvAll)
13247 && (opcode_data->variants != ARMV4T_ABOVE)
13248 && (opcode_data->variants != ARMV5_ABOVE)
13249 && (opcode_data->variants != ARMV5J_ABOVE)
13250 && (opcode_data->variants != ARMV6_ABOVE))
13251 return false;
13252 break;
13253
13254 case ARMv6T2:
13255 case ARMv7:
13256 case ARMv8:
13257 if ((opcode_data->variants != ARMvAll)
13258 && (opcode_data->variants != ARMV4T_ABOVE)
13259 && (opcode_data->variants != ARMV5_ABOVE)
13260 && (opcode_data->variants != ARMV5J_ABOVE)
13261 && (opcode_data->variants != ARMV6_ABOVE)
13262 && (opcode_data->variants != ARMV6T2_ABOVE))
13263 return false;
13264 break;
13265
13266 default:
13267// if (opcode_data->variants != ARMvAll)
13268// return false;
13269 break;
13270 }
13271
13272 // Just for now, for testing purposes.
Caroline Ticeaf591802011-04-05 23:22:54 +000013273 if (m_baton == NULL)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013274 fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(),
13275 opcode_data->name);
13276
13277 bool success;
13278 if (m_baton)
13279 {
13280 uint32_t cpsr_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
13281 if (success)
13282 m_opcode_cpsr = cpsr_value;
13283 }
Caroline Tice080bf612011-04-05 18:46:00 +000013284
Caroline Tice0fe5a532011-04-08 23:33:06 +000013285 uint32_t orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13286 if (!success)
13287 return false;
13288
13289 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function.
13290 if (!success)
13291 return false;
13292
13293 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13294 if (!success)
13295 return false;
13296
13297 if (m_advance_pc && (after_pc_value == orig_pc_value))
13298 {
13299 if (opcode_data->size == eSize32)
13300 after_pc_value += 4;
13301 else if (opcode_data->size == eSize16)
13302 after_pc_value += 2;
13303
13304 EmulateInstruction::Context context;
13305 context.type = eContextAdvancePC;
13306 context.SetNoArgs();
13307 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13308 return false;
13309
13310 }
13311
13312 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013313}