blob: 702ca061da30dffdceedc185d32dbf285f326e82 [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"
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013#include "EmulationStateARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000014#include "lldb/Core/ArchSpec.h"
Caroline Tice080bf612011-04-05 18:46:00 +000015#include "lldb/Core/Address.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000016#include "lldb/Core/ConstString.h"
Caroline Tice080bf612011-04-05 18:46:00 +000017#include "lldb/Core/PluginManager.h"
Caroline Tice6b8d3b52011-04-19 23:30:03 +000018#include "lldb/Core/Stream.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000019
Greg Claytonf29a08f2011-02-09 17:41:27 +000020#include "Plugins/Process/Utility/ARMDefines.h"
21#include "Plugins/Process/Utility/ARMUtils.h"
22#include "Utility/ARM_DWARF_Registers.h"
23
Johnny Chen9b8d7832011-02-02 01:13:56 +000024#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000025 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000026
27using namespace lldb;
28using namespace lldb_private;
29
Johnny Chene97c0d52011-02-18 19:32:20 +000030// Convenient macro definitions.
Greg Claytonb3448432011-03-24 21:19:54 +000031#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
32#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000033
Caroline Ticef55261f2011-02-18 22:24:22 +000034#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
35
Johnny Chen0e00af22011-02-10 19:40:42 +000036//----------------------------------------------------------------------
37//
38// ITSession implementation
39//
40//----------------------------------------------------------------------
41
Johnny Chen93070472011-02-04 23:02:47 +000042// A8.6.50
43// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
44static unsigned short CountITSize(unsigned ITMask) {
45 // First count the trailing zeros of the IT mask.
46 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
47 if (TZ > 3)
48 {
49 printf("Encoding error: IT Mask '0000'\n");
50 return 0;
51 }
52 return (4 - TZ);
53}
54
55// Init ITState. Note that at least one bit is always 1 in mask.
56bool ITSession::InitIT(unsigned short bits7_0)
57{
58 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
59 if (ITCounter == 0)
60 return false;
61
62 // A8.6.50 IT
63 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
64 if (FirstCond == 0xF)
65 {
66 printf("Encoding error: IT FirstCond '1111'\n");
67 return false;
68 }
69 if (FirstCond == 0xE && ITCounter != 1)
70 {
71 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
72 return false;
73 }
74
75 ITState = bits7_0;
76 return true;
77}
78
79// Update ITState if necessary.
80void ITSession::ITAdvance()
81{
82 assert(ITCounter);
83 --ITCounter;
84 if (ITCounter == 0)
85 ITState = 0;
86 else
87 {
88 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
89 SetBits32(ITState, 4, 0, NewITState4_0);
90 }
91}
92
93// Return true if we're inside an IT Block.
94bool ITSession::InITBlock()
95{
96 return ITCounter != 0;
97}
98
Johnny Chenc315f862011-02-05 00:46:10 +000099// Return true if we're the last instruction inside an IT Block.
100bool ITSession::LastInITBlock()
101{
102 return ITCounter == 1;
103}
104
Johnny Chen93070472011-02-04 23:02:47 +0000105// Get condition bits for the current thumb instruction.
106uint32_t ITSession::GetCond()
107{
Johnny Chenc315f862011-02-05 00:46:10 +0000108 if (InITBlock())
109 return Bits32(ITState, 7, 4);
110 else
111 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000112}
113
Greg Clayton64c84432011-01-21 22:02:52 +0000114// ARM constants used during decoding
115#define REG_RD 0
116#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000117#define SP_REG 13
118#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000119#define PC_REG 15
120#define PC_REGLIST_BIT 0x8000
121
Johnny Chen251af6a2011-01-21 22:47:25 +0000122#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000123#define ARMv4T (1u << 1)
124#define ARMv5T (1u << 2)
125#define ARMv5TE (1u << 3)
126#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000127#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000128#define ARMv6K (1u << 6)
129#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000130#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000131#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000132#define ARMvAll (0xffffffffu)
133
Johnny Chen9b8d7832011-02-02 01:13:56 +0000134#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
135#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice1697dd72011-03-30 17:11:45 +0000136#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000137#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000138#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000139#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000140
Caroline Tice4f605582011-03-31 00:02:51 +0000141#define No_VFP 0
142#define VFPv1 (1u << 1)
143#define VFPv2 (1u << 2)
144#define VFPv3 (1u << 3)
145#define AdvancedSIMD (1u << 4)
146
147#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
148#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
149#define VFPv2v3 (VFPv2 | VFPv3)
150
Johnny Chen0e00af22011-02-10 19:40:42 +0000151//----------------------------------------------------------------------
152//
153// EmulateInstructionARM implementation
154//
155//----------------------------------------------------------------------
156
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000157void
158EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000159{
Caroline Tice080bf612011-04-05 18:46:00 +0000160 PluginManager::RegisterPlugin (GetPluginNameStatic (),
161 GetPluginDescriptionStatic (),
162 CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000163}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000164
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000165void
166EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000167{
Caroline Tice080bf612011-04-05 18:46:00 +0000168 PluginManager::UnregisterPlugin (CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000169}
170
Caroline Tice080bf612011-04-05 18:46:00 +0000171const char *
172EmulateInstructionARM::GetPluginNameStatic ()
173{
174 return "lldb.emulate-instruction.arm";
175}
176
177const char *
178EmulateInstructionARM::GetPluginDescriptionStatic ()
179{
180 return "Emulate instructions for the ARM architecture.";
181}
182
183EmulateInstruction *
184EmulateInstructionARM::CreateInstance (const ArchSpec &arch)
185{
186 if (arch.GetTriple().getArch() == llvm::Triple::arm)
187 {
188 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
189
190 if (emulate_insn_ap.get())
191 return emulate_insn_ap.release();
192 }
193 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
194 {
195 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
196
197 if (emulate_insn_ap.get())
198 return emulate_insn_ap.release();
199 }
200
201 return NULL;
202}
203
204bool
205EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
206{
207 if (arch.GetTriple().getArch () == llvm::Triple::arm)
208 return true;
209 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
210 return true;
211
212 return false;
213}
214
Caroline Ticefa172202011-02-11 22:49:54 +0000215// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
216bool
217EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
218{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000219 EmulateInstruction::Context context;
220 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
221 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000222
223 uint32_t random_data = rand ();
224 const uint32_t addr_byte_size = GetAddressByteSize();
225
Caroline Ticecc96eb52011-02-17 19:20:40 +0000226 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000227 return false;
228
229 return true;
230}
231
Caroline Tice713c2662011-02-11 17:59:55 +0000232// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
233bool
234EmulateInstructionARM::WriteBits32Unknown (int n)
235{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000236 EmulateInstruction::Context context;
237 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
238 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000239
Johnny Chen62ff6f52011-02-11 18:11:22 +0000240 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000241 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
242
243 if (!success)
244 return false;
245
246 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
247 return false;
248
249 return true;
250}
251
Johnny Chen08c25e82011-01-31 18:02:28 +0000252// Push Multiple Registers stores multiple registers to the stack, storing to
253// consecutive memory locations ending just below the address in SP, and updates
254// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000255bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000256EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000257{
258#if 0
259 // ARM pseudo code...
260 if (ConditionPassed())
261 {
262 EncodingSpecificOperations();
263 NullCheckIfThumbEE(13);
264 address = SP - 4*BitCount(registers);
265
266 for (i = 0 to 14)
267 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000268 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000269 {
270 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
271 MemA[address,4] = bits(32) UNKNOWN;
272 else
273 MemA[address,4] = R[i];
274 address = address + 4;
275 }
276 }
277
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000278 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000279 MemA[address,4] = PCStoreValue();
280
281 SP = SP - 4*BitCount(registers);
282 }
283#endif
284
285 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000286 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000287 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000288 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000289 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000290 if (!success)
291 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000292 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000293 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000294 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000295 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000296 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000297 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000298 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000299 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000300 // if BitCount(registers) < 1 then UNPREDICTABLE;
301 if (BitCount(registers) < 1)
302 return false;
303 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000304 case eEncodingT2:
305 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000306 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000307 // if BitCount(registers) < 2 then UNPREDICTABLE;
308 if (BitCount(registers) < 2)
309 return false;
310 break;
311 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000312 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000313 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000314 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000315 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000316 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000317 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000318 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000319 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000320 // Instead of return false, let's handle the following case as well,
321 // which amounts to pushing one reg onto the full descending stacks.
322 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000323 break;
324 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000325 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000326 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000327 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000328 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000329 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000330 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000331 default:
332 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000333 }
Johnny Chence1ca772011-01-25 01:13:00 +0000334 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000335 addr_t addr = sp - sp_offset;
336 uint32_t i;
337
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000338 EmulateInstruction::Context context;
339 context.type = EmulateInstruction::eContextPushRegisterOnStack;
340 Register dwarf_reg;
341 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000342 Register sp_reg;
343 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
Greg Clayton64c84432011-01-21 22:02:52 +0000344 for (i=0; i<15; ++i)
345 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000346 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000347 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000348 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000349 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000350 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000351 if (!success)
352 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000353 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000354 return false;
355 addr += addr_byte_size;
356 }
357 }
358
Johnny Chen7c1bf922011-02-08 23:49:37 +0000359 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000360 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000361 dwarf_reg.num = dwarf_pc;
362 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000363 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000364 if (!success)
365 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000366 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000367 return false;
368 }
369
370 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000371 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000372
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000373 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000374 return false;
375 }
376 return true;
377}
378
Johnny Chenef85e912011-01-31 23:07:40 +0000379// Pop Multiple Registers loads multiple registers from the stack, loading from
380// consecutive memory locations staring at the address in SP, and updates
381// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000382bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000383EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000384{
385#if 0
386 // ARM pseudo code...
387 if (ConditionPassed())
388 {
389 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
390 address = SP;
391 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000392 if registers<i> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000393 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000394 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000395 if UnalignedAllowed then
396 LoadWritePC(MemU[address,4]);
397 else
398 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000399 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
400 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000401 }
402#endif
403
404 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000405
Greg Clayton7bc39082011-03-24 23:53:38 +0000406 if (ConditionPassed(opcode))
Johnny Chenef85e912011-01-31 23:07:40 +0000407 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000408 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000409 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000410 if (!success)
411 return false;
412 uint32_t registers = 0;
413 uint32_t Rt; // the destination register
414 switch (encoding) {
415 case eEncodingT1:
416 registers = Bits32(opcode, 7, 0);
417 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000418 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000419 registers |= (1u << 15);
420 // if BitCount(registers) < 1 then UNPREDICTABLE;
421 if (BitCount(registers) < 1)
422 return false;
423 break;
424 case eEncodingT2:
425 // Ignore bit 13.
426 registers = Bits32(opcode, 15, 0) & ~0x2000;
427 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000428 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000429 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000430 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
431 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
432 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000433 break;
434 case eEncodingT3:
435 Rt = Bits32(opcode, 15, 12);
436 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000437 if (Rt == 13)
438 return false;
439 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000440 return false;
441 registers = (1u << Rt);
442 break;
443 case eEncodingA1:
444 registers = Bits32(opcode, 15, 0);
445 // Instead of return false, let's handle the following case as well,
446 // which amounts to popping one reg from the full descending stacks.
447 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
448
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000449 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000450 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000451 return false;
452 break;
453 case eEncodingA2:
454 Rt = Bits32(opcode, 15, 12);
455 // if t == 13 then UNPREDICTABLE;
456 if (Rt == dwarf_sp)
457 return false;
458 registers = (1u << Rt);
459 break;
460 default:
461 return false;
462 }
463 addr_t sp_offset = addr_byte_size * BitCount (registers);
464 addr_t addr = sp;
465 uint32_t i, data;
466
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000467 EmulateInstruction::Context context;
468 context.type = EmulateInstruction::eContextPopRegisterOffStack;
469 Register dwarf_reg;
470 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice8ce836d2011-03-16 22:46:55 +0000471 Register sp_reg;
472 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Johnny Chenef85e912011-01-31 23:07:40 +0000473 for (i=0; i<15; ++i)
474 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000475 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000476 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000477 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000478 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000479 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000480 if (!success)
481 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000482 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000483 return false;
484 addr += addr_byte_size;
485 }
486 }
487
Johnny Chen7c1bf922011-02-08 23:49:37 +0000488 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000489 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000490 dwarf_reg.num = dwarf_pc;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000491 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000492 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000493 if (!success)
494 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000495 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000496 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000497 return false;
498 addr += addr_byte_size;
499 }
500
501 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000502 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000503
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000504 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000505 return false;
506 }
507 return true;
508}
509
Johnny Chen5b442b72011-01-27 19:34:30 +0000510// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000511// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000512bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000513EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000514{
515#if 0
516 // ARM pseudo code...
517 if (ConditionPassed())
518 {
519 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000520 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000521 if d == 15 then
522 ALUWritePC(result); // setflags is always FALSE here
523 else
524 R[d] = result;
525 if setflags then
526 APSR.N = result<31>;
527 APSR.Z = IsZeroBit(result);
528 APSR.C = carry;
529 APSR.V = overflow;
530 }
531#endif
532
533 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000534
Greg Clayton7bc39082011-03-24 23:53:38 +0000535 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000536 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000537 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000538 if (!success)
539 return false;
540 uint32_t Rd; // the destination register
541 uint32_t imm32;
542 switch (encoding) {
543 case eEncodingT1:
544 Rd = 7;
545 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
546 break;
547 case eEncodingA1:
548 Rd = Bits32(opcode, 15, 12);
549 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
550 break;
551 default:
552 return false;
553 }
554 addr_t sp_offset = imm32;
555 addr_t addr = sp + sp_offset; // a pointer to the stack area
556
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000557 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +0000558 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000559 Register sp_reg;
560 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
561 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000562
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000563 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000564 return false;
565 }
566 return true;
567}
568
Johnny Chen2ccad832011-01-28 19:57:25 +0000569// Set r7 or ip to the current stack pointer.
570// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000571bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000572EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000573{
574#if 0
575 // ARM pseudo code...
576 if (ConditionPassed())
577 {
578 EncodingSpecificOperations();
579 result = R[m];
580 if d == 15 then
581 ALUWritePC(result); // setflags is always FALSE here
582 else
583 R[d] = result;
584 if setflags then
585 APSR.N = result<31>;
586 APSR.Z = IsZeroBit(result);
587 // APSR.C unchanged
588 // APSR.V unchanged
589 }
590#endif
591
592 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000593
Greg Clayton7bc39082011-03-24 23:53:38 +0000594 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000595 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000596 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000597 if (!success)
598 return false;
599 uint32_t Rd; // the destination register
600 switch (encoding) {
601 case eEncodingT1:
602 Rd = 7;
603 break;
604 case eEncodingA1:
605 Rd = 12;
606 break;
607 default:
608 return false;
609 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000610
611 EmulateInstruction::Context context;
612 context.type = EmulateInstruction::eContextRegisterPlusOffset;
613 Register sp_reg;
614 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
615 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000616
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000617 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000618 return false;
619 }
620 return true;
621}
622
Johnny Chen1c13b622011-01-29 00:11:15 +0000623// Move from high register (r8-r15) to low register (r0-r7).
624// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000625bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000626EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000627{
Greg Clayton7bc39082011-03-24 23:53:38 +0000628 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000629}
630
631// Move from register to register.
632// MOV (register)
633bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000634EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000635{
Johnny Chen1c13b622011-01-29 00:11:15 +0000636#if 0
637 // ARM pseudo code...
638 if (ConditionPassed())
639 {
640 EncodingSpecificOperations();
641 result = R[m];
642 if d == 15 then
643 ALUWritePC(result); // setflags is always FALSE here
644 else
645 R[d] = result;
646 if setflags then
647 APSR.N = result<31>;
648 APSR.Z = IsZeroBit(result);
649 // APSR.C unchanged
650 // APSR.V unchanged
651 }
652#endif
653
654 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000655
Greg Clayton7bc39082011-03-24 23:53:38 +0000656 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000657 {
658 uint32_t Rm; // the source register
659 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000660 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000661 switch (encoding) {
662 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000663 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000664 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000665 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000666 if (Rd == 15 && InITBlock() && !LastInITBlock())
667 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000668 break;
669 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000670 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000671 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000672 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000673 if (InITBlock())
674 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000675 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000676 case eEncodingT3:
677 Rd = Bits32(opcode, 11, 8);
678 Rm = Bits32(opcode, 3, 0);
679 setflags = BitIsSet(opcode, 20);
680 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
681 if (setflags && (BadReg(Rd) || BadReg(Rm)))
682 return false;
683 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
684 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
685 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000686 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000687 case eEncodingA1:
688 Rd = Bits32(opcode, 15, 12);
689 Rm = Bits32(opcode, 3, 0);
690 setflags = BitIsSet(opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +0000691
Johnny Chen01d61572011-02-25 00:23:25 +0000692 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000693 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000694 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000695 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000696 default:
697 return false;
698 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000699 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000700 if (!success)
701 return false;
702
703 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000704 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000705 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000706 Register dwarf_reg;
707 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000708 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000709
Johnny Chen10530c22011-02-17 22:37:12 +0000710 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000711 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000712 }
713 return true;
714}
715
Johnny Chen357c30f2011-02-14 22:04:25 +0000716// Move (immediate) writes an immediate value to the destination register. It
717// can optionally update the condition flags based on the value.
718// MOV (immediate)
719bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000720EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000721{
722#if 0
723 // ARM pseudo code...
724 if (ConditionPassed())
725 {
726 EncodingSpecificOperations();
727 result = imm32;
728 if d == 15 then // Can only occur for ARM encoding
729 ALUWritePC(result); // setflags is always FALSE here
730 else
731 R[d] = result;
732 if setflags then
733 APSR.N = result<31>;
734 APSR.Z = IsZeroBit(result);
735 APSR.C = carry;
736 // APSR.V unchanged
737 }
738#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000739
Greg Clayton7bc39082011-03-24 23:53:38 +0000740 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000741 {
742 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000743 uint32_t imm32; // the immediate value to be written to Rd
744 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
745 bool setflags;
746 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000747 case eEncodingT1:
748 Rd = Bits32(opcode, 10, 8);
749 setflags = !InITBlock();
750 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
751 carry = APSR_C;
752
753 break;
754
755 case eEncodingT2:
756 Rd = Bits32(opcode, 11, 8);
757 setflags = BitIsSet(opcode, 20);
758 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
759 if (BadReg(Rd))
760 return false;
761
762 break;
763
764 case eEncodingT3:
765 {
766 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
767 Rd = Bits32 (opcode, 11, 8);
768 setflags = false;
769 uint32_t imm4 = Bits32 (opcode, 19, 16);
770 uint32_t imm3 = Bits32 (opcode, 14, 12);
771 uint32_t i = Bit32 (opcode, 26);
772 uint32_t imm8 = Bits32 (opcode, 7, 0);
773 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
774
775 // if BadReg(d) then UNPREDICTABLE;
776 if (BadReg (Rd))
777 return false;
778 }
779 break;
780
781 case eEncodingA1:
Caroline Tice89c6d582011-03-29 19:53:44 +0000782 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
783 Rd = Bits32 (opcode, 15, 12);
784 setflags = BitIsSet (opcode, 20);
785 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000786
787 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
788 if ((Rd == 15) && setflags)
789 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000790
791 break;
792
793 case eEncodingA2:
794 {
795 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
796 Rd = Bits32 (opcode, 15, 12);
797 setflags = false;
798 uint32_t imm4 = Bits32 (opcode, 19, 16);
799 uint32_t imm12 = Bits32 (opcode, 11, 0);
800 imm32 = (imm4 << 12) | imm12;
801
802 // if d == 15 then UNPREDICTABLE;
803 if (Rd == 15)
804 return false;
805 }
806 break;
807
808 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000809 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000810 }
811 uint32_t result = imm32;
812
813 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000814 EmulateInstruction::Context context;
815 context.type = EmulateInstruction::eContextImmediate;
816 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000817
Johnny Chen10530c22011-02-17 22:37:12 +0000818 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000819 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000820 }
821 return true;
822}
823
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000824// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
825// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
826// unsigned values.
827//
828// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
829// limited to only a few forms of the instruction.
830bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000831EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000832{
833#if 0
834 if ConditionPassed() then
835 EncodingSpecificOperations();
836 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
837 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
838 result = operand1 * operand2;
839 R[d] = result<31:0>;
840 if setflags then
841 APSR.N = result<31>;
842 APSR.Z = IsZeroBit(result);
843 if ArchVersion() == 4 then
844 APSR.C = bit UNKNOWN;
845 // else APSR.C unchanged
846 // APSR.V always unchanged
847#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000848
Greg Clayton7bc39082011-03-24 23:53:38 +0000849 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000850 {
851 uint32_t d;
852 uint32_t n;
853 uint32_t m;
854 bool setflags;
855
856 // EncodingSpecificOperations();
857 switch (encoding)
858 {
859 case eEncodingT1:
860 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
861 d = Bits32 (opcode, 2, 0);
862 n = Bits32 (opcode, 5, 3);
863 m = Bits32 (opcode, 2, 0);
864 setflags = !InITBlock();
865
866 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
867 if ((ArchVersion() < ARMv6) && (d == n))
868 return false;
869
870 break;
871
872 case eEncodingT2:
873 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
874 d = Bits32 (opcode, 11, 8);
875 n = Bits32 (opcode, 19, 16);
876 m = Bits32 (opcode, 3, 0);
877 setflags = false;
878
879 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
880 if (BadReg (d) || BadReg (n) || BadReg (m))
881 return false;
882
883 break;
884
885 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000886 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000887 d = Bits32 (opcode, 19, 16);
888 n = Bits32 (opcode, 3, 0);
889 m = Bits32 (opcode, 11, 8);
890 setflags = BitIsSet (opcode, 20);
891
892 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
893 if ((d == 15) || (n == 15) || (m == 15))
894 return false;
895
896 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
897 if ((ArchVersion() < ARMv6) && (d == n))
898 return false;
899
900 break;
901
902 default:
903 return false;
904 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000905
906 bool success = false;
907
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000908 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
909 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
910 if (!success)
911 return false;
912
913 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
914 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
915 if (!success)
916 return false;
917
918 // result = operand1 * operand2;
919 uint64_t result = operand1 * operand2;
920
921 // R[d] = result<31:0>;
922 Register op1_reg;
923 Register op2_reg;
924 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
925 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
926
927 EmulateInstruction::Context context;
928 context.type = eContextMultiplication;
929 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
930
931 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
932 return false;
933
934 // if setflags then
935 if (setflags)
936 {
937 // APSR.N = result<31>;
938 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000939 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000940 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
941 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000942 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000943 {
944 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
945 return false;
946 }
947
948 // if ArchVersion() == 4 then
949 // APSR.C = bit UNKNOWN;
950 }
951 }
952 return true;
953}
954
Johnny Chend642a6a2011-02-22 01:01:03 +0000955// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
956// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000957bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000958EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000959{
960#if 0
961 // ARM pseudo code...
962 if (ConditionPassed())
963 {
964 EncodingSpecificOperations();
965 result = NOT(imm32);
966 if d == 15 then // Can only occur for ARM encoding
967 ALUWritePC(result); // setflags is always FALSE here
968 else
969 R[d] = result;
970 if setflags then
971 APSR.N = result<31>;
972 APSR.Z = IsZeroBit(result);
973 APSR.C = carry;
974 // APSR.V unchanged
975 }
976#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000977
Greg Clayton7bc39082011-03-24 23:53:38 +0000978 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000979 {
980 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000981 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
982 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000983 bool setflags;
984 switch (encoding) {
985 case eEncodingT1:
986 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000987 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000988 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000989 break;
990 case eEncodingA1:
991 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000992 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000993 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000994
Johnny Chend642a6a2011-02-22 01:01:03 +0000995 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +0000996 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000997 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000998 break;
999 default:
1000 return false;
1001 }
1002 uint32_t result = ~imm32;
1003
1004 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001005 EmulateInstruction::Context context;
1006 context.type = EmulateInstruction::eContextImmediate;
1007 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001008
Johnny Chen10530c22011-02-17 22:37:12 +00001009 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001010 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001011 }
1012 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001013}
1014
Johnny Chend642a6a2011-02-22 01:01:03 +00001015// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1016// It can optionally update the condition flags based on the result.
1017bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001018EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001019{
1020#if 0
1021 // ARM pseudo code...
1022 if (ConditionPassed())
1023 {
1024 EncodingSpecificOperations();
1025 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1026 result = NOT(shifted);
1027 if d == 15 then // Can only occur for ARM encoding
1028 ALUWritePC(result); // setflags is always FALSE here
1029 else
1030 R[d] = result;
1031 if setflags then
1032 APSR.N = result<31>;
1033 APSR.Z = IsZeroBit(result);
1034 APSR.C = carry;
1035 // APSR.V unchanged
1036 }
1037#endif
1038
Greg Clayton7bc39082011-03-24 23:53:38 +00001039 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001040 {
1041 uint32_t Rm; // the source register
1042 uint32_t Rd; // the destination register
1043 ARM_ShifterType shift_t;
1044 uint32_t shift_n; // the shift applied to the value read from Rm
1045 bool setflags;
1046 uint32_t carry; // the carry bit after the shift operation
1047 switch (encoding) {
1048 case eEncodingT1:
1049 Rd = Bits32(opcode, 2, 0);
1050 Rm = Bits32(opcode, 5, 3);
1051 setflags = !InITBlock();
1052 shift_t = SRType_LSL;
1053 shift_n = 0;
1054 if (InITBlock())
1055 return false;
1056 break;
1057 case eEncodingT2:
1058 Rd = Bits32(opcode, 11, 8);
1059 Rm = Bits32(opcode, 3, 0);
1060 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001061 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001062 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001063 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001064 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001065 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001066 case eEncodingA1:
1067 Rd = Bits32(opcode, 15, 12);
1068 Rm = Bits32(opcode, 3, 0);
1069 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001070 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001071 break;
1072 default:
1073 return false;
1074 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001075 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001076 uint32_t value = ReadCoreReg(Rm, &success);
1077 if (!success)
1078 return false;
1079
1080 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1081 uint32_t result = ~shifted;
1082
1083 // The context specifies that an immediate is to be moved into Rd.
1084 EmulateInstruction::Context context;
1085 context.type = EmulateInstruction::eContextImmediate;
1086 context.SetNoArgs ();
1087
1088 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1089 return false;
1090 }
1091 return true;
1092}
1093
Johnny Chen788e0552011-01-27 22:52:23 +00001094// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1095// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001096bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001097EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001098{
1099#if 0
1100 // ARM pseudo code...
1101 if (ConditionPassed())
1102 {
1103 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1104 base = Align(PC,4);
1105 address = if add then (base + imm32) else (base - imm32);
1106 data = MemU[address,4];
1107 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001108 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1109 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001110 R[t] = data;
1111 else // Can only apply before ARMv7
1112 if CurrentInstrSet() == InstrSet_ARM then
1113 R[t] = ROR(data, 8*UInt(address<1:0>));
1114 else
1115 R[t] = bits(32) UNKNOWN;
1116 }
1117#endif
1118
Greg Clayton7bc39082011-03-24 23:53:38 +00001119 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001120 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001121 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001122 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001123 if (!success)
1124 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001125
1126 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001127 EmulateInstruction::Context context;
1128 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1129 Register pc_reg;
1130 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1131 context.SetRegisterPlusOffset (pc_reg, 0);
1132
Johnny Chenc9de9102011-02-11 19:12:30 +00001133 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001134 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001135 bool add; // +imm32 or -imm32?
1136 addr_t base; // the base address
1137 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001138 uint32_t data; // the literal data value from the PC relative load
1139 switch (encoding) {
1140 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001141 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001142 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001143 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001144 break;
1145 case eEncodingT2:
1146 Rt = Bits32(opcode, 15, 12);
1147 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1148 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001149 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001150 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001151 break;
1152 default:
1153 return false;
1154 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001155
Johnny Chene39f22d2011-02-19 01:36:13 +00001156 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001157 if (add)
1158 address = base + imm32;
1159 else
1160 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001161
1162 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001163 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001164 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001165 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001166
1167 if (Rt == 15)
1168 {
1169 if (Bits32(address, 1, 0) == 0)
1170 {
1171 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001172 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001173 return false;
1174 }
1175 else
1176 return false;
1177 }
1178 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1179 {
1180 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1181 return false;
1182 }
1183 else // We don't handle ARM for now.
1184 return false;
1185
Johnny Chen788e0552011-01-27 22:52:23 +00001186 }
1187 return true;
1188}
1189
Johnny Chen5b442b72011-01-27 19:34:30 +00001190// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001191// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001192bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001193EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001194{
1195#if 0
1196 // ARM pseudo code...
1197 if (ConditionPassed())
1198 {
1199 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001200 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001201 if d == 15 then // Can only occur for ARM encoding
1202 ALUWritePC(result); // setflags is always FALSE here
1203 else
1204 R[d] = result;
1205 if setflags then
1206 APSR.N = result<31>;
1207 APSR.Z = IsZeroBit(result);
1208 APSR.C = carry;
1209 APSR.V = overflow;
1210 }
1211#endif
1212
1213 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001214
Greg Clayton7bc39082011-03-24 23:53:38 +00001215 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001216 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001217 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001218 if (!success)
1219 return false;
1220 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001221 uint32_t d;
1222 bool setflags;
1223 switch (encoding)
1224 {
1225 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001226 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001227 d = Bits32 (opcode, 10, 8);
1228 setflags = false;
1229 imm32 = (Bits32 (opcode, 7, 0) << 2);
1230
1231 break;
1232
1233 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001234 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001235 d = 13;
1236 setflags = false;
1237 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1238
1239 break;
1240
1241 default:
1242 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001243 }
1244 addr_t sp_offset = imm32;
1245 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1246
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001247 EmulateInstruction::Context context;
1248 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice080bf612011-04-05 18:46:00 +00001249 Register sp_reg;
1250 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1251 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001252
Caroline Ticee2212882011-03-22 22:38:28 +00001253 if (d == 15)
1254 {
1255 if (!ALUWritePC (context, addr))
1256 return false;
1257 }
1258 else
1259 {
1260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1261 return false;
1262 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001263 }
1264 return true;
1265}
1266
1267// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001268// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001269bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001270EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001271{
1272#if 0
1273 // ARM pseudo code...
1274 if (ConditionPassed())
1275 {
1276 EncodingSpecificOperations();
1277 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001278 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001279 if d == 15 then
1280 ALUWritePC(result); // setflags is always FALSE here
1281 else
1282 R[d] = result;
1283 if setflags then
1284 APSR.N = result<31>;
1285 APSR.Z = IsZeroBit(result);
1286 APSR.C = carry;
1287 APSR.V = overflow;
1288 }
1289#endif
1290
1291 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001292
Greg Clayton7bc39082011-03-24 23:53:38 +00001293 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001294 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001295 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001296 if (!success)
1297 return false;
1298 uint32_t Rm; // the second operand
1299 switch (encoding) {
1300 case eEncodingT2:
1301 Rm = Bits32(opcode, 6, 3);
1302 break;
1303 default:
1304 return false;
1305 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001306 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001307 if (!success)
1308 return false;
1309
1310 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1311
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001312 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +00001313 context.type = EmulateInstruction::eContextAddition;
1314 Register sp_reg;
1315 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1316 Register other_reg;
1317 other_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1318 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001319
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001320 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001321 return false;
1322 }
1323 return true;
1324}
1325
Johnny Chen9b8d7832011-02-02 01:13:56 +00001326// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1327// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1328// from Thumb to ARM.
1329// BLX (immediate)
1330bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001331EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001332{
1333#if 0
1334 // ARM pseudo code...
1335 if (ConditionPassed())
1336 {
1337 EncodingSpecificOperations();
1338 if CurrentInstrSet() == InstrSet_ARM then
1339 LR = PC - 4;
1340 else
1341 LR = PC<31:1> : '1';
1342 if targetInstrSet == InstrSet_ARM then
1343 targetAddress = Align(PC,4) + imm32;
1344 else
1345 targetAddress = PC + imm32;
1346 SelectInstrSet(targetInstrSet);
1347 BranchWritePC(targetAddress);
1348 }
1349#endif
1350
Greg Clayton7bc39082011-03-24 23:53:38 +00001351 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001352
Greg Clayton7bc39082011-03-24 23:53:38 +00001353 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001354 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001355 EmulateInstruction::Context context;
1356 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001357 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001358 if (!success)
1359 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001360 addr_t lr; // next instruction address
1361 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001362 int32_t imm32; // PC-relative offset
1363 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001364 case eEncodingT1:
1365 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001366 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001367 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001368 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001369 uint32_t J1 = Bit32(opcode, 13);
1370 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001371 uint32_t imm11 = Bits32(opcode, 10, 0);
1372 uint32_t I1 = !(J1 ^ S);
1373 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001374 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001375 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001376 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001377 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001378 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001379 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001380 break;
1381 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001382 case eEncodingT2:
1383 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001384 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001385 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001386 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001387 uint32_t J1 = Bit32(opcode, 13);
1388 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001389 uint32_t imm10L = Bits32(opcode, 10, 1);
1390 uint32_t I1 = !(J1 ^ S);
1391 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001392 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001393 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001394 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001395 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001396 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001397 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001398 break;
1399 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001400 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001401 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001402 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001403 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001404 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001405 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001406 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001407 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001408 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001409 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001410 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001411 break;
1412 default:
1413 return false;
1414 }
1415 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1416 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001417 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001418 return false;
1419 }
1420 return true;
1421}
1422
1423// Branch with Link and Exchange (register) calls a subroutine at an address and
1424// instruction set specified by a register.
1425// BLX (register)
1426bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001427EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001428{
1429#if 0
1430 // ARM pseudo code...
1431 if (ConditionPassed())
1432 {
1433 EncodingSpecificOperations();
1434 target = R[m];
1435 if CurrentInstrSet() == InstrSet_ARM then
1436 next_instr_addr = PC - 4;
1437 LR = next_instr_addr;
1438 else
1439 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001440 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001441 BXWritePC(target);
1442 }
1443#endif
1444
1445 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001446
Greg Clayton7bc39082011-03-24 23:53:38 +00001447 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001448 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001449 EmulateInstruction::Context context;
1450 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001451 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001452 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001453 if (!success)
1454 return false;
1455 uint32_t Rm; // the register with the target address
1456 switch (encoding) {
1457 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001458 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001459 Rm = Bits32(opcode, 6, 3);
1460 // if m == 15 then UNPREDICTABLE;
1461 if (Rm == 15)
1462 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001463 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001464 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001465 break;
1466 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001467 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001468 Rm = Bits32(opcode, 3, 0);
1469 // if m == 15 then UNPREDICTABLE;
1470 if (Rm == 15)
1471 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001472 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001473 default:
1474 return false;
1475 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001476 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001477 if (!success)
1478 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001479 Register dwarf_reg;
1480 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1481 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001482 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1483 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001484 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001485 return false;
1486 }
1487 return true;
1488}
1489
Johnny Chenab3b3512011-02-12 00:10:51 +00001490// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001491bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001492EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001493{
1494#if 0
1495 // ARM pseudo code...
1496 if (ConditionPassed())
1497 {
1498 EncodingSpecificOperations();
1499 BXWritePC(R[m]);
1500 }
1501#endif
1502
Greg Clayton7bc39082011-03-24 23:53:38 +00001503 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001504 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001505 EmulateInstruction::Context context;
1506 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001507 uint32_t Rm; // the register with the target address
1508 switch (encoding) {
1509 case eEncodingT1:
1510 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001511 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001512 return false;
1513 break;
1514 case eEncodingA1:
1515 Rm = Bits32(opcode, 3, 0);
1516 break;
1517 default:
1518 return false;
1519 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001520 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001521 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001522 if (!success)
1523 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001524
1525 Register dwarf_reg;
1526 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001527 context.SetRegister (dwarf_reg);
1528 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001529 return false;
1530 }
1531 return true;
1532}
1533
Johnny Chen59e6ab72011-02-24 21:01:20 +00001534// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1535// address and instruction set specified by a register as though it were a BX instruction.
1536//
1537// TODO: Emulate Jazelle architecture?
1538// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1539bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001540EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001541{
1542#if 0
1543 // ARM pseudo code...
1544 if (ConditionPassed())
1545 {
1546 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001547 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001548 BXWritePC(R[m]);
1549 else
1550 if JazelleAcceptsExecution() then
1551 SwitchToJazelleExecution();
1552 else
1553 SUBARCHITECTURE_DEFINED handler call;
1554 }
1555#endif
1556
Greg Clayton7bc39082011-03-24 23:53:38 +00001557 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001558 {
1559 EmulateInstruction::Context context;
1560 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1561 uint32_t Rm; // the register with the target address
1562 switch (encoding) {
1563 case eEncodingT1:
1564 Rm = Bits32(opcode, 19, 16);
1565 if (BadReg(Rm))
1566 return false;
1567 if (InITBlock() && !LastInITBlock())
1568 return false;
1569 break;
1570 case eEncodingA1:
1571 Rm = Bits32(opcode, 3, 0);
1572 if (Rm == 15)
1573 return false;
1574 break;
1575 default:
1576 return false;
1577 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001578 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001579 addr_t target = ReadCoreReg (Rm, &success);
1580 if (!success)
1581 return false;
1582
1583 Register dwarf_reg;
1584 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1585 context.SetRegister (dwarf_reg);
1586 if (!BXWritePC(context, target))
1587 return false;
1588 }
1589 return true;
1590}
1591
Johnny Chen0d0148e2011-01-28 02:26:08 +00001592// Set r7 to point to some ip offset.
1593// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001594bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001595EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001596{
1597#if 0
1598 // ARM pseudo code...
1599 if (ConditionPassed())
1600 {
1601 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001602 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001603 if d == 15 then // Can only occur for ARM encoding
1604 ALUWritePC(result); // setflags is always FALSE here
1605 else
1606 R[d] = result;
1607 if setflags then
1608 APSR.N = result<31>;
1609 APSR.Z = IsZeroBit(result);
1610 APSR.C = carry;
1611 APSR.V = overflow;
1612 }
1613#endif
1614
Greg Clayton7bc39082011-03-24 23:53:38 +00001615 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001616 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001617 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001618 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001619 if (!success)
1620 return false;
1621 uint32_t imm32;
1622 switch (encoding) {
1623 case eEncodingA1:
1624 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1625 break;
1626 default:
1627 return false;
1628 }
1629 addr_t ip_offset = imm32;
1630 addr_t addr = ip - ip_offset; // the adjusted ip value
1631
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001632 EmulateInstruction::Context context;
1633 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1634 Register dwarf_reg;
1635 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1636 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001637
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001638 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001639 return false;
1640 }
1641 return true;
1642}
1643
1644// Set ip to point to some stack offset.
1645// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001646bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001647EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001648{
1649#if 0
1650 // ARM pseudo code...
1651 if (ConditionPassed())
1652 {
1653 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001654 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001655 if d == 15 then // Can only occur for ARM encoding
1656 ALUWritePC(result); // setflags is always FALSE here
1657 else
1658 R[d] = result;
1659 if setflags then
1660 APSR.N = result<31>;
1661 APSR.Z = IsZeroBit(result);
1662 APSR.C = carry;
1663 APSR.V = overflow;
1664 }
1665#endif
1666
Greg Clayton7bc39082011-03-24 23:53:38 +00001667 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001668 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001669 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001670 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001671 if (!success)
1672 return false;
1673 uint32_t imm32;
1674 switch (encoding) {
1675 case eEncodingA1:
1676 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1677 break;
1678 default:
1679 return false;
1680 }
1681 addr_t sp_offset = imm32;
1682 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1683
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001684 EmulateInstruction::Context context;
1685 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1686 Register dwarf_reg;
1687 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1688 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001689
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001690 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001691 return false;
1692 }
1693 return true;
1694}
1695
Johnny Chenc9e747f2011-02-23 01:55:07 +00001696// This instruction subtracts an immediate value from the SP value, and writes
1697// the result to the destination register.
1698//
1699// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001700bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001701EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001702{
1703#if 0
1704 // ARM pseudo code...
1705 if (ConditionPassed())
1706 {
1707 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001708 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001709 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001710 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001711 else
1712 R[d] = result;
1713 if setflags then
1714 APSR.N = result<31>;
1715 APSR.Z = IsZeroBit(result);
1716 APSR.C = carry;
1717 APSR.V = overflow;
1718 }
1719#endif
1720
1721 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001722 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001723 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001724 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001725 if (!success)
1726 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001727
1728 uint32_t Rd;
1729 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001730 uint32_t imm32;
1731 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001732 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001733 Rd = 13;
1734 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001735 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001736 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001737 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001738 Rd = Bits32(opcode, 11, 8);
1739 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001740 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001741 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001742 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001743 if (Rd == 15 && !setflags)
1744 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001745 break;
1746 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001747 Rd = Bits32(opcode, 11, 8);
1748 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001749 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001750 if (Rd == 15)
1751 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001752 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001753 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001754 Rd = Bits32(opcode, 15, 12);
1755 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001756 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001757
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001758 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001759 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001760 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001761 break;
1762 default:
1763 return false;
1764 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001765 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1766
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001767 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001768 if (Rd == 13)
1769 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001770 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1771 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001772 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001773 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001774 }
1775 else
1776 {
1777 context.type = EmulateInstruction::eContextImmediate;
1778 context.SetNoArgs ();
1779 }
1780
1781 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001782 return false;
1783 }
1784 return true;
1785}
1786
Johnny Chen08c25e82011-01-31 18:02:28 +00001787// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001788bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001789EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001790{
1791#if 0
1792 // ARM pseudo code...
1793 if (ConditionPassed())
1794 {
1795 EncodingSpecificOperations();
1796 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1797 address = if index then offset_addr else R[n];
1798 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1799 if wback then R[n] = offset_addr;
1800 }
1801#endif
1802
1803 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001804
Greg Clayton7bc39082011-03-24 23:53:38 +00001805 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001806 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001807 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001808 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001809 if (!success)
1810 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001811 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001812 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001813 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1814
1815 bool index;
1816 bool add;
1817 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001818 switch (encoding) {
1819 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001820 Rt = Bits32(opcode, 15, 12);
1821 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001822 Rn = Bits32 (opcode, 19, 16);
1823
1824 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1825 return false;
1826
1827 index = BitIsSet (opcode, 24);
1828 add = BitIsSet (opcode, 23);
1829 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1830
1831 if (wback && ((Rn == 15) || (Rn == Rt)))
1832 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001833 break;
1834 default:
1835 return false;
1836 }
Caroline Tice3e407972011-03-18 19:41:00 +00001837 addr_t offset_addr;
1838 if (add)
1839 offset_addr = sp + imm12;
1840 else
1841 offset_addr = sp - imm12;
1842
1843 addr_t addr;
1844 if (index)
1845 addr = offset_addr;
1846 else
1847 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001848
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001849 EmulateInstruction::Context context;
1850 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001851 Register sp_reg;
1852 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1853 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001854 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001855 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001856 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001857 if (!success)
1858 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001859 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001860 return false;
1861 }
1862 else
1863 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001864 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001865 if (!success)
1866 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001867 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001868 return false;
1869 }
1870
Caroline Tice3e407972011-03-18 19:41:00 +00001871
1872 if (wback)
1873 {
1874 context.type = EmulateInstruction::eContextAdjustStackPointer;
1875 context.SetImmediateSigned (addr - sp);
1876 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1877 return false;
1878 }
Johnny Chence1ca772011-01-25 01:13:00 +00001879 }
1880 return true;
1881}
1882
Johnny Chen08c25e82011-01-31 18:02:28 +00001883// Vector Push stores multiple extension registers to the stack.
1884// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001885bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001886EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001887{
1888#if 0
1889 // ARM pseudo code...
1890 if (ConditionPassed())
1891 {
1892 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1893 address = SP - imm32;
1894 SP = SP - imm32;
1895 if single_regs then
1896 for r = 0 to regs-1
1897 MemA[address,4] = S[d+r]; address = address+4;
1898 else
1899 for r = 0 to regs-1
1900 // Store as two word-aligned words in the correct order for current endianness.
1901 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1902 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1903 address = address+8;
1904 }
1905#endif
1906
1907 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001908
Greg Clayton7bc39082011-03-24 23:53:38 +00001909 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001910 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001911 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001912 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001913 if (!success)
1914 return false;
1915 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001916 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001917 uint32_t imm32; // stack offset
1918 uint32_t regs; // number of registers
1919 switch (encoding) {
1920 case eEncodingT1:
1921 case eEncodingA1:
1922 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001923 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001924 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1925 // If UInt(imm8) is odd, see "FSTMX".
1926 regs = Bits32(opcode, 7, 0) / 2;
1927 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1928 if (regs == 0 || regs > 16 || (d + regs) > 32)
1929 return false;
1930 break;
1931 case eEncodingT2:
1932 case eEncodingA2:
1933 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001934 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001935 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1936 regs = Bits32(opcode, 7, 0);
1937 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1938 if (regs == 0 || regs > 16 || (d + regs) > 32)
1939 return false;
1940 break;
1941 default:
1942 return false;
1943 }
1944 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1945 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1946 addr_t sp_offset = imm32;
1947 addr_t addr = sp - sp_offset;
1948 uint32_t i;
1949
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001950 EmulateInstruction::Context context;
1951 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1952 Register dwarf_reg;
1953 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001954 Register sp_reg;
1955 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1956 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001957 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001958 dwarf_reg.num = start_reg + d + i;
1959 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001960 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001961 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001962 if (!success)
1963 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001964 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001965 return false;
1966 addr += reg_byte_size;
1967 }
1968
1969 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001970 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001971
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001972 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001973 return false;
1974 }
1975 return true;
1976}
1977
Johnny Chen587a0a42011-02-01 18:35:28 +00001978// Vector Pop loads multiple extension registers from the stack.
1979// It also updates SP to point just above the loaded data.
1980bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001981EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00001982{
1983#if 0
1984 // ARM pseudo code...
1985 if (ConditionPassed())
1986 {
1987 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1988 address = SP;
1989 SP = SP + imm32;
1990 if single_regs then
1991 for r = 0 to regs-1
1992 S[d+r] = MemA[address,4]; address = address+4;
1993 else
1994 for r = 0 to regs-1
1995 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1996 // Combine the word-aligned words in the correct order for current endianness.
1997 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1998 }
1999#endif
2000
2001 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002002
Greg Clayton7bc39082011-03-24 23:53:38 +00002003 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002004 {
2005 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002006 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002007 if (!success)
2008 return false;
2009 bool single_regs;
2010 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2011 uint32_t imm32; // stack offset
2012 uint32_t regs; // number of registers
2013 switch (encoding) {
2014 case eEncodingT1:
2015 case eEncodingA1:
2016 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002017 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002018 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2019 // If UInt(imm8) is odd, see "FLDMX".
2020 regs = Bits32(opcode, 7, 0) / 2;
2021 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2022 if (regs == 0 || regs > 16 || (d + regs) > 32)
2023 return false;
2024 break;
2025 case eEncodingT2:
2026 case eEncodingA2:
2027 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002028 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002029 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2030 regs = Bits32(opcode, 7, 0);
2031 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2032 if (regs == 0 || regs > 16 || (d + regs) > 32)
2033 return false;
2034 break;
2035 default:
2036 return false;
2037 }
2038 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2039 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2040 addr_t sp_offset = imm32;
2041 addr_t addr = sp;
2042 uint32_t i;
2043 uint64_t data; // uint64_t to accomodate 64-bit registers.
2044
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002045 EmulateInstruction::Context context;
2046 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2047 Register dwarf_reg;
2048 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002049 Register sp_reg;
2050 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
2051 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002052 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002053 dwarf_reg.num = start_reg + d + i;
2054 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002055 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002056 if (!success)
2057 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002058 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002059 return false;
2060 addr += reg_byte_size;
2061 }
2062
2063 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002064 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002065
2066 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2067 return false;
2068 }
2069 return true;
2070}
2071
Johnny Chenb77be412011-02-04 00:40:18 +00002072// SVC (previously SWI)
2073bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002074EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002075{
2076#if 0
2077 // ARM pseudo code...
2078 if (ConditionPassed())
2079 {
2080 EncodingSpecificOperations();
2081 CallSupervisor();
2082 }
2083#endif
2084
2085 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002086
Greg Clayton7bc39082011-03-24 23:53:38 +00002087 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002088 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002089 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002090 addr_t lr; // next instruction address
2091 if (!success)
2092 return false;
2093 uint32_t imm32; // the immediate constant
2094 uint32_t mode; // ARM or Thumb mode
2095 switch (encoding) {
2096 case eEncodingT1:
2097 lr = (pc + 2) | 1u; // return address
2098 imm32 = Bits32(opcode, 7, 0);
2099 mode = eModeThumb;
2100 break;
2101 case eEncodingA1:
2102 lr = pc + 4; // return address
2103 imm32 = Bits32(opcode, 23, 0);
2104 mode = eModeARM;
2105 break;
2106 default:
2107 return false;
2108 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002109
2110 EmulateInstruction::Context context;
2111 context.type = EmulateInstruction::eContextSupervisorCall;
2112 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002113 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2114 return false;
2115 }
2116 return true;
2117}
2118
Johnny Chenc315f862011-02-05 00:46:10 +00002119// If Then makes up to four following instructions (the IT block) conditional.
2120bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002121EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002122{
2123#if 0
2124 // ARM pseudo code...
2125 EncodingSpecificOperations();
2126 ITSTATE.IT<7:0> = firstcond:mask;
2127#endif
2128
Johnny Chenc315f862011-02-05 00:46:10 +00002129 m_it_session.InitIT(Bits32(opcode, 7, 0));
2130 return true;
2131}
2132
Johnny Chen3b620b32011-02-07 20:11:47 +00002133// Branch causes a branch to a target address.
2134bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002135EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002136{
2137#if 0
2138 // ARM pseudo code...
2139 if (ConditionPassed())
2140 {
2141 EncodingSpecificOperations();
2142 BranchWritePC(PC + imm32);
2143 }
2144#endif
2145
2146 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002147
Greg Clayton7bc39082011-03-24 23:53:38 +00002148 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002149 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002150 EmulateInstruction::Context context;
2151 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002152 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002153 if (!success)
2154 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002155 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002156 int32_t imm32; // PC-relative offset
2157 switch (encoding) {
2158 case eEncodingT1:
2159 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2160 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002161 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002162 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002163 break;
2164 case eEncodingT2:
2165 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002166 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002167 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002168 break;
2169 case eEncodingT3:
2170 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2171 {
Johnny Chenbd599902011-02-10 21:39:01 +00002172 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002173 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002174 uint32_t J1 = Bit32(opcode, 13);
2175 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002176 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002177 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002178 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002179 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002180 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002181 break;
2182 }
2183 case eEncodingT4:
2184 {
Johnny Chenbd599902011-02-10 21:39:01 +00002185 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002186 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002187 uint32_t J1 = Bit32(opcode, 13);
2188 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002189 uint32_t imm11 = Bits32(opcode, 10, 0);
2190 uint32_t I1 = !(J1 ^ S);
2191 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002192 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002193 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002194 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002195 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002196 break;
2197 }
2198 case eEncodingA1:
2199 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002200 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002201 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002202 break;
2203 default:
2204 return false;
2205 }
2206 if (!BranchWritePC(context, target))
2207 return false;
2208 }
2209 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002210}
2211
Johnny Chen53ebab72011-02-08 23:21:57 +00002212// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2213// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2214// CBNZ, CBZ
2215bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002216EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002217{
2218#if 0
2219 // ARM pseudo code...
2220 EncodingSpecificOperations();
2221 if nonzero ^ IsZero(R[n]) then
2222 BranchWritePC(PC + imm32);
2223#endif
2224
2225 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002226
2227 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002228 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002229 if (!success)
2230 return false;
2231
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002232 EmulateInstruction::Context context;
2233 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002234 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002235 if (!success)
2236 return false;
2237
2238 addr_t target; // target address
2239 uint32_t imm32; // PC-relative offset to branch forward
2240 bool nonzero;
2241 switch (encoding) {
2242 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002243 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002244 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002245 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002246 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002247 break;
2248 default:
2249 return false;
2250 }
2251 if (nonzero ^ (reg_val == 0))
2252 if (!BranchWritePC(context, target))
2253 return false;
2254
2255 return true;
2256}
2257
Johnny Chen60299ec2011-02-17 19:34:27 +00002258// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2259// A base register provides a pointer to the table, and a second register supplies an index into the table.
2260// The branch length is twice the value of the byte returned from the table.
2261//
2262// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2263// A base register provides a pointer to the table, and a second register supplies an index into the table.
2264// The branch length is twice the value of the halfword returned from the table.
2265// TBB, TBH
2266bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002267EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002268{
2269#if 0
2270 // ARM pseudo code...
2271 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2272 if is_tbh then
2273 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2274 else
2275 halfwords = UInt(MemU[R[n]+R[m], 1]);
2276 BranchWritePC(PC + 2*halfwords);
2277#endif
2278
2279 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002280
2281 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2282 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2283 bool is_tbh; // true if table branch halfword
2284 switch (encoding) {
2285 case eEncodingT1:
2286 Rn = Bits32(opcode, 19, 16);
2287 Rm = Bits32(opcode, 3, 0);
2288 is_tbh = BitIsSet(opcode, 4);
2289 if (Rn == 13 || BadReg(Rm))
2290 return false;
2291 if (InITBlock() && !LastInITBlock())
2292 return false;
2293 break;
2294 default:
2295 return false;
2296 }
2297
2298 // Read the address of the table from the operand register Rn.
2299 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002300 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002301 if (!success)
2302 return false;
2303
2304 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002305 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002306 if (!success)
2307 return false;
2308
2309 // the offsetted table address
2310 addr_t addr = base + (is_tbh ? index*2 : index);
2311
2312 // PC-relative offset to branch forward
2313 EmulateInstruction::Context context;
2314 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002315 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002316 if (!success)
2317 return false;
2318
Johnny Chene39f22d2011-02-19 01:36:13 +00002319 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002320 if (!success)
2321 return false;
2322
2323 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002324 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002325 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2326 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2327
2328 if (!BranchWritePC(context, target))
2329 return false;
2330
2331 return true;
2332}
2333
Caroline Ticedcc11b32011-03-02 23:57:02 +00002334// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2335// It can optionally update the condition flags based on the result.
2336bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002337EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002338{
2339#if 0
2340 if ConditionPassed() then
2341 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002342 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002343 R[d] = result;
2344 if setflags then
2345 APSR.N = result<31>;
2346 APSR.Z = IsZeroBit(result);
2347 APSR.C = carry;
2348 APSR.V = overflow;
2349#endif
2350
2351 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002352
Greg Clayton7bc39082011-03-24 23:53:38 +00002353 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002354 {
2355 uint32_t d;
2356 uint32_t n;
2357 bool setflags;
2358 uint32_t imm32;
2359 uint32_t carry_out;
2360
2361 //EncodingSpecificOperations();
2362 switch (encoding)
2363 {
2364 case eEncodingT1:
2365 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2366 d = Bits32 (opcode, 2, 0);
2367 n = Bits32 (opcode, 5, 3);
2368 setflags = !InITBlock();
2369 imm32 = Bits32 (opcode, 8,6);
2370
2371 break;
2372
2373 case eEncodingT2:
2374 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2375 d = Bits32 (opcode, 10, 8);
2376 n = Bits32 (opcode, 10, 8);
2377 setflags = !InITBlock();
2378 imm32 = Bits32 (opcode, 7, 0);
2379
2380 break;
2381
2382 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002383 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2384 // if Rn == '1101' then SEE ADD (SP plus immediate);
2385 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002386 d = Bits32 (opcode, 11, 8);
2387 n = Bits32 (opcode, 19, 16);
2388 setflags = BitIsSet (opcode, 20);
2389 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2390
2391 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2392 if (BadReg (d) || (n == 15))
2393 return false;
2394
2395 break;
2396
2397 case eEncodingT4:
2398 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002399 // if Rn == '1111' then SEE ADR;
2400 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002401 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2402 d = Bits32 (opcode, 11, 8);
2403 n = Bits32 (opcode, 19, 16);
2404 setflags = false;
2405 uint32_t i = Bit32 (opcode, 26);
2406 uint32_t imm3 = Bits32 (opcode, 14, 12);
2407 uint32_t imm8 = Bits32 (opcode, 7, 0);
2408 imm32 = (i << 11) | (imm3 << 8) | imm8;
2409
2410 // if BadReg(d) then UNPREDICTABLE;
2411 if (BadReg (d))
2412 return false;
2413
2414 break;
2415 }
2416 default:
2417 return false;
2418 }
2419
2420 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2421 if (!success)
2422 return false;
2423
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002424 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002425 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2426
2427 Register reg_n;
2428 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2429
2430 EmulateInstruction::Context context;
2431 context.type = eContextAddition;
2432 context.SetRegisterPlusOffset (reg_n, imm32);
2433
2434 //R[d] = result;
2435 //if setflags then
2436 //APSR.N = result<31>;
2437 //APSR.Z = IsZeroBit(result);
2438 //APSR.C = carry;
2439 //APSR.V = overflow;
2440 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2441 return false;
2442
2443 }
2444 return true;
2445}
2446
Johnny Chen8fa20592011-02-18 01:22:22 +00002447// This instruction adds an immediate value to a register value, and writes the result to the destination
2448// register. It can optionally update the condition flags based on the result.
2449bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002450EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002451{
2452#if 0
2453 // ARM pseudo code...
2454 if ConditionPassed() then
2455 EncodingSpecificOperations();
2456 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2457 if d == 15 then
2458 ALUWritePC(result); // setflags is always FALSE here
2459 else
2460 R[d] = result;
2461 if setflags then
2462 APSR.N = result<31>;
2463 APSR.Z = IsZeroBit(result);
2464 APSR.C = carry;
2465 APSR.V = overflow;
2466#endif
2467
2468 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002469
Greg Clayton7bc39082011-03-24 23:53:38 +00002470 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002471 {
2472 uint32_t Rd, Rn;
2473 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2474 bool setflags;
2475 switch (encoding)
2476 {
2477 case eEncodingA1:
2478 Rd = Bits32(opcode, 15, 12);
2479 Rn = Bits32(opcode, 19, 16);
2480 setflags = BitIsSet(opcode, 20);
2481 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2482 break;
2483 default:
2484 return false;
2485 }
2486
Johnny Chen8fa20592011-02-18 01:22:22 +00002487 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002488 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002489 if (!success)
2490 return false;
2491
2492 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2493
2494 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +00002495 context.type = EmulateInstruction::eContextAddition;
2496 Register dwarf_reg;
2497 dwarf_reg.SetRegister (eRegisterKindDWARF, Rn);
2498 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002499
2500 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2501 return false;
2502 }
2503 return true;
2504}
2505
Johnny Chend761dcf2011-02-17 22:03:29 +00002506// This instruction adds a register value and an optionally-shifted register value, and writes the result
2507// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002508bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002509EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002510{
2511#if 0
2512 // ARM pseudo code...
2513 if ConditionPassed() then
2514 EncodingSpecificOperations();
2515 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2516 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2517 if d == 15 then
2518 ALUWritePC(result); // setflags is always FALSE here
2519 else
2520 R[d] = result;
2521 if setflags then
2522 APSR.N = result<31>;
2523 APSR.Z = IsZeroBit(result);
2524 APSR.C = carry;
2525 APSR.V = overflow;
2526#endif
2527
2528 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002529
Greg Clayton7bc39082011-03-24 23:53:38 +00002530 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002531 {
2532 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002533 ARM_ShifterType shift_t;
2534 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002535 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002536 switch (encoding)
2537 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002538 case eEncodingT1:
2539 Rd = Bits32(opcode, 2, 0);
2540 Rn = Bits32(opcode, 5, 3);
2541 Rm = Bits32(opcode, 8, 6);
2542 setflags = !InITBlock();
2543 shift_t = SRType_LSL;
2544 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002545 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002546 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002547 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002548 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002549 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002550 shift_t = SRType_LSL;
2551 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002552 if (Rn == 15 && Rm == 15)
2553 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002554 if (Rd == 15 && InITBlock() && !LastInITBlock())
2555 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002556 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002557 case eEncodingA1:
2558 Rd = Bits32(opcode, 15, 12);
2559 Rn = Bits32(opcode, 19, 16);
2560 Rm = Bits32(opcode, 3, 0);
2561 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002562 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002563 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002564 default:
2565 return false;
2566 }
2567
Johnny Chen26863dc2011-02-09 23:43:29 +00002568 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002569 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002570 if (!success)
2571 return false;
2572
2573 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002574 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002575 if (!success)
2576 return false;
2577
Johnny Chene97c0d52011-02-18 19:32:20 +00002578 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002579 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002580
2581 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002582 context.type = EmulateInstruction::eContextAddition;
2583 Register op1_reg;
2584 Register op2_reg;
2585 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2586 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2587 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002588
Johnny Chen10530c22011-02-17 22:37:12 +00002589 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002590 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002591 }
2592 return true;
2593}
2594
Johnny Chen34075cb2011-02-22 01:56:31 +00002595// Compare Negative (immediate) adds a register value and an immediate value.
2596// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002597bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002598EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002599{
2600#if 0
2601 // ARM pseudo code...
2602 if ConditionPassed() then
2603 EncodingSpecificOperations();
2604 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2605 APSR.N = result<31>;
2606 APSR.Z = IsZeroBit(result);
2607 APSR.C = carry;
2608 APSR.V = overflow;
2609#endif
2610
2611 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002612
2613 uint32_t Rn; // the first operand
2614 uint32_t imm32; // the immediate value to be compared with
2615 switch (encoding) {
2616 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002617 Rn = Bits32(opcode, 19, 16);
2618 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2619 if (Rn == 15)
2620 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002621 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002622 case eEncodingA1:
2623 Rn = Bits32(opcode, 19, 16);
2624 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2625 break;
2626 default:
2627 return false;
2628 }
2629 // Read the register value from the operand register Rn.
2630 uint32_t reg_val = ReadCoreReg(Rn, &success);
2631 if (!success)
2632 return false;
2633
Johnny Chen078fbc62011-02-22 19:48:22 +00002634 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002635
2636 EmulateInstruction::Context context;
2637 context.type = EmulateInstruction::eContextImmediate;
2638 context.SetNoArgs ();
2639 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2640 return false;
2641
2642 return true;
2643}
2644
2645// Compare Negative (register) adds a register value and an optionally-shifted register value.
2646// It updates the condition flags based on the result, and discards the result.
2647bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002648EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002649{
2650#if 0
2651 // ARM pseudo code...
2652 if ConditionPassed() then
2653 EncodingSpecificOperations();
2654 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2655 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2656 APSR.N = result<31>;
2657 APSR.Z = IsZeroBit(result);
2658 APSR.C = carry;
2659 APSR.V = overflow;
2660#endif
2661
2662 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002663
2664 uint32_t Rn; // the first operand
2665 uint32_t Rm; // the second operand
2666 ARM_ShifterType shift_t;
2667 uint32_t shift_n; // the shift applied to the value read from Rm
2668 switch (encoding) {
2669 case eEncodingT1:
2670 Rn = Bits32(opcode, 2, 0);
2671 Rm = Bits32(opcode, 5, 3);
2672 shift_t = SRType_LSL;
2673 shift_n = 0;
2674 break;
2675 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002676 Rn = Bits32(opcode, 19, 16);
2677 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002678 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002679 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2680 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002681 return false;
2682 break;
2683 case eEncodingA1:
2684 Rn = Bits32(opcode, 19, 16);
2685 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002686 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002687 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002688 default:
2689 return false;
2690 }
2691 // Read the register value from register Rn.
2692 uint32_t val1 = ReadCoreReg(Rn, &success);
2693 if (!success)
2694 return false;
2695
2696 // Read the register value from register Rm.
2697 uint32_t val2 = ReadCoreReg(Rm, &success);
2698 if (!success)
2699 return false;
2700
2701 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002702 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002703
2704 EmulateInstruction::Context context;
2705 context.type = EmulateInstruction::eContextImmediate;
2706 context.SetNoArgs();
2707 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2708 return false;
2709
2710 return true;
2711}
2712
2713// Compare (immediate) subtracts an immediate value from a register value.
2714// It updates the condition flags based on the result, and discards the result.
2715bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002716EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002717{
2718#if 0
2719 // ARM pseudo code...
2720 if ConditionPassed() then
2721 EncodingSpecificOperations();
2722 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2723 APSR.N = result<31>;
2724 APSR.Z = IsZeroBit(result);
2725 APSR.C = carry;
2726 APSR.V = overflow;
2727#endif
2728
2729 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002730
2731 uint32_t Rn; // the first operand
2732 uint32_t imm32; // the immediate value to be compared with
2733 switch (encoding) {
2734 case eEncodingT1:
2735 Rn = Bits32(opcode, 10, 8);
2736 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002737 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002738 case eEncodingT2:
2739 Rn = Bits32(opcode, 19, 16);
2740 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2741 if (Rn == 15)
2742 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002743 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002744 case eEncodingA1:
2745 Rn = Bits32(opcode, 19, 16);
2746 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002747 break;
2748 default:
2749 return false;
2750 }
2751 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002752 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002753 if (!success)
2754 return false;
2755
Johnny Chen10530c22011-02-17 22:37:12 +00002756 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2757
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002758 EmulateInstruction::Context context;
2759 context.type = EmulateInstruction::eContextImmediate;
2760 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002761 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2762 return false;
2763
Johnny Chend4dc4442011-02-11 02:02:56 +00002764 return true;
2765}
2766
Johnny Chen34075cb2011-02-22 01:56:31 +00002767// Compare (register) subtracts an optionally-shifted register value from a register value.
2768// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002769bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002770EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002771{
2772#if 0
2773 // ARM pseudo code...
2774 if ConditionPassed() then
2775 EncodingSpecificOperations();
2776 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2777 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2778 APSR.N = result<31>;
2779 APSR.Z = IsZeroBit(result);
2780 APSR.C = carry;
2781 APSR.V = overflow;
2782#endif
2783
2784 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002785
2786 uint32_t Rn; // the first operand
2787 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002788 ARM_ShifterType shift_t;
2789 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002790 switch (encoding) {
2791 case eEncodingT1:
2792 Rn = Bits32(opcode, 2, 0);
2793 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002794 shift_t = SRType_LSL;
2795 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002796 break;
2797 case eEncodingT2:
2798 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2799 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002800 shift_t = SRType_LSL;
2801 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002802 if (Rn < 8 && Rm < 8)
2803 return false;
2804 if (Rn == 15 || Rm == 15)
2805 return false;
2806 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002807 case eEncodingA1:
2808 Rn = Bits32(opcode, 19, 16);
2809 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002810 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002811 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002812 default:
2813 return false;
2814 }
2815 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002816 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002817 if (!success)
2818 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002819
Johnny Chene4a4d302011-02-11 21:53:58 +00002820 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002821 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002822 if (!success)
2823 return false;
2824
Johnny Chen34075cb2011-02-22 01:56:31 +00002825 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2826 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002827
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002828 EmulateInstruction::Context context;
2829 context.type = EmulateInstruction::eContextImmediate;
2830 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002831 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2832 return false;
2833
Johnny Chene4a4d302011-02-11 21:53:58 +00002834 return true;
2835}
2836
Johnny Chen82f16aa2011-02-15 20:10:55 +00002837// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2838// shifting in copies of its sign bit, and writes the result to the destination register. It can
2839// optionally update the condition flags based on the result.
2840bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002841EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002842{
2843#if 0
2844 // ARM pseudo code...
2845 if ConditionPassed() then
2846 EncodingSpecificOperations();
2847 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2848 if d == 15 then // Can only occur for ARM encoding
2849 ALUWritePC(result); // setflags is always FALSE here
2850 else
2851 R[d] = result;
2852 if setflags then
2853 APSR.N = result<31>;
2854 APSR.Z = IsZeroBit(result);
2855 APSR.C = carry;
2856 // APSR.V unchanged
2857#endif
2858
Greg Clayton7bc39082011-03-24 23:53:38 +00002859 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002860}
2861
2862// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2863// shifting in copies of its sign bit, and writes the result to the destination register.
2864// The variable number of bits is read from the bottom byte of a register. It can optionally update
2865// the condition flags based on the result.
2866bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002867EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002868{
2869#if 0
2870 // ARM pseudo code...
2871 if ConditionPassed() then
2872 EncodingSpecificOperations();
2873 shift_n = UInt(R[m]<7:0>);
2874 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2875 R[d] = result;
2876 if setflags then
2877 APSR.N = result<31>;
2878 APSR.Z = IsZeroBit(result);
2879 APSR.C = carry;
2880 // APSR.V unchanged
2881#endif
2882
Greg Clayton7bc39082011-03-24 23:53:38 +00002883 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002884}
2885
2886// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2887// shifting in zeros, and writes the result to the destination register. It can optionally
2888// update the condition flags based on the result.
2889bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002890EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002891{
2892#if 0
2893 // ARM pseudo code...
2894 if ConditionPassed() then
2895 EncodingSpecificOperations();
2896 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2897 if d == 15 then // Can only occur for ARM encoding
2898 ALUWritePC(result); // setflags is always FALSE here
2899 else
2900 R[d] = result;
2901 if setflags then
2902 APSR.N = result<31>;
2903 APSR.Z = IsZeroBit(result);
2904 APSR.C = carry;
2905 // APSR.V unchanged
2906#endif
2907
Greg Clayton7bc39082011-03-24 23:53:38 +00002908 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002909}
2910
2911// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2912// shifting in zeros, and writes the result to the destination register. The variable number
2913// of bits is read from the bottom byte of a register. It can optionally update the condition
2914// flags based on the result.
2915bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002916EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002917{
2918#if 0
2919 // ARM pseudo code...
2920 if ConditionPassed() then
2921 EncodingSpecificOperations();
2922 shift_n = UInt(R[m]<7:0>);
2923 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2924 R[d] = result;
2925 if setflags then
2926 APSR.N = result<31>;
2927 APSR.Z = IsZeroBit(result);
2928 APSR.C = carry;
2929 // APSR.V unchanged
2930#endif
2931
Greg Clayton7bc39082011-03-24 23:53:38 +00002932 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002933}
2934
2935// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2936// shifting in zeros, and writes the result to the destination register. It can optionally
2937// update the condition flags based on the result.
2938bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002939EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002940{
2941#if 0
2942 // ARM pseudo code...
2943 if ConditionPassed() then
2944 EncodingSpecificOperations();
2945 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2946 if d == 15 then // Can only occur for ARM encoding
2947 ALUWritePC(result); // setflags is always FALSE here
2948 else
2949 R[d] = result;
2950 if setflags then
2951 APSR.N = result<31>;
2952 APSR.Z = IsZeroBit(result);
2953 APSR.C = carry;
2954 // APSR.V unchanged
2955#endif
2956
Greg Clayton7bc39082011-03-24 23:53:38 +00002957 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002958}
2959
2960// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2961// shifting in zeros, and writes the result to the destination register. The variable number
2962// of bits is read from the bottom byte of a register. It can optionally update the condition
2963// flags based on the result.
2964bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002965EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002966{
2967#if 0
2968 // ARM pseudo code...
2969 if ConditionPassed() then
2970 EncodingSpecificOperations();
2971 shift_n = UInt(R[m]<7:0>);
2972 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2973 R[d] = result;
2974 if setflags then
2975 APSR.N = result<31>;
2976 APSR.Z = IsZeroBit(result);
2977 APSR.C = carry;
2978 // APSR.V unchanged
2979#endif
2980
Greg Clayton7bc39082011-03-24 23:53:38 +00002981 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002982}
2983
Johnny Cheneeab4852011-02-16 22:14:44 +00002984// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2985// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2986// It can optionally update the condition flags based on the result.
2987bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002988EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002989{
2990#if 0
2991 // ARM pseudo code...
2992 if ConditionPassed() then
2993 EncodingSpecificOperations();
2994 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2995 if d == 15 then // Can only occur for ARM encoding
2996 ALUWritePC(result); // setflags is always FALSE here
2997 else
2998 R[d] = result;
2999 if setflags then
3000 APSR.N = result<31>;
3001 APSR.Z = IsZeroBit(result);
3002 APSR.C = carry;
3003 // APSR.V unchanged
3004#endif
3005
Greg Clayton7bc39082011-03-24 23:53:38 +00003006 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003007}
3008
3009// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3010// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3011// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3012// flags based on the result.
3013bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003014EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003015{
3016#if 0
3017 // ARM pseudo code...
3018 if ConditionPassed() then
3019 EncodingSpecificOperations();
3020 shift_n = UInt(R[m]<7:0>);
3021 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3022 R[d] = result;
3023 if setflags then
3024 APSR.N = result<31>;
3025 APSR.Z = IsZeroBit(result);
3026 APSR.C = carry;
3027 // APSR.V unchanged
3028#endif
3029
Greg Clayton7bc39082011-03-24 23:53:38 +00003030 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003031}
3032
3033// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3034// with the carry flag shifted into bit [31].
3035//
3036// RRX can optionally update the condition flags based on the result.
3037// In that case, bit [0] is shifted into the carry flag.
3038bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003039EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003040{
3041#if 0
3042 // ARM pseudo code...
3043 if ConditionPassed() then
3044 EncodingSpecificOperations();
3045 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3046 if d == 15 then // Can only occur for ARM encoding
3047 ALUWritePC(result); // setflags is always FALSE here
3048 else
3049 R[d] = result;
3050 if setflags then
3051 APSR.N = result<31>;
3052 APSR.Z = IsZeroBit(result);
3053 APSR.C = carry;
3054 // APSR.V unchanged
3055#endif
3056
Greg Clayton7bc39082011-03-24 23:53:38 +00003057 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003058}
3059
Johnny Chen41a0a152011-02-16 01:27:54 +00003060bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003061EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003062{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003063 assert(shift_type == SRType_ASR
3064 || shift_type == SRType_LSL
3065 || shift_type == SRType_LSR
3066 || shift_type == SRType_ROR
3067 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003068
Johnny Chen82f16aa2011-02-15 20:10:55 +00003069 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003070
Greg Clayton7bc39082011-03-24 23:53:38 +00003071 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003072 {
Johnny Chene7f89532011-02-15 23:22:46 +00003073 uint32_t Rd; // the destination register
3074 uint32_t Rm; // the first operand register
3075 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003076 uint32_t carry; // the carry bit after the shift operation
3077 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003078
3079 // Special case handling!
3080 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003081 ARMEncoding use_encoding = encoding;
3082 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003083 {
3084 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3085 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003086 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003087 }
3088
Greg Clayton7bc39082011-03-24 23:53:38 +00003089 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003090 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003091 // Due to the above special case handling!
3092 assert(shift_type != SRType_ROR);
3093
Johnny Chen82f16aa2011-02-15 20:10:55 +00003094 Rd = Bits32(opcode, 2, 0);
3095 Rm = Bits32(opcode, 5, 3);
3096 setflags = !InITBlock();
3097 imm5 = Bits32(opcode, 10, 6);
3098 break;
3099 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003100 // A8.6.141 RRX
3101 assert(shift_type != SRType_RRX);
3102
Johnny Chen82f16aa2011-02-15 20:10:55 +00003103 Rd = Bits32(opcode, 11, 8);
3104 Rm = Bits32(opcode, 3, 0);
3105 setflags = BitIsSet(opcode, 20);
3106 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3107 if (BadReg(Rd) || BadReg(Rm))
3108 return false;
3109 break;
3110 case eEncodingA1:
3111 Rd = Bits32(opcode, 15, 12);
3112 Rm = Bits32(opcode, 3, 0);
3113 setflags = BitIsSet(opcode, 20);
3114 imm5 = Bits32(opcode, 11, 7);
3115 break;
3116 default:
3117 return false;
3118 }
3119
Johnny Cheneeab4852011-02-16 22:14:44 +00003120 // A8.6.139 ROR (immediate)
3121 if (shift_type == SRType_ROR && imm5 == 0)
3122 shift_type = SRType_RRX;
3123
Johnny Chen82f16aa2011-02-15 20:10:55 +00003124 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003125 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003126 if (!success)
3127 return false;
3128
Johnny Cheneeab4852011-02-16 22:14:44 +00003129 // Decode the shift amount if not RRX.
3130 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003131
Johnny Chene97c0d52011-02-18 19:32:20 +00003132 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003133
3134 // The context specifies that an immediate is to be moved into Rd.
3135 EmulateInstruction::Context context;
3136 context.type = EmulateInstruction::eContextImmediate;
3137 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003138
Johnny Chen10530c22011-02-17 22:37:12 +00003139 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003140 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003141 }
3142 return true;
3143}
3144
Johnny Chene7f89532011-02-15 23:22:46 +00003145bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003146EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003147{
Johnny Chen41a0a152011-02-16 01:27:54 +00003148 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003149
3150 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003151
Greg Clayton7bc39082011-03-24 23:53:38 +00003152 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003153 {
3154 uint32_t Rd; // the destination register
3155 uint32_t Rn; // the first operand register
3156 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3157 uint32_t carry; // the carry bit after the shift operation
3158 bool setflags;
3159 switch (encoding) {
3160 case eEncodingT1:
3161 Rd = Bits32(opcode, 2, 0);
3162 Rn = Rd;
3163 Rm = Bits32(opcode, 5, 3);
3164 setflags = !InITBlock();
3165 break;
3166 case eEncodingT2:
3167 Rd = Bits32(opcode, 11, 8);
3168 Rn = Bits32(opcode, 19, 16);
3169 Rm = Bits32(opcode, 3, 0);
3170 setflags = BitIsSet(opcode, 20);
3171 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3172 return false;
3173 break;
3174 case eEncodingA1:
3175 Rd = Bits32(opcode, 15, 12);
3176 Rn = Bits32(opcode, 3, 0);
3177 Rm = Bits32(opcode, 11, 8);
3178 setflags = BitIsSet(opcode, 20);
3179 if (Rd == 15 || Rn == 15 || Rm == 15)
3180 return false;
3181 break;
3182 default:
3183 return false;
3184 }
3185
3186 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003187 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003188 if (!success)
3189 return false;
3190 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003191 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003192 if (!success)
3193 return false;
3194
3195 // Get the shift amount.
3196 uint32_t amt = Bits32(val, 7, 0);
3197
Johnny Chene97c0d52011-02-18 19:32:20 +00003198 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003199
3200 // The context specifies that an immediate is to be moved into Rd.
3201 EmulateInstruction::Context context;
3202 context.type = EmulateInstruction::eContextImmediate;
3203 context.SetNoArgs ();
3204
Johnny Chen10530c22011-02-17 22:37:12 +00003205 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003206 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003207 }
3208 return true;
3209}
3210
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003211// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003212// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003213// can be written back to the base register.
3214bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003215EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003216{
3217#if 0
3218 // ARM pseudo code...
3219 if ConditionPassed()
3220 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3221 address = R[n];
3222
3223 for i = 0 to 14
3224 if registers<i> == '1' then
3225 R[i] = MemA[address, 4]; address = address + 4;
3226 if registers<15> == '1' then
3227 LoadWritePC (MemA[address, 4]);
3228
3229 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3230 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3231
3232#endif
3233
3234 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003235
Greg Clayton7bc39082011-03-24 23:53:38 +00003236 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003237 {
3238 uint32_t n;
3239 uint32_t registers = 0;
3240 bool wback;
3241 const uint32_t addr_byte_size = GetAddressByteSize();
3242 switch (encoding)
3243 {
3244 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003245 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003246 n = Bits32 (opcode, 10, 8);
3247 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003248 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003249 wback = BitIsClear (registers, n);
3250 // if BitCount(registers) < 1 then UNPREDICTABLE;
3251 if (BitCount(registers) < 1)
3252 return false;
3253 break;
3254 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003255 // if W == '1' && Rn == '1101' then SEE POP;
3256 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003257 n = Bits32 (opcode, 19, 16);
3258 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003259 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003260 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003261
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003262 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003263 if ((n == 15)
3264 || (BitCount (registers) < 2)
3265 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3266 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003267
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003268 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003269 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003270 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003271
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003272 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003273 if (wback
3274 && BitIsSet (registers, n))
3275 return false;
3276 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003277
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003278 case eEncodingA1:
3279 n = Bits32 (opcode, 19, 16);
3280 registers = Bits32 (opcode, 15, 0);
3281 wback = BitIsSet (opcode, 21);
3282 if ((n == 15)
3283 || (BitCount (registers) < 1))
3284 return false;
3285 break;
3286 default:
3287 return false;
3288 }
3289
3290 int32_t offset = 0;
3291 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3292 if (!success)
3293 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003294
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003295 EmulateInstruction::Context context;
3296 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3297 Register dwarf_reg;
3298 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3299 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003300
3301 for (int i = 0; i < 14; ++i)
3302 {
3303 if (BitIsSet (registers, i))
3304 {
Caroline Tice85aab332011-02-08 23:56:10 +00003305 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003306 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003307 if (wback && (n == 13)) // Pop Instruction
3308 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3309
3310 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003311 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003312 if (!success)
3313 return false;
3314
3315 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3316 return false;
3317
3318 offset += addr_byte_size;
3319 }
3320 }
3321
3322 if (BitIsSet (registers, 15))
3323 {
3324 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003325 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003326 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003327 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003328 if (!success)
3329 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003330 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003331 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003332 return false;
3333 }
3334
3335 if (wback && BitIsClear (registers, n))
3336 {
Caroline Ticefa172202011-02-11 22:49:54 +00003337 // R[n] = R[n] + 4 * BitCount (registers)
3338 int32_t offset = addr_byte_size * BitCount (registers);
3339 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003340 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003341
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003342 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3343 return false;
3344 }
3345 if (wback && BitIsSet (registers, n))
3346 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003347 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003348 }
3349 return true;
3350}
Caroline Tice713c2662011-02-11 17:59:55 +00003351
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003352// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3353// The consecutive memory locations end at this address and the address just below the lowest of those locations
3354// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003355bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003356EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003357{
3358#if 0
3359 // ARM pseudo code...
3360 if ConditionPassed() then
3361 EncodingSpecificOperations();
3362 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003363
Caroline Tice713c2662011-02-11 17:59:55 +00003364 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003365 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003366 R[i] = MemA[address,4]; address = address + 4;
3367
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003368 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003369 LoadWritePC(MemA[address,4]);
3370
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003371 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3372 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003373#endif
3374
3375 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003376
Greg Clayton7bc39082011-03-24 23:53:38 +00003377 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003378 {
3379 uint32_t n;
3380 uint32_t registers = 0;
3381 bool wback;
3382 const uint32_t addr_byte_size = GetAddressByteSize();
3383
3384 // EncodingSpecificOperations();
3385 switch (encoding)
3386 {
3387 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003388 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003389 n = Bits32 (opcode, 19, 16);
3390 registers = Bits32 (opcode, 15, 0);
3391 wback = BitIsSet (opcode, 21);
3392
3393 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3394 if ((n == 15) || (BitCount (registers) < 1))
3395 return false;
3396
3397 break;
3398
3399 default:
3400 return false;
3401 }
3402 // address = R[n] - 4*BitCount(registers) + 4;
3403
3404 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003405 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003406
3407 if (!success)
3408 return false;
3409
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003410 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003411
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003412 EmulateInstruction::Context context;
3413 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3414 Register dwarf_reg;
3415 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3416 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003417
3418 // for i = 0 to 14
3419 for (int i = 0; i < 14; ++i)
3420 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003421 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003422 if (BitIsSet (registers, i))
3423 {
3424 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003425 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003426 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003427 if (!success)
3428 return false;
3429 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3430 return false;
3431 offset += addr_byte_size;
3432 }
3433 }
3434
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003435 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003436 // LoadWritePC(MemA[address,4]);
3437 if (BitIsSet (registers, 15))
3438 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003439 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003440 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003441 if (!success)
3442 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003443 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003444 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003445 return false;
3446 }
3447
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003448 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003449 if (wback && BitIsClear (registers, n))
3450 {
Caroline Tice713c2662011-02-11 17:59:55 +00003451 if (!success)
3452 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003453
3454 offset = (addr_byte_size * BitCount (registers)) * -1;
3455 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003456 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003457 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003458 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3459 return false;
3460 }
3461
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003462 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003463 if (wback && BitIsSet (registers, n))
3464 return WriteBits32Unknown (n);
3465 }
3466 return true;
3467}
3468
3469// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3470// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3471// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003472bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003473EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003474{
3475#if 0
3476 // ARM pseudo code...
3477 if ConditionPassed() then
3478 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3479 address = R[n] - 4*BitCount(registers);
3480
3481 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003482 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003483 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003484 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003485 LoadWritePC(MemA[address,4]);
3486
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003487 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3488 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003489#endif
3490
3491 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003492
Greg Clayton7bc39082011-03-24 23:53:38 +00003493 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003494 {
3495 uint32_t n;
3496 uint32_t registers = 0;
3497 bool wback;
3498 const uint32_t addr_byte_size = GetAddressByteSize();
3499 switch (encoding)
3500 {
3501 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003502 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003503 n = Bits32 (opcode, 19, 16);
3504 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003505 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003506 wback = BitIsSet (opcode, 21);
3507
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003508 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003509 if ((n == 15)
3510 || (BitCount (registers) < 2)
3511 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3512 return false;
3513
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003514 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003515 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003516 return false;
3517
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003518 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003519 if (wback && BitIsSet (registers, n))
3520 return false;
3521
3522 break;
3523
3524 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003525 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003526 n = Bits32 (opcode, 19, 16);
3527 registers = Bits32 (opcode, 15, 0);
3528 wback = BitIsSet (opcode, 21);
3529
3530 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3531 if ((n == 15) || (BitCount (registers) < 1))
3532 return false;
3533
3534 break;
3535
3536 default:
3537 return false;
3538 }
3539
Caroline Tice713c2662011-02-11 17:59:55 +00003540 // address = R[n] - 4*BitCount(registers);
3541
Caroline Tice0b29e242011-02-08 23:16:02 +00003542 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003543 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003544
3545 if (!success)
3546 return false;
3547
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003548 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003549 EmulateInstruction::Context context;
3550 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3551 Register dwarf_reg;
3552 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003553 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003554
3555 for (int i = 0; i < 14; ++i)
3556 {
3557 if (BitIsSet (registers, i))
3558 {
3559 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003560 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003561 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003562 if (!success)
3563 return false;
3564
3565 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3566 return false;
3567
3568 offset += addr_byte_size;
3569 }
3570 }
3571
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003572 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003573 // LoadWritePC(MemA[address,4]);
3574 if (BitIsSet (registers, 15))
3575 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003576 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003577 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003578 if (!success)
3579 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003580 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003581 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003582 return false;
3583 }
3584
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003585 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003586 if (wback && BitIsClear (registers, n))
3587 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003588 if (!success)
3589 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003590
3591 offset = (addr_byte_size * BitCount (registers)) * -1;
3592 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003593 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003594 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003595 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3596 return false;
3597 }
3598
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003599 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003600 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003601 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003602 }
3603 return true;
3604}
Caroline Tice85aab332011-02-08 23:56:10 +00003605
Caroline Tice713c2662011-02-11 17:59:55 +00003606// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3607// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3608// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003609bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003610EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003611{
3612#if 0
3613 if ConditionPassed() then
3614 EncodingSpecificOperations();
3615 address = R[n] + 4;
3616
3617 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003618 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003619 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003620 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003621 LoadWritePC(MemA[address,4]);
3622
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003623 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3624 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003625#endif
3626
3627 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003628
Greg Clayton7bc39082011-03-24 23:53:38 +00003629 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003630 {
3631 uint32_t n;
3632 uint32_t registers = 0;
3633 bool wback;
3634 const uint32_t addr_byte_size = GetAddressByteSize();
3635 switch (encoding)
3636 {
3637 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003638 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003639 n = Bits32 (opcode, 19, 16);
3640 registers = Bits32 (opcode, 15, 0);
3641 wback = BitIsSet (opcode, 21);
3642
3643 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3644 if ((n == 15) || (BitCount (registers) < 1))
3645 return false;
3646
3647 break;
3648 default:
3649 return false;
3650 }
3651 // address = R[n] + 4;
3652
3653 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003654 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003655
3656 if (!success)
3657 return false;
3658
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003659 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003660
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003661 EmulateInstruction::Context context;
3662 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3663 Register dwarf_reg;
3664 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3665 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003666
3667 for (int i = 0; i < 14; ++i)
3668 {
3669 if (BitIsSet (registers, i))
3670 {
3671 // R[i] = MemA[address,4]; address = address + 4;
3672
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003673 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003674 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003675 if (!success)
3676 return false;
3677
3678 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3679 return false;
3680
3681 offset += addr_byte_size;
3682 }
3683 }
3684
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003685 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003686 // LoadWritePC(MemA[address,4]);
3687 if (BitIsSet (registers, 15))
3688 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003689 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003690 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003691 if (!success)
3692 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003693 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003694 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003695 return false;
3696 }
3697
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003698 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003699 if (wback && BitIsClear (registers, n))
3700 {
Caroline Tice85aab332011-02-08 23:56:10 +00003701 if (!success)
3702 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003703
3704 offset = addr_byte_size * BitCount (registers);
3705 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003706 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003707 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003708 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3709 return false;
3710 }
3711
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003712 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003713 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003714 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003715 }
3716 return true;
3717}
Caroline Tice0b29e242011-02-08 23:16:02 +00003718
Johnny Chenef21b592011-02-10 01:52:38 +00003719// Load Register (immediate) calculates an address from a base register value and
3720// an immediate offset, loads a word from memory, and writes to a register.
3721// LDR (immediate, Thumb)
3722bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003723EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003724{
3725#if 0
3726 // ARM pseudo code...
3727 if (ConditionPassed())
3728 {
3729 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3730 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3731 address = if index then offset_addr else R[n];
3732 data = MemU[address,4];
3733 if wback then R[n] = offset_addr;
3734 if t == 15 then
3735 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3736 elsif UnalignedSupport() || address<1:0> = '00' then
3737 R[t] = data;
3738 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3739 }
3740#endif
3741
3742 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003743
Greg Clayton7bc39082011-03-24 23:53:38 +00003744 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003745 {
3746 uint32_t Rt; // the destination register
3747 uint32_t Rn; // the base register
3748 uint32_t imm32; // the immediate offset used to form the address
3749 addr_t offset_addr; // the offset address
3750 addr_t address; // the calculated address
3751 uint32_t data; // the literal data value from memory load
3752 bool add, index, wback;
3753 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003754 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003755 Rt = Bits32(opcode, 2, 0);
3756 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003757 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3758 // index = TRUE; add = TRUE; wback = FALSE
3759 add = true;
3760 index = true;
3761 wback = false;
3762
3763 break;
3764
3765 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003766 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003767 Rt = Bits32 (opcode, 10, 8);
3768 Rn = 13;
3769 imm32 = Bits32 (opcode, 7, 0) << 2;
3770
3771 // index = TRUE; add = TRUE; wback = FALSE;
3772 index = true;
3773 add = true;
3774 wback = false;
3775
3776 break;
3777
3778 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003779 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003780 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3781 Rt = Bits32 (opcode, 15, 12);
3782 Rn = Bits32 (opcode, 19, 16);
3783 imm32 = Bits32 (opcode, 11, 0);
3784
3785 // index = TRUE; add = TRUE; wback = FALSE;
3786 index = true;
3787 add = true;
3788 wback = false;
3789
3790 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3791 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3792 return false;
3793
3794 break;
3795
3796 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003797 // if Rn == '1111' then SEE LDR (literal);
3798 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3799 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3800 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003801 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3802 return false;
3803
3804 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3805 Rt = Bits32 (opcode, 15, 12);
3806 Rn = Bits32 (opcode, 19, 16);
3807 imm32 = Bits32 (opcode, 7, 0);
3808
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003809 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003810 index = BitIsSet (opcode, 10);
3811 add = BitIsSet (opcode, 9);
3812 wback = BitIsSet (opcode, 8);
3813
3814 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3815 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3816 return false;
3817
3818 break;
3819
3820 default:
3821 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003822 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003823 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003824 if (!success)
3825 return false;
3826 if (add)
3827 offset_addr = base + imm32;
3828 else
3829 offset_addr = base - imm32;
3830
3831 address = (index ? offset_addr : base);
3832
Caroline Ticebaf1f642011-03-24 19:23:45 +00003833 Register base_reg;
3834 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003835 if (wback)
3836 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003837 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003838 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3839 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003840
Johnny Chenef21b592011-02-10 01:52:38 +00003841 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3842 return false;
3843 }
3844
3845 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003846 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003847 context.type = EmulateInstruction::eContextRegisterLoad;
3848 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003849
3850 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003851 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003852 if (!success)
3853 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003854
3855 if (Rt == 15)
3856 {
3857 if (Bits32(address, 1, 0) == 0)
3858 {
Johnny Chen668b4512011-02-15 21:08:58 +00003859 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003860 return false;
3861 }
3862 else
3863 return false;
3864 }
3865 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3866 {
3867 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3868 return false;
3869 }
3870 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003871 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003872 }
3873 return true;
3874}
3875
Caroline Ticeaf556562011-02-15 18:42:15 +00003876// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3877// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3878// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003879bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003880EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003881{
3882#if 0
3883 if ConditionPassed() then
3884 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3885 address = R[n];
3886
3887 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003888 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003889 if i == n && wback && i != LowestSetBit(registers) then
3890 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3891 else
3892 MemA[address,4] = R[i];
3893 address = address + 4;
3894
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003895 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003896 MemA[address,4] = PCStoreValue();
3897 if wback then R[n] = R[n] + 4*BitCount(registers);
3898#endif
3899
3900 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003901
Greg Clayton7bc39082011-03-24 23:53:38 +00003902 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003903 {
3904 uint32_t n;
3905 uint32_t registers = 0;
3906 bool wback;
3907 const uint32_t addr_byte_size = GetAddressByteSize();
3908
3909 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3910 switch (encoding)
3911 {
3912 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003913 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003914 n = Bits32 (opcode, 10, 8);
3915 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003916 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003917 wback = true;
3918
3919 // if BitCount(registers) < 1 then UNPREDICTABLE;
3920 if (BitCount (registers) < 1)
3921 return false;
3922
3923 break;
3924
3925 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003926 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003927 n = Bits32 (opcode, 19, 16);
3928 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003929 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003930 wback = BitIsSet (opcode, 21);
3931
3932 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3933 if ((n == 15) || (BitCount (registers) < 2))
3934 return false;
3935
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003936 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003937 if (wback && BitIsSet (registers, n))
3938 return false;
3939
3940 break;
3941
3942 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003943 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003944 n = Bits32 (opcode, 19, 16);
3945 registers = Bits32 (opcode, 15, 0);
3946 wback = BitIsSet (opcode, 21);
3947
3948 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3949 if ((n == 15) || (BitCount (registers) < 1))
3950 return false;
3951
3952 break;
3953
3954 default:
3955 return false;
3956 }
3957
3958 // address = R[n];
3959 int32_t offset = 0;
3960 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3961 if (!success)
3962 return false;
3963
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003964 EmulateInstruction::Context context;
3965 context.type = EmulateInstruction::eContextRegisterStore;
3966 Register base_reg;
3967 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003968
3969 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003970 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003971 for (int i = 0; i < 14; ++i)
3972 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003973 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003974 if (BitIsSet (registers, i))
3975 {
3976 if (i < lowest_set_bit)
3977 lowest_set_bit = i;
3978 // if i == n && wback && i != LowestSetBit(registers) then
3979 if ((i == n) && wback && (i != lowest_set_bit))
3980 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3981 WriteBits32UnknownToMemory (address + offset);
3982 else
3983 {
3984 // MemA[address,4] = R[i];
3985 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3986 if (!success)
3987 return false;
3988
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003989 Register data_reg;
3990 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3991 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003992 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003993 return false;
3994 }
3995
3996 // address = address + 4;
3997 offset += addr_byte_size;
3998 }
3999 }
4000
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004001 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004002 // MemA[address,4] = PCStoreValue();
4003 if (BitIsSet (registers, 15))
4004 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004005 Register pc_reg;
4006 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4007 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004008 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004009 if (!success)
4010 return false;
4011
Caroline Tice8d681f52011-03-17 23:50:16 +00004012 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004013 return false;
4014 }
4015
4016 // if wback then R[n] = R[n] + 4*BitCount(registers);
4017 if (wback)
4018 {
4019 offset = addr_byte_size * BitCount (registers);
4020 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004021 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004022 addr_t data = address + offset;
4023 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4024 return false;
4025 }
4026 }
4027 return true;
4028}
4029
Caroline Ticeaf556562011-02-15 18:42:15 +00004030// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4031// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4032// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004033bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004034EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004035{
4036#if 0
4037 if ConditionPassed() then
4038 EncodingSpecificOperations();
4039 address = R[n] - 4*BitCount(registers) + 4;
4040
4041 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004042 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004043 if i == n && wback && i != LowestSetBit(registers) then
4044 MemA[address,4] = bits(32) UNKNOWN;
4045 else
4046 MemA[address,4] = R[i];
4047 address = address + 4;
4048
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004049 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004050 MemA[address,4] = PCStoreValue();
4051
4052 if wback then R[n] = R[n] - 4*BitCount(registers);
4053#endif
4054
4055 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004056
Greg Clayton7bc39082011-03-24 23:53:38 +00004057 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004058 {
4059 uint32_t n;
4060 uint32_t registers = 0;
4061 bool wback;
4062 const uint32_t addr_byte_size = GetAddressByteSize();
4063
4064 // EncodingSpecificOperations();
4065 switch (encoding)
4066 {
4067 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004068 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004069 n = Bits32 (opcode, 19, 16);
4070 registers = Bits32 (opcode, 15, 0);
4071 wback = BitIsSet (opcode, 21);
4072
4073 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4074 if ((n == 15) || (BitCount (registers) < 1))
4075 return false;
4076 break;
4077 default:
4078 return false;
4079 }
4080
4081 // address = R[n] - 4*BitCount(registers) + 4;
4082 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004083 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004084 if (!success)
4085 return false;
4086
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004087 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004088
4089 EmulateInstruction::Context context;
4090 context.type = EmulateInstruction::eContextRegisterStore;
4091 Register base_reg;
4092 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4093
4094 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004095 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004096 for (int i = 0; i < 14; ++i)
4097 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004098 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004099 if (BitIsSet (registers, i))
4100 {
4101 if (i < lowest_bit_set)
4102 lowest_bit_set = i;
4103 //if i == n && wback && i != LowestSetBit(registers) then
4104 if ((i == n) && wback && (i != lowest_bit_set))
4105 // MemA[address,4] = bits(32) UNKNOWN;
4106 WriteBits32UnknownToMemory (address + offset);
4107 else
4108 {
4109 // MemA[address,4] = R[i];
4110 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4111 if (!success)
4112 return false;
4113
4114 Register data_reg;
4115 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004116 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004117 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004118 return false;
4119 }
4120
4121 // address = address + 4;
4122 offset += addr_byte_size;
4123 }
4124 }
4125
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004126 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004127 // MemA[address,4] = PCStoreValue();
4128 if (BitIsSet (registers, 15))
4129 {
4130 Register pc_reg;
4131 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4132 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004133 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004134 if (!success)
4135 return false;
4136
Caroline Tice8d681f52011-03-17 23:50:16 +00004137 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004138 return false;
4139 }
4140
4141 // if wback then R[n] = R[n] - 4*BitCount(registers);
4142 if (wback)
4143 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004144 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004145 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4146 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004147 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004148 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4149 return false;
4150 }
4151 }
4152 return true;
4153}
4154
Caroline Ticeaf556562011-02-15 18:42:15 +00004155// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4156// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4157// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004158bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004159EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004160{
4161#if 0
4162 if ConditionPassed() then
4163 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4164 address = R[n] - 4*BitCount(registers);
4165
4166 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004167 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004168 if i == n && wback && i != LowestSetBit(registers) then
4169 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4170 else
4171 MemA[address,4] = R[i];
4172 address = address + 4;
4173
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004174 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004175 MemA[address,4] = PCStoreValue();
4176
4177 if wback then R[n] = R[n] - 4*BitCount(registers);
4178#endif
4179
4180
4181 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004182
Greg Clayton7bc39082011-03-24 23:53:38 +00004183 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004184 {
4185 uint32_t n;
4186 uint32_t registers = 0;
4187 bool wback;
4188 const uint32_t addr_byte_size = GetAddressByteSize();
4189
4190 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4191 switch (encoding)
4192 {
4193 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004194 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004195 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4196 {
4197 // See PUSH
4198 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004199 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004200 n = Bits32 (opcode, 19, 16);
4201 registers = Bits32 (opcode, 15, 0);
4202 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4203 wback = BitIsSet (opcode, 21);
4204 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4205 if ((n == 15) || BitCount (registers) < 2)
4206 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004207 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004208 if (wback && BitIsSet (registers, n))
4209 return false;
4210 break;
4211
4212 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004213 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004214 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4215 {
4216 // See Push
4217 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004218 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004219 n = Bits32 (opcode, 19, 16);
4220 registers = Bits32 (opcode, 15, 0);
4221 wback = BitIsSet (opcode, 21);
4222 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4223 if ((n == 15) || BitCount (registers) < 1)
4224 return false;
4225 break;
4226
4227 default:
4228 return false;
4229 }
4230
4231 // address = R[n] - 4*BitCount(registers);
4232
4233 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004234 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004235 if (!success)
4236 return false;
4237
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004238 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004239
4240 EmulateInstruction::Context context;
4241 context.type = EmulateInstruction::eContextRegisterStore;
4242 Register base_reg;
4243 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4244
4245 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004246 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004247 for (int i = 0; i < 14; ++i)
4248 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004249 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004250 if (BitIsSet (registers, i))
4251 {
4252 if (i < lowest_set_bit)
4253 lowest_set_bit = i;
4254 // if i == n && wback && i != LowestSetBit(registers) then
4255 if ((i == n) && wback && (i != lowest_set_bit))
4256 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4257 WriteBits32UnknownToMemory (address + offset);
4258 else
4259 {
4260 // MemA[address,4] = R[i];
4261 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4262 if (!success)
4263 return false;
4264
4265 Register data_reg;
4266 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004267 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004268 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004269 return false;
4270 }
4271
4272 // address = address + 4;
4273 offset += addr_byte_size;
4274 }
4275 }
4276
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004277 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004278 // MemA[address,4] = PCStoreValue();
4279 if (BitIsSet (registers, 15))
4280 {
4281 Register pc_reg;
4282 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4283 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004284 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004285 if (!success)
4286 return false;
4287
Caroline Tice8d681f52011-03-17 23:50:16 +00004288 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004289 return false;
4290 }
4291
4292 // if wback then R[n] = R[n] - 4*BitCount(registers);
4293 if (wback)
4294 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004295 offset = (addr_byte_size * BitCount (registers)) * -1;
4296 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4297 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004298 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004299 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4300 return false;
4301 }
4302 }
4303 return true;
4304}
4305
4306// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4307// from a base register. The consecutive memory locations start just above this address, and the address of the last
4308// of those locations can optionally be written back to the base register.
4309bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004310EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004311{
4312#if 0
4313 if ConditionPassed() then
4314 EncodingSpecificOperations();
4315 address = R[n] + 4;
4316
4317 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004318 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004319 if i == n && wback && i != LowestSetBit(registers) then
4320 MemA[address,4] = bits(32) UNKNOWN;
4321 else
4322 MemA[address,4] = R[i];
4323 address = address + 4;
4324
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004325 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004326 MemA[address,4] = PCStoreValue();
4327
4328 if wback then R[n] = R[n] + 4*BitCount(registers);
4329#endif
4330
4331 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004332
Greg Clayton7bc39082011-03-24 23:53:38 +00004333 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004334 {
4335 uint32_t n;
4336 uint32_t registers = 0;
4337 bool wback;
4338 const uint32_t addr_byte_size = GetAddressByteSize();
4339
4340 // EncodingSpecificOperations();
4341 switch (encoding)
4342 {
4343 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004344 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004345 n = Bits32 (opcode, 19, 16);
4346 registers = Bits32 (opcode, 15, 0);
4347 wback = BitIsSet (opcode, 21);
4348
4349 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4350 if ((n == 15) && (BitCount (registers) < 1))
4351 return false;
4352 break;
4353 default:
4354 return false;
4355 }
4356 // address = R[n] + 4;
4357
4358 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004359 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004360 if (!success)
4361 return false;
4362
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004363 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004364
4365 EmulateInstruction::Context context;
4366 context.type = EmulateInstruction::eContextRegisterStore;
4367 Register base_reg;
4368 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4369
4370 uint32_t lowest_set_bit = 14;
4371 // for i = 0 to 14
4372 for (int i = 0; i < 14; ++i)
4373 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004374 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004375 if (BitIsSet (registers, i))
4376 {
4377 if (i < lowest_set_bit)
4378 lowest_set_bit = i;
4379 // if i == n && wback && i != LowestSetBit(registers) then
4380 if ((i == n) && wback && (i != lowest_set_bit))
4381 // MemA[address,4] = bits(32) UNKNOWN;
4382 WriteBits32UnknownToMemory (address + offset);
4383 // else
4384 else
4385 {
4386 // MemA[address,4] = R[i];
4387 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4388 if (!success)
4389 return false;
4390
4391 Register data_reg;
4392 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004393 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004394 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004395 return false;
4396 }
4397
4398 // address = address + 4;
4399 offset += addr_byte_size;
4400 }
4401 }
4402
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004403 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004404 // MemA[address,4] = PCStoreValue();
4405 if (BitIsSet (registers, 15))
4406 {
4407 Register pc_reg;
4408 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4409 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004410 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004411 if (!success)
4412 return false;
4413
Caroline Tice8d681f52011-03-17 23:50:16 +00004414 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004415 return false;
4416 }
4417
4418 // if wback then R[n] = R[n] + 4*BitCount(registers);
4419 if (wback)
4420 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004421 offset = addr_byte_size * BitCount (registers);
4422 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4423 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004424 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004425 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4426 return false;
4427 }
4428 }
4429 return true;
4430}
Caroline Tice7fac8572011-02-15 22:53:54 +00004431
4432// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4433// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4434bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004435EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004436{
4437#if 0
4438 if ConditionPassed() then
4439 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4440 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4441 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004442 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004443 MemU[address,4] = R[t];
4444 else // Can only occur before ARMv7
4445 MemU[address,4] = bits(32) UNKNOWN;
4446 if wback then R[n] = offset_addr;
4447#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004448
Caroline Tice7fac8572011-02-15 22:53:54 +00004449 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004450
Greg Clayton7bc39082011-03-24 23:53:38 +00004451 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004452 {
4453 const uint32_t addr_byte_size = GetAddressByteSize();
4454
4455 uint32_t t;
4456 uint32_t n;
4457 uint32_t imm32;
4458 bool index;
4459 bool add;
4460 bool wback;
4461 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4462 switch (encoding)
4463 {
4464 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004465 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004466 t = Bits32 (opcode, 2, 0);
4467 n = Bits32 (opcode, 5, 3);
4468 imm32 = Bits32 (opcode, 10, 6) << 2;
4469
4470 // index = TRUE; add = TRUE; wback = FALSE;
4471 index = true;
4472 add = false;
4473 wback = false;
4474 break;
4475
4476 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004477 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004478 t = Bits32 (opcode, 10, 8);
4479 n = 13;
4480 imm32 = Bits32 (opcode, 7, 0) << 2;
4481
4482 // index = TRUE; add = TRUE; wback = FALSE;
4483 index = true;
4484 add = true;
4485 wback = false;
4486 break;
4487
4488 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004489 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004490 if (Bits32 (opcode, 19, 16) == 15)
4491 return false;
4492
4493 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4494 t = Bits32 (opcode, 15, 12);
4495 n = Bits32 (opcode, 19, 16);
4496 imm32 = Bits32 (opcode, 11, 0);
4497
4498 // index = TRUE; add = TRUE; wback = FALSE;
4499 index = true;
4500 add = true;
4501 wback = false;
4502
4503 // if t == 15 then UNPREDICTABLE;
4504 if (t == 15)
4505 return false;
4506 break;
4507
4508 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004509 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4510 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4511 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004512 if ((Bits32 (opcode, 19, 16) == 15)
4513 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4514 return false;
4515
4516 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4517 t = Bits32 (opcode, 15, 12);
4518 n = Bits32 (opcode, 19, 16);
4519 imm32 = Bits32 (opcode, 7, 0);
4520
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004521 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004522 index = BitIsSet (opcode, 10);
4523 add = BitIsSet (opcode, 9);
4524 wback = BitIsSet (opcode, 8);
4525
4526 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4527 if ((t == 15) || (wback && (n == t)))
4528 return false;
4529 break;
4530
4531 default:
4532 return false;
4533 }
4534
4535 addr_t offset_addr;
4536 addr_t address;
4537
4538 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004539 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004540 if (!success)
4541 return false;
4542
4543 if (add)
4544 offset_addr = base_address + imm32;
4545 else
4546 offset_addr = base_address - imm32;
4547
4548 // address = if index then offset_addr else R[n];
4549 if (index)
4550 address = offset_addr;
4551 else
4552 address = base_address;
4553
4554 EmulateInstruction::Context context;
4555 context.type = eContextRegisterStore;
4556 Register base_reg;
4557 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4558
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004559 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004560 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4561 {
4562 // MemU[address,4] = R[t];
4563 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4564 if (!success)
4565 return false;
4566
4567 Register data_reg;
4568 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4569 int32_t offset = address - base_address;
4570 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004571 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004572 return false;
4573 }
4574 else
4575 {
4576 // MemU[address,4] = bits(32) UNKNOWN;
4577 WriteBits32UnknownToMemory (address);
4578 }
4579
4580 // if wback then R[n] = offset_addr;
4581 if (wback)
4582 {
4583 context.type = eContextRegisterLoad;
4584 context.SetAddress (offset_addr);
4585 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4586 return false;
4587 }
4588 }
4589 return true;
4590}
Caroline Ticeaf556562011-02-15 18:42:15 +00004591
Caroline Tice3fd63e92011-02-16 00:33:43 +00004592// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4593// word from a register to memory. The offset register value can optionally be shifted.
4594bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004595EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004596{
4597#if 0
4598 if ConditionPassed() then
4599 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4600 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4601 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4602 address = if index then offset_addr else R[n];
4603 if t == 15 then // Only possible for encoding A1
4604 data = PCStoreValue();
4605 else
4606 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004607 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004608 MemU[address,4] = data;
4609 else // Can only occur before ARMv7
4610 MemU[address,4] = bits(32) UNKNOWN;
4611 if wback then R[n] = offset_addr;
4612#endif
4613
4614 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004615
Greg Clayton7bc39082011-03-24 23:53:38 +00004616 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004617 {
4618 const uint32_t addr_byte_size = GetAddressByteSize();
4619
4620 uint32_t t;
4621 uint32_t n;
4622 uint32_t m;
4623 ARM_ShifterType shift_t;
4624 uint32_t shift_n;
4625 bool index;
4626 bool add;
4627 bool wback;
4628
4629 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4630 switch (encoding)
4631 {
4632 case eEncodingT1:
4633 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4634 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4635 t = Bits32 (opcode, 2, 0);
4636 n = Bits32 (opcode, 5, 3);
4637 m = Bits32 (opcode, 8, 6);
4638
4639 // index = TRUE; add = TRUE; wback = FALSE;
4640 index = true;
4641 add = true;
4642 wback = false;
4643
4644 // (shift_t, shift_n) = (SRType_LSL, 0);
4645 shift_t = SRType_LSL;
4646 shift_n = 0;
4647 break;
4648
4649 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004650 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004651 if (Bits32 (opcode, 19, 16) == 15)
4652 return false;
4653
4654 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4655 t = Bits32 (opcode, 15, 12);
4656 n = Bits32 (opcode, 19, 16);
4657 m = Bits32 (opcode, 3, 0);
4658
4659 // index = TRUE; add = TRUE; wback = FALSE;
4660 index = true;
4661 add = true;
4662 wback = false;
4663
4664 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4665 shift_t = SRType_LSL;
4666 shift_n = Bits32 (opcode, 5, 4);
4667
4668 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4669 if ((t == 15) || (BadReg (m)))
4670 return false;
4671 break;
4672
4673 case eEncodingA1:
4674 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004675 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004676 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4677 t = Bits32 (opcode, 15, 12);
4678 n = Bits32 (opcode, 19, 16);
4679 m = Bits32 (opcode, 3, 0);
4680
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004681 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004682 index = BitIsSet (opcode, 24);
4683 add = BitIsSet (opcode, 23);
4684 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4685
4686 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4687 uint32_t typ = Bits32 (opcode, 6, 5);
4688 uint32_t imm5 = Bits32 (opcode, 11, 7);
4689 shift_n = DecodeImmShift(typ, imm5, shift_t);
4690
4691 // if m == 15 then UNPREDICTABLE;
4692 if (m == 15)
4693 return false;
4694
4695 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4696 if (wback && ((n == 15) || (n == t)))
4697 return false;
4698
4699 break;
4700 }
4701 default:
4702 return false;
4703 }
4704
4705 addr_t offset_addr;
4706 addr_t address;
4707 int32_t offset = 0;
4708
4709 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4710 if (!success)
4711 return false;
4712
4713 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4714 if (!success)
4715 return false;
4716
4717 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004718 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004719
4720 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4721 if (add)
4722 offset_addr = base_address + offset;
4723 else
4724 offset_addr = base_address - offset;
4725
4726 // address = if index then offset_addr else R[n];
4727 if (index)
4728 address = offset_addr;
4729 else
4730 address = base_address;
4731
4732 uint32_t data;
4733 // if t == 15 then // Only possible for encoding A1
4734 if (t == 15)
4735 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004736 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004737 else
4738 // data = R[t];
4739 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4740
4741 if (!success)
4742 return false;
4743
4744 EmulateInstruction::Context context;
4745 context.type = eContextRegisterStore;
4746
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004747 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004748 if (UnalignedSupport ()
4749 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4750 || CurrentInstrSet() == eModeARM)
4751 {
4752 // MemU[address,4] = data;
4753
4754 Register base_reg;
4755 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4756
4757 Register data_reg;
4758 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4759
4760 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004761 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004762 return false;
4763
4764 }
4765 else
4766 // MemU[address,4] = bits(32) UNKNOWN;
4767 WriteBits32UnknownToMemory (address);
4768
4769 // if wback then R[n] = offset_addr;
4770 if (wback)
4771 {
4772 context.type = eContextRegisterLoad;
4773 context.SetAddress (offset_addr);
4774 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4775 return false;
4776 }
4777
4778 }
4779 return true;
4780}
Caroline Tice73a29de2011-02-16 20:22:22 +00004781
4782bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004783EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004784{
4785#if 0
4786 if ConditionPassed() then
4787 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4788 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4789 address = if index then offset_addr else R[n];
4790 MemU[address,1] = R[t]<7:0>;
4791 if wback then R[n] = offset_addr;
4792#endif
4793
4794
4795 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004796
Greg Clayton7bc39082011-03-24 23:53:38 +00004797 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004798 {
4799 uint32_t t;
4800 uint32_t n;
4801 uint32_t imm32;
4802 bool index;
4803 bool add;
4804 bool wback;
4805 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4806 switch (encoding)
4807 {
4808 case eEncodingT1:
4809 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4810 t = Bits32 (opcode, 2, 0);
4811 n = Bits32 (opcode, 5, 3);
4812 imm32 = Bits32 (opcode, 10, 6);
4813
4814 // index = TRUE; add = TRUE; wback = FALSE;
4815 index = true;
4816 add = true;
4817 wback = false;
4818 break;
4819
4820 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004821 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004822 if (Bits32 (opcode, 19, 16) == 15)
4823 return false;
4824
4825 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4826 t = Bits32 (opcode, 15, 12);
4827 n = Bits32 (opcode, 19, 16);
4828 imm32 = Bits32 (opcode, 11, 0);
4829
4830 // index = TRUE; add = TRUE; wback = FALSE;
4831 index = true;
4832 add = true;
4833 wback = false;
4834
4835 // if BadReg(t) then UNPREDICTABLE;
4836 if (BadReg (t))
4837 return false;
4838 break;
4839
4840 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004841 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4842 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004843 if (Bits32 (opcode, 19, 16) == 15)
4844 return false;
4845
4846 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4847 t = Bits32 (opcode, 15, 12);
4848 n = Bits32 (opcode, 19, 16);
4849 imm32 = Bits32 (opcode, 7, 0);
4850
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004851 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004852 index = BitIsSet (opcode, 10);
4853 add = BitIsSet (opcode, 9);
4854 wback = BitIsSet (opcode, 8);
4855
4856 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4857 if ((BadReg (t)) || (wback && (n == t)))
4858 return false;
4859 break;
4860
4861 default:
4862 return false;
4863 }
4864
4865 addr_t offset_addr;
4866 addr_t address;
4867 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4868 if (!success)
4869 return false;
4870
4871 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4872 if (add)
4873 offset_addr = base_address + imm32;
4874 else
4875 offset_addr = base_address - imm32;
4876
4877 // address = if index then offset_addr else R[n];
4878 if (index)
4879 address = offset_addr;
4880 else
4881 address = base_address;
4882
Caroline Ticecc96eb52011-02-17 19:20:40 +00004883 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004884 Register base_reg;
4885 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4886
4887 Register data_reg;
4888 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4889
4890 EmulateInstruction::Context context;
4891 context.type = eContextRegisterStore;
4892 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4893
4894 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4895 if (!success)
4896 return false;
4897
4898 data = Bits32 (data, 7, 0);
4899
Caroline Ticecc96eb52011-02-17 19:20:40 +00004900 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004901 return false;
4902
4903 // if wback then R[n] = offset_addr;
4904 if (wback)
4905 {
4906 context.type = eContextRegisterLoad;
4907 context.SetAddress (offset_addr);
4908 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4909 return false;
4910 }
4911
4912 }
4913
4914 return true;
4915}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004916
4917// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4918// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4919bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004920EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004921{
4922#if 0
4923 if ConditionPassed() then
4924 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4925 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4926 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4927 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004928 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004929 MemU[address,2] = R[t]<15:0>;
4930 else // Can only occur before ARMv7
4931 MemU[address,2] = bits(16) UNKNOWN;
4932 if wback then R[n] = offset_addr;
4933#endif
4934
4935 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004936
Greg Clayton7bc39082011-03-24 23:53:38 +00004937 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004938 {
4939 uint32_t t;
4940 uint32_t n;
4941 uint32_t m;
4942 bool index;
4943 bool add;
4944 bool wback;
4945 ARM_ShifterType shift_t;
4946 uint32_t shift_n;
4947
4948 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4949 switch (encoding)
4950 {
4951 case eEncodingT1:
4952 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4953 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4954 t = Bits32 (opcode, 2, 0);
4955 n = Bits32 (opcode, 5, 3);
4956 m = Bits32 (opcode, 8, 6);
4957
4958 // index = TRUE; add = TRUE; wback = FALSE;
4959 index = true;
4960 add = true;
4961 wback = false;
4962
4963 // (shift_t, shift_n) = (SRType_LSL, 0);
4964 shift_t = SRType_LSL;
4965 shift_n = 0;
4966
4967 break;
4968
4969 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004970 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004971 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4972 t = Bits32 (opcode, 15, 12);
4973 n = Bits32 (opcode, 19, 16);
4974 m = Bits32 (opcode, 3, 0);
4975 if (n == 15)
4976 return false;
4977
4978 // index = TRUE; add = TRUE; wback = FALSE;
4979 index = true;
4980 add = true;
4981 wback = false;
4982
4983 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4984 shift_t = SRType_LSL;
4985 shift_n = Bits32 (opcode, 5, 4);
4986
4987 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4988 if (BadReg (t) || BadReg (m))
4989 return false;
4990
4991 break;
4992
4993 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004994 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004995 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4996 t = Bits32 (opcode, 15, 12);
4997 n = Bits32 (opcode, 19, 16);
4998 m = Bits32 (opcode, 3, 0);
4999
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005000 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005001 index = BitIsSet (opcode, 24);
5002 add = BitIsSet (opcode, 23);
5003 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5004
5005 // (shift_t, shift_n) = (SRType_LSL, 0);
5006 shift_t = SRType_LSL;
5007 shift_n = 0;
5008
5009 // if t == 15 || m == 15 then UNPREDICTABLE;
5010 if ((t == 15) || (m == 15))
5011 return false;
5012
5013 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5014 if (wback && ((n == 15) || (n == t)))
5015 return false;
5016
5017 break;
5018
5019 default:
5020 return false;
5021 }
5022
5023 uint32_t Rm = ReadCoreReg (m, &success);
5024 if (!success)
5025 return false;
5026
5027 uint32_t Rn = ReadCoreReg (n, &success);
5028 if (!success)
5029 return false;
5030
5031 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5032 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5033
5034 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5035 addr_t offset_addr;
5036 if (add)
5037 offset_addr = Rn + offset;
5038 else
5039 offset_addr = Rn - offset;
5040
5041 // address = if index then offset_addr else R[n];
5042 addr_t address;
5043 if (index)
5044 address = offset_addr;
5045 else
5046 address = Rn;
5047
5048 EmulateInstruction::Context context;
5049 context.type = eContextRegisterStore;
5050 Register base_reg;
5051 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5052 Register offset_reg;
5053 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5054
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005055 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005056 if (UnalignedSupport() || BitIsClear (address, 0))
5057 {
5058 // MemU[address,2] = R[t]<15:0>;
5059 uint32_t Rt = ReadCoreReg (t, &success);
5060 if (!success)
5061 return false;
5062
5063 EmulateInstruction::Context context;
5064 context.type = eContextRegisterStore;
5065 Register base_reg;
5066 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5067 Register offset_reg;
5068 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5069 Register data_reg;
5070 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5071 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5072
5073 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5074 return false;
5075 }
5076 else // Can only occur before ARMv7
5077 {
5078 // MemU[address,2] = bits(16) UNKNOWN;
5079 }
5080
5081 // if wback then R[n] = offset_addr;
5082 if (wback)
5083 {
5084 context.type = eContextAdjustBaseRegister;
5085 context.SetAddress (offset_addr);
5086 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5087 return false;
5088 }
5089 }
5090
5091 return true;
5092}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005093
Johnny Chen157b9592011-02-18 21:13:05 +00005094// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5095// and writes the result to the destination register. It can optionally update the condition flags
5096// based on the result.
5097bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005098EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005099{
5100#if 0
5101 // ARM pseudo code...
5102 if ConditionPassed() then
5103 EncodingSpecificOperations();
5104 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5105 if d == 15 then // Can only occur for ARM encoding
5106 ALUWritePC(result); // setflags is always FALSE here
5107 else
5108 R[d] = result;
5109 if setflags then
5110 APSR.N = result<31>;
5111 APSR.Z = IsZeroBit(result);
5112 APSR.C = carry;
5113 APSR.V = overflow;
5114#endif
5115
5116 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005117
Greg Clayton7bc39082011-03-24 23:53:38 +00005118 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005119 {
5120 uint32_t Rd, Rn;
5121 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5122 bool setflags;
5123 switch (encoding)
5124 {
5125 case eEncodingT1:
5126 Rd = Bits32(opcode, 11, 8);
5127 Rn = Bits32(opcode, 19, 16);
5128 setflags = BitIsSet(opcode, 20);
5129 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5130 if (BadReg(Rd) || BadReg(Rn))
5131 return false;
5132 break;
5133 case eEncodingA1:
5134 Rd = Bits32(opcode, 15, 12);
5135 Rn = Bits32(opcode, 19, 16);
5136 setflags = BitIsSet(opcode, 20);
5137 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005138
Johnny Chen157b9592011-02-18 21:13:05 +00005139 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005140 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005141 break;
5142 default:
5143 return false;
5144 }
5145
5146 // Read the first operand.
5147 int32_t val1 = ReadCoreReg(Rn, &success);
5148 if (!success)
5149 return false;
5150
5151 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5152
5153 EmulateInstruction::Context context;
5154 context.type = EmulateInstruction::eContextImmediate;
5155 context.SetNoArgs ();
5156
5157 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5158 return false;
5159 }
5160 return true;
5161}
5162
5163// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5164// register value, and writes the result to the destination register. It can optionally update the
5165// condition flags based on the result.
5166bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005167EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005168{
5169#if 0
5170 // ARM pseudo code...
5171 if ConditionPassed() then
5172 EncodingSpecificOperations();
5173 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5174 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5175 if d == 15 then // Can only occur for ARM encoding
5176 ALUWritePC(result); // setflags is always FALSE here
5177 else
5178 R[d] = result;
5179 if setflags then
5180 APSR.N = result<31>;
5181 APSR.Z = IsZeroBit(result);
5182 APSR.C = carry;
5183 APSR.V = overflow;
5184#endif
5185
5186 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005187
Greg Clayton7bc39082011-03-24 23:53:38 +00005188 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005189 {
5190 uint32_t Rd, Rn, Rm;
5191 ARM_ShifterType shift_t;
5192 uint32_t shift_n; // the shift applied to the value read from Rm
5193 bool setflags;
5194 switch (encoding)
5195 {
5196 case eEncodingT1:
5197 Rd = Rn = Bits32(opcode, 2, 0);
5198 Rm = Bits32(opcode, 5, 3);
5199 setflags = !InITBlock();
5200 shift_t = SRType_LSL;
5201 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005202 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005203 case eEncodingT2:
5204 Rd = Bits32(opcode, 11, 8);
5205 Rn = Bits32(opcode, 19, 16);
5206 Rm = Bits32(opcode, 3, 0);
5207 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005208 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005209 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5210 return false;
5211 break;
5212 case eEncodingA1:
5213 Rd = Bits32(opcode, 15, 12);
5214 Rn = Bits32(opcode, 19, 16);
5215 Rm = Bits32(opcode, 3, 0);
5216 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005217 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005218
Johnny Chen157b9592011-02-18 21:13:05 +00005219 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005220 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005221 break;
5222 default:
5223 return false;
5224 }
5225
5226 // Read the first operand.
5227 int32_t val1 = ReadCoreReg(Rn, &success);
5228 if (!success)
5229 return false;
5230
5231 // Read the second operand.
5232 int32_t val2 = ReadCoreReg(Rm, &success);
5233 if (!success)
5234 return false;
5235
5236 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5237 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5238
5239 EmulateInstruction::Context context;
5240 context.type = EmulateInstruction::eContextImmediate;
5241 context.SetNoArgs ();
5242
5243 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5244 return false;
5245 }
5246 return true;
5247}
5248
Johnny Chena695f952011-02-23 21:24:25 +00005249// This instruction adds an immediate value to the PC value to form a PC-relative address,
5250// and writes the result to the destination register.
5251bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005252EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005253{
5254#if 0
5255 // ARM pseudo code...
5256 if ConditionPassed() then
5257 EncodingSpecificOperations();
5258 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5259 if d == 15 then // Can only occur for ARM encodings
5260 ALUWritePC(result);
5261 else
5262 R[d] = result;
5263#endif
5264
5265 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005266
Greg Clayton7bc39082011-03-24 23:53:38 +00005267 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005268 {
5269 uint32_t Rd;
5270 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5271 bool add;
5272 switch (encoding)
5273 {
5274 case eEncodingT1:
5275 Rd = Bits32(opcode, 10, 8);
5276 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5277 break;
5278 case eEncodingT2:
5279 case eEncodingT3:
5280 Rd = Bits32(opcode, 11, 8);
5281 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5282 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5283 if (BadReg(Rd))
5284 return false;
5285 break;
5286 case eEncodingA1:
5287 case eEncodingA2:
5288 Rd = Bits32(opcode, 15, 12);
5289 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5290 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5291 break;
5292 default:
5293 return false;
5294 }
5295
5296 // Read the PC value.
5297 uint32_t pc = ReadCoreReg(PC_REG, &success);
5298 if (!success)
5299 return false;
5300
5301 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5302
5303 EmulateInstruction::Context context;
5304 context.type = EmulateInstruction::eContextImmediate;
5305 context.SetNoArgs ();
5306
5307 if (!WriteCoreReg(context, result, Rd))
5308 return false;
5309 }
5310 return true;
5311}
5312
Johnny Chene97c0d52011-02-18 19:32:20 +00005313// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5314// to the destination register. It can optionally update the condition flags based on the result.
5315bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005316EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005317{
5318#if 0
5319 // ARM pseudo code...
5320 if ConditionPassed() then
5321 EncodingSpecificOperations();
5322 result = R[n] AND imm32;
5323 if d == 15 then // Can only occur for ARM encoding
5324 ALUWritePC(result); // setflags is always FALSE here
5325 else
5326 R[d] = result;
5327 if setflags then
5328 APSR.N = result<31>;
5329 APSR.Z = IsZeroBit(result);
5330 APSR.C = carry;
5331 // APSR.V unchanged
5332#endif
5333
5334 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005335
Greg Clayton7bc39082011-03-24 23:53:38 +00005336 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005337 {
5338 uint32_t Rd, Rn;
5339 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5340 bool setflags;
5341 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5342 switch (encoding)
5343 {
5344 case eEncodingT1:
5345 Rd = Bits32(opcode, 11, 8);
5346 Rn = Bits32(opcode, 19, 16);
5347 setflags = BitIsSet(opcode, 20);
5348 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005349 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005350 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005351 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005352 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5353 return false;
5354 break;
5355 case eEncodingA1:
5356 Rd = Bits32(opcode, 15, 12);
5357 Rn = Bits32(opcode, 19, 16);
5358 setflags = BitIsSet(opcode, 20);
5359 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005360
Johnny Chene97c0d52011-02-18 19:32:20 +00005361 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005362 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005363 break;
5364 default:
5365 return false;
5366 }
5367
Johnny Chene97c0d52011-02-18 19:32:20 +00005368 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005369 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005370 if (!success)
5371 return false;
5372
5373 uint32_t result = val1 & imm32;
5374
5375 EmulateInstruction::Context context;
5376 context.type = EmulateInstruction::eContextImmediate;
5377 context.SetNoArgs ();
5378
5379 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5380 return false;
5381 }
5382 return true;
5383}
5384
5385// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5386// and writes the result to the destination register. It can optionally update the condition flags
5387// based on the result.
5388bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005389EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005390{
5391#if 0
5392 // ARM pseudo code...
5393 if ConditionPassed() then
5394 EncodingSpecificOperations();
5395 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5396 result = R[n] AND shifted;
5397 if d == 15 then // Can only occur for ARM encoding
5398 ALUWritePC(result); // setflags is always FALSE here
5399 else
5400 R[d] = result;
5401 if setflags then
5402 APSR.N = result<31>;
5403 APSR.Z = IsZeroBit(result);
5404 APSR.C = carry;
5405 // APSR.V unchanged
5406#endif
5407
5408 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005409
Greg Clayton7bc39082011-03-24 23:53:38 +00005410 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005411 {
5412 uint32_t Rd, Rn, Rm;
5413 ARM_ShifterType shift_t;
5414 uint32_t shift_n; // the shift applied to the value read from Rm
5415 bool setflags;
5416 uint32_t carry;
5417 switch (encoding)
5418 {
5419 case eEncodingT1:
5420 Rd = Rn = Bits32(opcode, 2, 0);
5421 Rm = Bits32(opcode, 5, 3);
5422 setflags = !InITBlock();
5423 shift_t = SRType_LSL;
5424 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005425 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005426 case eEncodingT2:
5427 Rd = Bits32(opcode, 11, 8);
5428 Rn = Bits32(opcode, 19, 16);
5429 Rm = Bits32(opcode, 3, 0);
5430 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005431 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005432 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005433 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005434 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005435 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5436 return false;
5437 break;
5438 case eEncodingA1:
5439 Rd = Bits32(opcode, 15, 12);
5440 Rn = Bits32(opcode, 19, 16);
5441 Rm = Bits32(opcode, 3, 0);
5442 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005443 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005444
Johnny Chene97c0d52011-02-18 19:32:20 +00005445 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005446 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005447 break;
5448 default:
5449 return false;
5450 }
5451
Johnny Chene97c0d52011-02-18 19:32:20 +00005452 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005453 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005454 if (!success)
5455 return false;
5456
5457 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005458 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005459 if (!success)
5460 return false;
5461
5462 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5463 uint32_t result = val1 & shifted;
5464
5465 EmulateInstruction::Context context;
5466 context.type = EmulateInstruction::eContextImmediate;
5467 context.SetNoArgs ();
5468
5469 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5470 return false;
5471 }
5472 return true;
5473}
5474
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005475// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5476// immediate value, and writes the result to the destination register. It can optionally update the
5477// condition flags based on the result.
5478bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005479EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005480{
5481#if 0
5482 // ARM pseudo code...
5483 if ConditionPassed() then
5484 EncodingSpecificOperations();
5485 result = R[n] AND NOT(imm32);
5486 if d == 15 then // Can only occur for ARM encoding
5487 ALUWritePC(result); // setflags is always FALSE here
5488 else
5489 R[d] = result;
5490 if setflags then
5491 APSR.N = result<31>;
5492 APSR.Z = IsZeroBit(result);
5493 APSR.C = carry;
5494 // APSR.V unchanged
5495#endif
5496
5497 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005498
Greg Clayton7bc39082011-03-24 23:53:38 +00005499 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005500 {
5501 uint32_t Rd, Rn;
5502 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5503 bool setflags;
5504 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5505 switch (encoding)
5506 {
5507 case eEncodingT1:
5508 Rd = Bits32(opcode, 11, 8);
5509 Rn = Bits32(opcode, 19, 16);
5510 setflags = BitIsSet(opcode, 20);
5511 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5512 if (BadReg(Rd) || BadReg(Rn))
5513 return false;
5514 break;
5515 case eEncodingA1:
5516 Rd = Bits32(opcode, 15, 12);
5517 Rn = Bits32(opcode, 19, 16);
5518 setflags = BitIsSet(opcode, 20);
5519 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005520
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005521 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005522 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005523 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005524 break;
5525 default:
5526 return false;
5527 }
5528
5529 // Read the first operand.
5530 uint32_t val1 = ReadCoreReg(Rn, &success);
5531 if (!success)
5532 return false;
5533
5534 uint32_t result = val1 & ~imm32;
5535
5536 EmulateInstruction::Context context;
5537 context.type = EmulateInstruction::eContextImmediate;
5538 context.SetNoArgs ();
5539
5540 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5541 return false;
5542 }
5543 return true;
5544}
5545
5546// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5547// optionally-shifted register value, and writes the result to the destination register.
5548// It can optionally update the condition flags based on the result.
5549bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005550EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005551{
5552#if 0
5553 // ARM pseudo code...
5554 if ConditionPassed() then
5555 EncodingSpecificOperations();
5556 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5557 result = R[n] AND NOT(shifted);
5558 if d == 15 then // Can only occur for ARM encoding
5559 ALUWritePC(result); // setflags is always FALSE here
5560 else
5561 R[d] = result;
5562 if setflags then
5563 APSR.N = result<31>;
5564 APSR.Z = IsZeroBit(result);
5565 APSR.C = carry;
5566 // APSR.V unchanged
5567#endif
5568
5569 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005570
Greg Clayton7bc39082011-03-24 23:53:38 +00005571 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005572 {
5573 uint32_t Rd, Rn, Rm;
5574 ARM_ShifterType shift_t;
5575 uint32_t shift_n; // the shift applied to the value read from Rm
5576 bool setflags;
5577 uint32_t carry;
5578 switch (encoding)
5579 {
5580 case eEncodingT1:
5581 Rd = Rn = Bits32(opcode, 2, 0);
5582 Rm = Bits32(opcode, 5, 3);
5583 setflags = !InITBlock();
5584 shift_t = SRType_LSL;
5585 shift_n = 0;
5586 break;
5587 case eEncodingT2:
5588 Rd = Bits32(opcode, 11, 8);
5589 Rn = Bits32(opcode, 19, 16);
5590 Rm = Bits32(opcode, 3, 0);
5591 setflags = BitIsSet(opcode, 20);
5592 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5593 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5594 return false;
5595 break;
5596 case eEncodingA1:
5597 Rd = Bits32(opcode, 15, 12);
5598 Rn = Bits32(opcode, 19, 16);
5599 Rm = Bits32(opcode, 3, 0);
5600 setflags = BitIsSet(opcode, 20);
5601 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005602
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005603 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005604 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005605 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005606 break;
5607 default:
5608 return false;
5609 }
5610
5611 // Read the first operand.
5612 uint32_t val1 = ReadCoreReg(Rn, &success);
5613 if (!success)
5614 return false;
5615
5616 // Read the second operand.
5617 uint32_t val2 = ReadCoreReg(Rm, &success);
5618 if (!success)
5619 return false;
5620
5621 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5622 uint32_t result = val1 & ~shifted;
5623
5624 EmulateInstruction::Context context;
5625 context.type = EmulateInstruction::eContextImmediate;
5626 context.SetNoArgs ();
5627
5628 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5629 return false;
5630 }
5631 return true;
5632}
5633
Caroline Tice4d729c52011-02-18 00:55:53 +00005634// 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 +00005635// 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 +00005636bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005637EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005638{
5639#if 0
5640 if ConditionPassed() then
5641 EncodingSpecificOperations();
5642 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5643 address = if index then offset_addr else R[n];
5644 data = MemU[address,4];
5645 if wback then R[n] = offset_addr;
5646 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005647 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5648 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005649 R[t] = data;
5650 else // Can only apply before ARMv7
5651 R[t] = ROR(data, 8*UInt(address<1:0>));
5652#endif
5653
5654 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005655
Greg Clayton7bc39082011-03-24 23:53:38 +00005656 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005657 {
5658 const uint32_t addr_byte_size = GetAddressByteSize();
5659
5660 uint32_t t;
5661 uint32_t n;
5662 uint32_t imm32;
5663 bool index;
5664 bool add;
5665 bool wback;
5666
5667 switch (encoding)
5668 {
5669 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005670 // if Rn == '1111' then SEE LDR (literal);
5671 // if P == '0' && W == '1' then SEE LDRT;
5672 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005673 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5674 t = Bits32 (opcode, 15, 12);
5675 n = Bits32 (opcode, 19, 16);
5676 imm32 = Bits32 (opcode, 11, 0);
5677
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005678 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5679 index = BitIsSet (opcode, 24);
5680 add = BitIsSet (opcode, 23);
5681 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005682
5683 // if wback && n == t then UNPREDICTABLE;
5684 if (wback && (n == t))
5685 return false;
5686
5687 break;
5688
5689 default:
5690 return false;
5691 }
5692
5693 addr_t address;
5694 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005695 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005696 if (!success)
5697 return false;
5698
5699 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5700 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005701 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005702 else
5703 offset_addr = base_address - imm32;
5704
5705 // address = if index then offset_addr else R[n];
5706 if (index)
5707 address = offset_addr;
5708 else
5709 address = base_address;
5710
5711 // data = MemU[address,4];
5712
5713 Register base_reg;
5714 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5715
5716 EmulateInstruction::Context context;
5717 context.type = eContextRegisterLoad;
5718 context.SetRegisterPlusOffset (base_reg, address - base_address);
5719
5720 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5721 if (!success)
5722 return false;
5723
5724 // if wback then R[n] = offset_addr;
5725 if (wback)
5726 {
5727 context.type = eContextAdjustBaseRegister;
5728 context.SetAddress (offset_addr);
5729 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5730 return false;
5731 }
5732
5733 // if t == 15 then
5734 if (t == 15)
5735 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005736 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005737 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5738 {
5739 // LoadWritePC (data);
5740 context.type = eContextRegisterLoad;
5741 context.SetRegisterPlusOffset (base_reg, address - base_address);
5742 LoadWritePC (context, data);
5743 }
5744 else
5745 return false;
5746 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005747 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005748 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5749 {
5750 // R[t] = data;
5751 context.type = eContextRegisterLoad;
5752 context.SetRegisterPlusOffset (base_reg, address - base_address);
5753 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5754 return false;
5755 }
5756 // else // Can only apply before ARMv7
5757 else
5758 {
5759 // R[t] = ROR(data, 8*UInt(address<1:0>));
5760 data = ROR (data, Bits32 (address, 1, 0));
5761 context.type = eContextRegisterLoad;
5762 context.SetImmediate (data);
5763 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5764 return false;
5765 }
5766
5767 }
5768 return true;
5769}
5770
Caroline Ticefe479112011-02-18 18:52:37 +00005771// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5772// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5773bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005774EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005775{
5776#if 0
5777 if ConditionPassed() then
5778 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5779 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5780 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5781 address = if index then offset_addr else R[n];
5782 data = MemU[address,4];
5783 if wback then R[n] = offset_addr;
5784 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005785 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5786 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005787 R[t] = data;
5788 else // Can only apply before ARMv7
5789 if CurrentInstrSet() == InstrSet_ARM then
5790 R[t] = ROR(data, 8*UInt(address<1:0>));
5791 else
5792 R[t] = bits(32) UNKNOWN;
5793#endif
5794
5795 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005796
Greg Clayton7bc39082011-03-24 23:53:38 +00005797 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005798 {
5799 const uint32_t addr_byte_size = GetAddressByteSize();
5800
5801 uint32_t t;
5802 uint32_t n;
5803 uint32_t m;
5804 bool index;
5805 bool add;
5806 bool wback;
5807 ARM_ShifterType shift_t;
5808 uint32_t shift_n;
5809
5810 switch (encoding)
5811 {
5812 case eEncodingT1:
5813 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5814 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5815 t = Bits32 (opcode, 2, 0);
5816 n = Bits32 (opcode, 5, 3);
5817 m = Bits32 (opcode, 8, 6);
5818
5819 // index = TRUE; add = TRUE; wback = FALSE;
5820 index = true;
5821 add = true;
5822 wback = false;
5823
5824 // (shift_t, shift_n) = (SRType_LSL, 0);
5825 shift_t = SRType_LSL;
5826 shift_n = 0;
5827
5828 break;
5829
5830 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005831 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005832 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5833 t = Bits32 (opcode, 15, 12);
5834 n = Bits32 (opcode, 19, 16);
5835 m = Bits32 (opcode, 3, 0);
5836
5837 // index = TRUE; add = TRUE; wback = FALSE;
5838 index = true;
5839 add = true;
5840 wback = false;
5841
5842 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5843 shift_t = SRType_LSL;
5844 shift_n = Bits32 (opcode, 5, 4);
5845
5846 // if BadReg(m) then UNPREDICTABLE;
5847 if (BadReg (m))
5848 return false;
5849
5850 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5851 if ((t == 15) && InITBlock() && !LastInITBlock())
5852 return false;
5853
5854 break;
5855
5856 case eEncodingA1:
5857 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005858 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005859 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5860 t = Bits32 (opcode, 15, 12);
5861 n = Bits32 (opcode, 19, 16);
5862 m = Bits32 (opcode, 3, 0);
5863
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005864 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005865 index = BitIsSet (opcode, 24);
5866 add = BitIsSet (opcode, 23);
5867 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5868
5869 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5870 uint32_t type = Bits32 (opcode, 6, 5);
5871 uint32_t imm5 = Bits32 (opcode, 11, 7);
5872 shift_n = DecodeImmShift (type, imm5, shift_t);
5873
5874 // if m == 15 then UNPREDICTABLE;
5875 if (m == 15)
5876 return false;
5877
5878 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5879 if (wback && ((n == 15) || (n == t)))
5880 return false;
5881 }
5882 break;
5883
5884
5885 default:
5886 return false;
5887 }
5888
5889 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5890 if (!success)
5891 return false;
5892
5893 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5894 if (!success)
5895 return false;
5896
5897 addr_t offset_addr;
5898 addr_t address;
5899
5900 // 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 +00005901 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005902
5903 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5904 if (add)
5905 offset_addr = Rn + offset;
5906 else
5907 offset_addr = Rn - offset;
5908
5909 // address = if index then offset_addr else R[n];
5910 if (index)
5911 address = offset_addr;
5912 else
5913 address = Rn;
5914
5915 // data = MemU[address,4];
5916 Register base_reg;
5917 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5918
5919 EmulateInstruction::Context context;
5920 context.type = eContextRegisterLoad;
5921 context.SetRegisterPlusOffset (base_reg, address - Rn);
5922
5923 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5924 if (!success)
5925 return false;
5926
5927 // if wback then R[n] = offset_addr;
5928 if (wback)
5929 {
5930 context.type = eContextAdjustBaseRegister;
5931 context.SetAddress (offset_addr);
5932 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5933 return false;
5934 }
5935
5936 // if t == 15 then
5937 if (t == 15)
5938 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005939 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005940 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5941 {
5942 context.type = eContextRegisterLoad;
5943 context.SetRegisterPlusOffset (base_reg, address - Rn);
5944 LoadWritePC (context, data);
5945 }
5946 else
5947 return false;
5948 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005949 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005950 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5951 {
5952 // R[t] = data;
5953 context.type = eContextRegisterLoad;
5954 context.SetRegisterPlusOffset (base_reg, address - Rn);
5955 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5956 return false;
5957 }
5958 else // Can only apply before ARMv7
5959 {
5960 // if CurrentInstrSet() == InstrSet_ARM then
5961 if (CurrentInstrSet () == eModeARM)
5962 {
5963 // R[t] = ROR(data, 8*UInt(address<1:0>));
5964 data = ROR (data, Bits32 (address, 1, 0));
5965 context.type = eContextRegisterLoad;
5966 context.SetImmediate (data);
5967 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5968 return false;
5969 }
5970 else
5971 {
5972 // R[t] = bits(32) UNKNOWN;
5973 WriteBits32Unknown (t);
5974 }
5975 }
5976 }
5977 return true;
5978}
Caroline Tice21b604b2011-02-18 21:06:04 +00005979
5980// LDRB (immediate, Thumb)
5981bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005982EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00005983{
5984#if 0
5985 if ConditionPassed() then
5986 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5987 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5988 address = if index then offset_addr else R[n];
5989 R[t] = ZeroExtend(MemU[address,1], 32);
5990 if wback then R[n] = offset_addr;
5991#endif
5992
5993 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00005994
Greg Clayton7bc39082011-03-24 23:53:38 +00005995 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00005996 {
5997 uint32_t t;
5998 uint32_t n;
5999 uint32_t imm32;
6000 bool index;
6001 bool add;
6002 bool wback;
6003
6004 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6005 switch (encoding)
6006 {
6007 case eEncodingT1:
6008 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6009 t = Bits32 (opcode, 2, 0);
6010 n = Bits32 (opcode, 5, 3);
6011 imm32 = Bits32 (opcode, 10, 6);
6012
6013 // index = TRUE; add = TRUE; wback = FALSE;
6014 index = true;
6015 add = true;
6016 wback= false;
6017
6018 break;
6019
6020 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006021 // if Rt == '1111' then SEE PLD;
6022 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006023 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6024 t = Bits32 (opcode, 15, 12);
6025 n = Bits32 (opcode, 19, 16);
6026 imm32 = Bits32 (opcode, 11, 0);
6027
6028 // index = TRUE; add = TRUE; wback = FALSE;
6029 index = true;
6030 add = true;
6031 wback = false;
6032
6033 // if t == 13 then UNPREDICTABLE;
6034 if (t == 13)
6035 return false;
6036
6037 break;
6038
6039 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006040 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6041 // if Rn == '1111' then SEE LDRB (literal);
6042 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6043 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006044 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6045 return false;
6046
6047 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6048 t = Bits32 (opcode, 15, 12);
6049 n = Bits32 (opcode, 19, 16);
6050 imm32 = Bits32 (opcode, 7, 0);
6051
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006052 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006053 index = BitIsSet (opcode, 10);
6054 add = BitIsSet (opcode, 9);
6055 wback = BitIsSet (opcode, 8);
6056
6057 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6058 if (BadReg (t) || (wback && (n == t)))
6059 return false;
6060
6061 break;
6062
6063 default:
6064 return false;
6065 }
6066
6067 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6068 if (!success)
6069 return false;
6070
6071 addr_t address;
6072 addr_t offset_addr;
6073
6074 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6075 if (add)
6076 offset_addr = Rn + imm32;
6077 else
6078 offset_addr = Rn - imm32;
6079
6080 // address = if index then offset_addr else R[n];
6081 if (index)
6082 address = offset_addr;
6083 else
6084 address = Rn;
6085
6086 // R[t] = ZeroExtend(MemU[address,1], 32);
6087 Register base_reg;
6088 Register data_reg;
6089 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6090 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6091
6092 EmulateInstruction::Context context;
6093 context.type = eContextRegisterLoad;
6094 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6095
6096 uint64_t data = MemURead (context, address, 1, 0, &success);
6097 if (!success)
6098 return false;
6099
6100 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6101 return false;
6102
6103 // if wback then R[n] = offset_addr;
6104 if (wback)
6105 {
6106 context.type = eContextAdjustBaseRegister;
6107 context.SetAddress (offset_addr);
6108 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6109 return false;
6110 }
6111 }
6112 return true;
6113}
Caroline Ticef55261f2011-02-18 22:24:22 +00006114
6115// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6116// zero-extends it to form a 32-bit word and writes it to a register.
6117bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006118EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006119{
6120#if 0
6121 if ConditionPassed() then
6122 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6123 base = Align(PC,4);
6124 address = if add then (base + imm32) else (base - imm32);
6125 R[t] = ZeroExtend(MemU[address,1], 32);
6126#endif
6127
6128 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006129
Greg Clayton7bc39082011-03-24 23:53:38 +00006130 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006131 {
6132 uint32_t t;
6133 uint32_t imm32;
6134 bool add;
6135 switch (encoding)
6136 {
6137 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006138 // if Rt == '1111' then SEE PLD;
6139 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006140 t = Bits32 (opcode, 15, 12);
6141 imm32 = Bits32 (opcode, 11, 0);
6142 add = BitIsSet (opcode, 23);
6143
6144 // if t == 13 then UNPREDICTABLE;
6145 if (t == 13)
6146 return false;
6147
6148 break;
6149
6150 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006151 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006152 t = Bits32 (opcode, 15, 12);
6153 imm32 = Bits32 (opcode, 11, 0);
6154 add = BitIsSet (opcode, 23);
6155
6156 // if t == 15 then UNPREDICTABLE;
6157 if (t == 15)
6158 return false;
6159 break;
6160
6161 default:
6162 return false;
6163 }
6164
6165 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006166 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006167 if (!success)
6168 return false;
6169
6170 uint32_t base = AlignPC (pc_val);
6171
6172 addr_t address;
6173 // address = if add then (base + imm32) else (base - imm32);
6174 if (add)
6175 address = base + imm32;
6176 else
6177 address = base - imm32;
6178
6179 // R[t] = ZeroExtend(MemU[address,1], 32);
6180 EmulateInstruction::Context context;
6181 context.type = eContextRelativeBranchImmediate;
6182 context.SetImmediate (address - base);
6183
6184 uint64_t data = MemURead (context, address, 1, 0, &success);
6185 if (!success)
6186 return false;
6187
6188 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6189 return false;
6190 }
6191 return true;
6192}
Caroline Tice30fec122011-02-18 23:52:21 +00006193
6194// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6195// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6196// optionally be shifted.
6197bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006198EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006199{
6200#if 0
6201 if ConditionPassed() then
6202 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6203 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6204 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6205 address = if index then offset_addr else R[n];
6206 R[t] = ZeroExtend(MemU[address,1],32);
6207 if wback then R[n] = offset_addr;
6208#endif
6209
6210 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006211
Greg Clayton7bc39082011-03-24 23:53:38 +00006212 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006213 {
6214 uint32_t t;
6215 uint32_t n;
6216 uint32_t m;
6217 bool index;
6218 bool add;
6219 bool wback;
6220 ARM_ShifterType shift_t;
6221 uint32_t shift_n;
6222
6223 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6224 switch (encoding)
6225 {
6226 case eEncodingT1:
6227 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6228 t = Bits32 (opcode, 2, 0);
6229 n = Bits32 (opcode, 5, 3);
6230 m = Bits32 (opcode, 8, 6);
6231
6232 // index = TRUE; add = TRUE; wback = FALSE;
6233 index = true;
6234 add = true;
6235 wback = false;
6236
6237 // (shift_t, shift_n) = (SRType_LSL, 0);
6238 shift_t = SRType_LSL;
6239 shift_n = 0;
6240 break;
6241
6242 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006243 // if Rt == '1111' then SEE PLD;
6244 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006245 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6246 t = Bits32 (opcode, 15, 12);
6247 n = Bits32 (opcode, 19, 16);
6248 m = Bits32 (opcode, 3, 0);
6249
6250 // index = TRUE; add = TRUE; wback = FALSE;
6251 index = true;
6252 add = true;
6253 wback = false;
6254
6255 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6256 shift_t = SRType_LSL;
6257 shift_n = Bits32 (opcode, 5, 4);
6258
6259 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6260 if ((t == 13) || BadReg (m))
6261 return false;
6262 break;
6263
6264 case eEncodingA1:
6265 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006266 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006267 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6268 t = Bits32 (opcode, 15, 12);
6269 n = Bits32 (opcode, 19, 16);
6270 m = Bits32 (opcode, 3, 0);
6271
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006272 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006273 index = BitIsSet (opcode, 24);
6274 add = BitIsSet (opcode, 23);
6275 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6276
6277 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6278 uint32_t type = Bits32 (opcode, 6, 5);
6279 uint32_t imm5 = Bits32 (opcode, 11, 7);
6280 shift_n = DecodeImmShift (type, imm5, shift_t);
6281
6282 // if t == 15 || m == 15 then UNPREDICTABLE;
6283 if ((t == 15) || (m == 15))
6284 return false;
6285
6286 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6287 if (wback && ((n == 15) || (n == t)))
6288 return false;
6289 }
6290 break;
6291
6292 default:
6293 return false;
6294 }
6295
6296 addr_t offset_addr;
6297 addr_t address;
6298
6299 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6300 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6301 if (!success)
6302 return false;
6303
6304 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6305
6306 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6307 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6308 if (!success)
6309 return false;
6310
6311 if (add)
6312 offset_addr = Rn + offset;
6313 else
6314 offset_addr = Rn - offset;
6315
6316 // address = if index then offset_addr else R[n];
6317 if (index)
6318 address = offset_addr;
6319 else
6320 address = Rn;
6321
6322 // R[t] = ZeroExtend(MemU[address,1],32);
6323 Register base_reg;
6324 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6325
6326 EmulateInstruction::Context context;
6327 context.type = eContextRegisterLoad;
6328 context.SetRegisterPlusOffset (base_reg, address - Rn);
6329
6330 uint64_t data = MemURead (context, address, 1, 0, &success);
6331 if (!success)
6332 return false;
6333
6334 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6335 return false;
6336
6337 // if wback then R[n] = offset_addr;
6338 if (wback)
6339 {
6340 context.type = eContextAdjustBaseRegister;
6341 context.SetAddress (offset_addr);
6342 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6343 return false;
6344 }
6345 }
6346 return true;
6347}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006348
6349// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6350// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6351// post-indexed, or pre-indexed addressing.
6352bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006353EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006354{
6355#if 0
6356 if ConditionPassed() then
6357 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6358 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6359 address = if index then offset_addr else R[n];
6360 data = MemU[address,2];
6361 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006362 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006363 R[t] = ZeroExtend(data, 32);
6364 else // Can only apply before ARMv7
6365 R[t] = bits(32) UNKNOWN;
6366#endif
6367
6368
6369 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006370
Greg Clayton7bc39082011-03-24 23:53:38 +00006371 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006372 {
6373 uint32_t t;
6374 uint32_t n;
6375 uint32_t imm32;
6376 bool index;
6377 bool add;
6378 bool wback;
6379
6380 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6381 switch (encoding)
6382 {
6383 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006384 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006385 t = Bits32 (opcode, 2, 0);
6386 n = Bits32 (opcode, 5, 3);
6387 imm32 = Bits32 (opcode, 10, 6) << 1;
6388
6389 // index = TRUE; add = TRUE; wback = FALSE;
6390 index = true;
6391 add = true;
6392 wback = false;
6393
6394 break;
6395
6396 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006397 // if Rt == '1111' then SEE "Unallocated memory hints";
6398 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006399 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6400 t = Bits32 (opcode, 15, 12);
6401 n = Bits32 (opcode, 19, 16);
6402 imm32 = Bits32 (opcode, 11, 0);
6403
6404 // index = TRUE; add = TRUE; wback = FALSE;
6405 index = true;
6406 add = true;
6407 wback = false;
6408
6409 // if t == 13 then UNPREDICTABLE;
6410 if (t == 13)
6411 return false;
6412 break;
6413
6414 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006415 // if Rn == '1111' then SEE LDRH (literal);
6416 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6417 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6418 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006419 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6420 return false;
6421
6422 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6423 t = Bits32 (opcode, 15, 12);
6424 n = Bits32 (opcode, 19, 16);
6425 imm32 = Bits32 (opcode, 7, 0);
6426
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006427 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006428 index = BitIsSet (opcode, 10);
6429 add = BitIsSet (opcode, 9);
6430 wback = BitIsSet (opcode, 8);
6431
6432 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6433 if (BadReg (t) || (wback && (n == t)))
6434 return false;
6435 break;
6436
6437 default:
6438 return false;
6439 }
6440
6441 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6442 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6443 if (!success)
6444 return false;
6445
6446 addr_t offset_addr;
6447 addr_t address;
6448
6449 if (add)
6450 offset_addr = Rn + imm32;
6451 else
6452 offset_addr = Rn - imm32;
6453
6454 // address = if index then offset_addr else R[n];
6455 if (index)
6456 address = offset_addr;
6457 else
6458 address = Rn;
6459
6460 // data = MemU[address,2];
6461 Register base_reg;
6462 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6463
6464 EmulateInstruction::Context context;
6465 context.type = eContextRegisterLoad;
6466 context.SetRegisterPlusOffset (base_reg, address - Rn);
6467
6468 uint64_t data = MemURead (context, address, 2, 0, &success);
6469 if (!success)
6470 return false;
6471
6472 // if wback then R[n] = offset_addr;
6473 if (wback)
6474 {
6475 context.type = eContextAdjustBaseRegister;
6476 context.SetAddress (offset_addr);
6477 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6478 return false;
6479 }
6480
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006481 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006482 if (UnalignedSupport () || BitIsClear (address, 0))
6483 {
6484 // R[t] = ZeroExtend(data, 32);
6485 context.type = eContextRegisterLoad;
6486 context.SetRegisterPlusOffset (base_reg, address - Rn);
6487 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6488 return false;
6489 }
6490 else // Can only apply before ARMv7
6491 {
6492 // R[t] = bits(32) UNKNOWN;
6493 WriteBits32Unknown (t);
6494 }
6495 }
6496 return true;
6497}
Caroline Ticefe479112011-02-18 18:52:37 +00006498
Caroline Tice952b5382011-02-28 23:15:24 +00006499// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6500// zero-extends it to form a 32-bit word, and writes it to a register.
6501bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006502EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006503{
6504#if 0
6505 if ConditionPassed() then
6506 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6507 base = Align(PC,4);
6508 address = if add then (base + imm32) else (base - imm32);
6509 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006510 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006511 R[t] = ZeroExtend(data, 32);
6512 else // Can only apply before ARMv7
6513 R[t] = bits(32) UNKNOWN;
6514#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006515
Caroline Tice952b5382011-02-28 23:15:24 +00006516 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006517
Greg Clayton7bc39082011-03-24 23:53:38 +00006518 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006519 {
6520 uint32_t t;
6521 uint32_t imm32;
6522 bool add;
6523
6524 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6525 switch (encoding)
6526 {
6527 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006528 // if Rt == '1111' then SEE "Unallocated memory hints";
6529 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006530 t = Bits32 (opcode, 15, 12);
6531 imm32 = Bits32 (opcode, 11, 0);
6532 add = BitIsSet (opcode, 23);
6533
6534 // if t == 13 then UNPREDICTABLE;
6535 if (t == 13)
6536 return false;
6537
6538 break;
6539
6540 case eEncodingA1:
6541 {
6542 uint32_t imm4H = Bits32 (opcode, 11, 8);
6543 uint32_t imm4L = Bits32 (opcode, 3, 0);
6544
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006545 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006546 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006547 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006548 add = BitIsSet (opcode, 23);
6549
6550 // if t == 15 then UNPREDICTABLE;
6551 if (t == 15)
6552 return false;
6553 break;
6554 }
6555
6556 default:
6557 return false;
6558 }
6559
6560 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006561 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006562 if (!success)
6563 return false;
6564
6565 addr_t base = AlignPC (pc_value);
6566 addr_t address;
6567
6568 // address = if add then (base + imm32) else (base - imm32);
6569 if (add)
6570 address = base + imm32;
6571 else
6572 address = base - imm32;
6573
6574 // data = MemU[address,2];
6575 Register base_reg;
6576 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6577
6578 EmulateInstruction::Context context;
6579 context.type = eContextRegisterLoad;
6580 context.SetRegisterPlusOffset (base_reg, address - base);
6581
6582 uint64_t data = MemURead (context, address, 2, 0, &success);
6583 if (!success)
6584 return false;
6585
6586
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006587 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006588 if (UnalignedSupport () || BitIsClear (address, 0))
6589 {
6590 // R[t] = ZeroExtend(data, 32);
6591 context.type = eContextRegisterLoad;
6592 context.SetRegisterPlusOffset (base_reg, address - base);
6593 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6594 return false;
6595
6596 }
6597 else // Can only apply before ARMv7
6598 {
6599 // R[t] = bits(32) UNKNOWN;
6600 WriteBits32Unknown (t);
6601 }
6602 }
6603 return true;
6604}
6605
Caroline Tice0e6bc952011-03-01 18:00:42 +00006606// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6607// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6608// be shifted left by 0, 1, 2, or 3 bits.
6609bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006610EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006611{
6612#if 0
6613 if ConditionPassed() then
6614 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6615 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6616 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6617 address = if index then offset_addr else R[n];
6618 data = MemU[address,2];
6619 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006620 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006621 R[t] = ZeroExtend(data, 32);
6622 else // Can only apply before ARMv7
6623 R[t] = bits(32) UNKNOWN;
6624#endif
6625
6626 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006627
Greg Clayton7bc39082011-03-24 23:53:38 +00006628 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006629 {
6630 uint32_t t;
6631 uint32_t n;
6632 uint32_t m;
6633 bool index;
6634 bool add;
6635 bool wback;
6636 ARM_ShifterType shift_t;
6637 uint32_t shift_n;
6638
6639 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6640 switch (encoding)
6641 {
6642 case eEncodingT1:
6643 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6644 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6645 t = Bits32 (opcode, 2, 0);
6646 n = Bits32 (opcode, 5, 3);
6647 m = Bits32 (opcode, 8, 6);
6648
6649 // index = TRUE; add = TRUE; wback = FALSE;
6650 index = true;
6651 add = true;
6652 wback = false;
6653
6654 // (shift_t, shift_n) = (SRType_LSL, 0);
6655 shift_t = SRType_LSL;
6656 shift_n = 0;
6657
6658 break;
6659
6660 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006661 // if Rn == '1111' then SEE LDRH (literal);
6662 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006663 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6664 t = Bits32 (opcode, 15, 12);
6665 n = Bits32 (opcode, 19, 16);
6666 m = Bits32 (opcode, 3, 0);
6667
6668 // index = TRUE; add = TRUE; wback = FALSE;
6669 index = true;
6670 add = true;
6671 wback = false;
6672
6673 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6674 shift_t = SRType_LSL;
6675 shift_n = Bits32 (opcode, 5, 4);
6676
6677 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6678 if ((t == 13) || BadReg (m))
6679 return false;
6680 break;
6681
6682 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006683 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006684 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6685 t = Bits32 (opcode, 15, 12);
6686 n = Bits32 (opcode, 19, 16);
6687 m = Bits32 (opcode, 3, 0);
6688
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006689 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006690 index = BitIsSet (opcode, 24);
6691 add = BitIsSet (opcode, 23);
6692 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6693
6694 // (shift_t, shift_n) = (SRType_LSL, 0);
6695 shift_t = SRType_LSL;
6696 shift_n = 0;
6697
6698 // if t == 15 || m == 15 then UNPREDICTABLE;
6699 if ((t == 15) || (m == 15))
6700 return false;
6701
6702 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6703 if (wback && ((n == 15) || (n == t)))
6704 return false;
6705
6706 break;
6707
6708 default:
6709 return false;
6710 }
6711
6712 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6713
6714 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6715 if (!success)
6716 return false;
6717
6718 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6719
6720 addr_t offset_addr;
6721 addr_t address;
6722
6723 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6724 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6725 if (!success)
6726 return false;
6727
6728 if (add)
6729 offset_addr = Rn + offset;
6730 else
6731 offset_addr = Rn - offset;
6732
6733 // address = if index then offset_addr else R[n];
6734 if (index)
6735 address = offset_addr;
6736 else
6737 address = Rn;
6738
6739 // data = MemU[address,2];
6740 Register base_reg;
6741 Register offset_reg;
6742 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6743 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6744
6745 EmulateInstruction::Context context;
6746 context.type = eContextRegisterLoad;
6747 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6748 uint64_t data = MemURead (context, address, 2, 0, &success);
6749 if (!success)
6750 return false;
6751
6752 // if wback then R[n] = offset_addr;
6753 if (wback)
6754 {
6755 context.type = eContextAdjustBaseRegister;
6756 context.SetAddress (offset_addr);
6757 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6758 return false;
6759 }
6760
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006761 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006762 if (UnalignedSupport() || BitIsClear (address, 0))
6763 {
6764 // R[t] = ZeroExtend(data, 32);
6765 context.type = eContextRegisterLoad;
6766 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6767 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6768 return false;
6769 }
6770 else // Can only apply before ARMv7
6771 {
6772 // R[t] = bits(32) UNKNOWN;
6773 WriteBits32Unknown (t);
6774 }
6775 }
6776 return true;
6777}
6778
Caroline Ticea5e28af2011-03-01 21:53:03 +00006779// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6780// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6781// or pre-indexed addressing.
6782bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006783EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006784{
6785#if 0
6786 if ConditionPassed() then
6787 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6788 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6789 address = if index then offset_addr else R[n];
6790 R[t] = SignExtend(MemU[address,1], 32);
6791 if wback then R[n] = offset_addr;
6792#endif
6793
6794 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006795
Greg Clayton7bc39082011-03-24 23:53:38 +00006796 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006797 {
6798 uint32_t t;
6799 uint32_t n;
6800 uint32_t imm32;
6801 bool index;
6802 bool add;
6803 bool wback;
6804
6805 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6806 switch (encoding)
6807 {
6808 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006809 // if Rt == '1111' then SEE PLI;
6810 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006811 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6812 t = Bits32 (opcode, 15, 12);
6813 n = Bits32 (opcode, 19, 16);
6814 imm32 = Bits32 (opcode, 11, 0);
6815
6816 // index = TRUE; add = TRUE; wback = FALSE;
6817 index = true;
6818 add = true;
6819 wback = false;
6820
6821 // if t == 13 then UNPREDICTABLE;
6822 if (t == 13)
6823 return false;
6824
6825 break;
6826
6827 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006828 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6829 // if Rn == '1111' then SEE LDRSB (literal);
6830 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6831 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006832 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6833 return false;
6834
6835 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6836 t = Bits32 (opcode, 15, 12);
6837 n = Bits32 (opcode, 19, 16);
6838 imm32 = Bits32 (opcode, 7, 0);
6839
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006840 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006841 index = BitIsSet (opcode, 10);
6842 add = BitIsSet (opcode, 9);
6843 wback = BitIsSet (opcode, 8);
6844
6845 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006846 if (((t == 13) || ((t == 15)
6847 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6848 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006849 return false;
6850
6851 break;
6852
6853 case eEncodingA1:
6854 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006855 // if Rn == '1111' then SEE LDRSB (literal);
6856 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006857 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6858 t = Bits32 (opcode, 15, 12);
6859 n = Bits32 (opcode, 19, 16);
6860
6861 uint32_t imm4H = Bits32 (opcode, 11, 8);
6862 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006863 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006864
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006865 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006866 index = BitIsSet (opcode, 24);
6867 add = BitIsSet (opcode, 23);
6868 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6869
6870 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6871 if ((t == 15) || (wback && (n == t)))
6872 return false;
6873
6874 break;
6875 }
6876
6877 default:
6878 return false;
6879 }
6880
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006881 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006882 if (!success)
6883 return false;
6884
6885 addr_t offset_addr;
6886 addr_t address;
6887
6888 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6889 if (add)
6890 offset_addr = Rn + imm32;
6891 else
6892 offset_addr = Rn - imm32;
6893
6894 // address = if index then offset_addr else R[n];
6895 if (index)
6896 address = offset_addr;
6897 else
6898 address = Rn;
6899
6900 // R[t] = SignExtend(MemU[address,1], 32);
6901 Register base_reg;
6902 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6903
6904 EmulateInstruction::Context context;
6905 context.type = eContextRegisterLoad;
6906 context.SetRegisterPlusOffset (base_reg, address - Rn);
6907
6908 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6909 if (!success)
6910 return false;
6911
6912 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6913 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6914 return false;
6915
6916 // if wback then R[n] = offset_addr;
6917 if (wback)
6918 {
6919 context.type = eContextAdjustBaseRegister;
6920 context.SetAddress (offset_addr);
6921 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6922 return false;
6923 }
6924 }
6925
6926 return true;
6927}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006928
Caroline Tice5f593912011-03-01 22:25:17 +00006929// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6930// sign-extends it to form a 32-bit word, and writes tit to a register.
6931bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006932EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006933{
6934#if 0
6935 if ConditionPassed() then
6936 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6937 base = Align(PC,4);
6938 address = if add then (base + imm32) else (base - imm32);
6939 R[t] = SignExtend(MemU[address,1], 32);
6940#endif
6941
6942 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006943
Greg Clayton7bc39082011-03-24 23:53:38 +00006944 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006945 {
6946 uint32_t t;
6947 uint32_t imm32;
6948 bool add;
6949
6950 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6951 switch (encoding)
6952 {
6953 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006954 // if Rt == '1111' then SEE PLI;
6955 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006956 t = Bits32 (opcode, 15, 12);
6957 imm32 = Bits32 (opcode, 11, 0);
6958 add = BitIsSet (opcode, 23);
6959
6960 // if t == 13 then UNPREDICTABLE;
6961 if (t == 13)
6962 return false;
6963
6964 break;
6965
6966 case eEncodingA1:
6967 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006968 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006969 t = Bits32 (opcode, 15, 12);
6970 uint32_t imm4H = Bits32 (opcode, 11, 8);
6971 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006972 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006973 add = BitIsSet (opcode, 23);
6974
6975 // if t == 15 then UNPREDICTABLE;
6976 if (t == 15)
6977 return false;
6978
6979 break;
6980 }
6981
6982 default:
6983 return false;
6984 }
6985
6986 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006987 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006988 if (!success)
6989 return false;
6990 uint64_t base = AlignPC (pc_value);
6991
6992 // address = if add then (base + imm32) else (base - imm32);
6993 addr_t address;
6994 if (add)
6995 address = base + imm32;
6996 else
6997 address = base - imm32;
6998
6999 // R[t] = SignExtend(MemU[address,1], 32);
7000 Register base_reg;
7001 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7002
7003 EmulateInstruction::Context context;
7004 context.type = eContextRegisterLoad;
7005 context.SetRegisterPlusOffset (base_reg, address - base);
7006
7007 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7008 if (!success)
7009 return false;
7010
7011 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7012 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7013 return false;
7014 }
7015 return true;
7016}
7017
Caroline Tice672f3112011-03-01 23:55:59 +00007018// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7019// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7020// shifted left by 0, 1, 2, or 3 bits.
7021bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007022EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007023{
7024#if 0
7025 if ConditionPassed() then
7026 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7027 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7028 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7029 address = if index then offset_addr else R[n];
7030 R[t] = SignExtend(MemU[address,1], 32);
7031 if wback then R[n] = offset_addr;
7032#endif
7033
7034 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007035
Greg Clayton7bc39082011-03-24 23:53:38 +00007036 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007037 {
7038 uint32_t t;
7039 uint32_t n;
7040 uint32_t m;
7041 bool index;
7042 bool add;
7043 bool wback;
7044 ARM_ShifterType shift_t;
7045 uint32_t shift_n;
7046
7047 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7048 switch (encoding)
7049 {
7050 case eEncodingT1:
7051 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7052 t = Bits32 (opcode, 2, 0);
7053 n = Bits32 (opcode, 5, 3);
7054 m = Bits32 (opcode, 8, 6);
7055
7056 // index = TRUE; add = TRUE; wback = FALSE;
7057 index = true;
7058 add = true;
7059 wback = false;
7060
7061 // (shift_t, shift_n) = (SRType_LSL, 0);
7062 shift_t = SRType_LSL;
7063 shift_n = 0;
7064
7065 break;
7066
7067 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007068 // if Rt == '1111' then SEE PLI;
7069 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007070 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7071 t = Bits32 (opcode, 15, 12);
7072 n = Bits32 (opcode, 19, 16);
7073 m = Bits32 (opcode, 3, 0);
7074
7075 // index = TRUE; add = TRUE; wback = FALSE;
7076 index = true;
7077 add = true;
7078 wback = false;
7079
7080 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7081 shift_t = SRType_LSL;
7082 shift_n = Bits32 (opcode, 5, 4);
7083
7084 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7085 if ((t == 13) || BadReg (m))
7086 return false;
7087 break;
7088
7089 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007090 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007091 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7092 t = Bits32 (opcode, 15, 12);
7093 n = Bits32 (opcode, 19, 16);
7094 m = Bits32 (opcode, 3, 0);
7095
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007096 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007097 index = BitIsSet (opcode, 24);
7098 add = BitIsSet (opcode, 23);
7099 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7100
7101 // (shift_t, shift_n) = (SRType_LSL, 0);
7102 shift_t = SRType_LSL;
7103 shift_n = 0;
7104
7105 // if t == 15 || m == 15 then UNPREDICTABLE;
7106 if ((t == 15) || (m == 15))
7107 return false;
7108
7109 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7110 if (wback && ((n == 15) || (n == t)))
7111 return false;
7112 break;
7113
7114 default:
7115 return false;
7116 }
7117
7118 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7119 if (!success)
7120 return false;
7121
7122 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7123 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7124
7125 addr_t offset_addr;
7126 addr_t address;
7127
7128 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7129 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7130 if (!success)
7131 return false;
7132
7133 if (add)
7134 offset_addr = Rn + offset;
7135 else
7136 offset_addr = Rn - offset;
7137
7138 // address = if index then offset_addr else R[n];
7139 if (index)
7140 address = offset_addr;
7141 else
7142 address = Rn;
7143
7144 // R[t] = SignExtend(MemU[address,1], 32);
7145 Register base_reg;
7146 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7147 Register offset_reg;
7148 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7149
7150 EmulateInstruction::Context context;
7151 context.type = eContextRegisterLoad;
7152 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7153
7154 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7155 if (!success)
7156 return false;
7157
7158 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7159 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7160 return false;
7161
7162 // if wback then R[n] = offset_addr;
7163 if (wback)
7164 {
7165 context.type = eContextAdjustBaseRegister;
7166 context.SetAddress (offset_addr);
7167 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7168 return false;
7169 }
7170 }
7171 return true;
7172}
7173
Caroline Tice78fb5632011-03-02 00:39:42 +00007174// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7175// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7176// pre-indexed addressing.
7177bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007178EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007179{
7180#if 0
7181 if ConditionPassed() then
7182 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7183 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7184 address = if index then offset_addr else R[n];
7185 data = MemU[address,2];
7186 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007187 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007188 R[t] = SignExtend(data, 32);
7189 else // Can only apply before ARMv7
7190 R[t] = bits(32) UNKNOWN;
7191#endif
7192
7193 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007194
Greg Clayton7bc39082011-03-24 23:53:38 +00007195 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007196 {
7197 uint32_t t;
7198 uint32_t n;
7199 uint32_t imm32;
7200 bool index;
7201 bool add;
7202 bool wback;
7203
7204 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7205 switch (encoding)
7206 {
7207 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007208 // if Rn == '1111' then SEE LDRSH (literal);
7209 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007210 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7211 t = Bits32 (opcode, 15, 12);
7212 n = Bits32 (opcode, 19, 16);
7213 imm32 = Bits32 (opcode, 11, 0);
7214
7215 // index = TRUE; add = TRUE; wback = FALSE;
7216 index = true;
7217 add = true;
7218 wback = false;
7219
7220 // if t == 13 then UNPREDICTABLE;
7221 if (t == 13)
7222 return false;
7223
7224 break;
7225
7226 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007227 // if Rn == '1111' then SEE LDRSH (literal);
7228 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7229 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7230 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007231 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7232 return false;
7233
7234 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7235 t = Bits32 (opcode, 15, 12);
7236 n = Bits32 (opcode, 19, 16);
7237 imm32 = Bits32 (opcode, 7, 0);
7238
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007239 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007240 index = BitIsSet (opcode, 10);
7241 add = BitIsSet (opcode, 9);
7242 wback = BitIsSet (opcode, 8);
7243
7244 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7245 if (BadReg (t) || (wback && (n == t)))
7246 return false;
7247
7248 break;
7249
7250 case eEncodingA1:
7251 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007252 // if Rn == '1111' then SEE LDRSH (literal);
7253 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007254 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7255 t = Bits32 (opcode, 15, 12);
7256 n = Bits32 (opcode, 19, 16);
7257 uint32_t imm4H = Bits32 (opcode, 11,8);
7258 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007259 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007260
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007261 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007262 index = BitIsSet (opcode, 24);
7263 add = BitIsSet (opcode, 23);
7264 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7265
7266 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7267 if ((t == 15) || (wback && (n == t)))
7268 return false;
7269
7270 break;
7271 }
7272
7273 default:
7274 return false;
7275 }
7276
7277 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7278 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7279 if (!success)
7280 return false;
7281
7282 addr_t offset_addr;
7283 if (add)
7284 offset_addr = Rn + imm32;
7285 else
7286 offset_addr = Rn - imm32;
7287
7288 // address = if index then offset_addr else R[n];
7289 addr_t address;
7290 if (index)
7291 address = offset_addr;
7292 else
7293 address = Rn;
7294
7295 // data = MemU[address,2];
7296 Register base_reg;
7297 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7298
7299 EmulateInstruction::Context context;
7300 context.type = eContextRegisterLoad;
7301 context.SetRegisterPlusOffset (base_reg, address - Rn);
7302
7303 uint64_t data = MemURead (context, address, 2, 0, &success);
7304 if (!success)
7305 return false;
7306
7307 // if wback then R[n] = offset_addr;
7308 if (wback)
7309 {
7310 context.type = eContextAdjustBaseRegister;
7311 context.SetAddress (offset_addr);
7312 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7313 return false;
7314 }
7315
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007316 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007317 if (UnalignedSupport() || BitIsClear (address, 0))
7318 {
7319 // R[t] = SignExtend(data, 32);
7320 int64_t signed_data = llvm::SignExtend64<16>(data);
7321 context.type = eContextRegisterLoad;
7322 context.SetRegisterPlusOffset (base_reg, address - Rn);
7323 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7324 return false;
7325 }
7326 else // Can only apply before ARMv7
7327 {
7328 // R[t] = bits(32) UNKNOWN;
7329 WriteBits32Unknown (t);
7330 }
7331 }
7332 return true;
7333}
7334
Caroline Ticed2fac092011-03-02 19:45:34 +00007335// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7336// sign-extends it to from a 32-bit word, and writes it to a register.
7337bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007338EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007339{
7340#if 0
7341 if ConditionPassed() then
7342 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7343 base = Align(PC,4);
7344 address = if add then (base + imm32) else (base - imm32);
7345 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007346 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007347 R[t] = SignExtend(data, 32);
7348 else // Can only apply before ARMv7
7349 R[t] = bits(32) UNKNOWN;
7350#endif
7351
7352 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007353
Greg Clayton7bc39082011-03-24 23:53:38 +00007354 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007355 {
7356 uint32_t t;
7357 uint32_t imm32;
7358 bool add;
7359
7360 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7361 switch (encoding)
7362 {
7363 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007364 // if Rt == '1111' then SEE "Unallocated memory hints";
7365 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007366 t = Bits32 (opcode, 15, 12);
7367 imm32 = Bits32 (opcode, 11, 0);
7368 add = BitIsSet (opcode, 23);
7369
7370 // if t == 13 then UNPREDICTABLE;
7371 if (t == 13)
7372 return false;
7373
7374 break;
7375
7376 case eEncodingA1:
7377 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007378 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007379 t = Bits32 (opcode, 15, 12);
7380 uint32_t imm4H = Bits32 (opcode, 11, 8);
7381 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007382 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007383 add = BitIsSet (opcode, 23);
7384
7385 // if t == 15 then UNPREDICTABLE;
7386 if (t == 15)
7387 return false;
7388
7389 break;
7390 }
7391 default:
7392 return false;
7393 }
7394
7395 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007396 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007397 if (!success)
7398 return false;
7399
7400 uint64_t base = AlignPC (pc_value);
7401
7402 addr_t address;
7403 // address = if add then (base + imm32) else (base - imm32);
7404 if (add)
7405 address = base + imm32;
7406 else
7407 address = base - imm32;
7408
7409 // data = MemU[address,2];
7410 Register base_reg;
7411 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7412
7413 EmulateInstruction::Context context;
7414 context.type = eContextRegisterLoad;
7415 context.SetRegisterPlusOffset (base_reg, imm32);
7416
7417 uint64_t data = MemURead (context, address, 2, 0, &success);
7418 if (!success)
7419 return false;
7420
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007421 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007422 if (UnalignedSupport() || BitIsClear (address, 0))
7423 {
7424 // R[t] = SignExtend(data, 32);
7425 int64_t signed_data = llvm::SignExtend64<16>(data);
7426 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7427 return false;
7428 }
7429 else // Can only apply before ARMv7
7430 {
7431 // R[t] = bits(32) UNKNOWN;
7432 WriteBits32Unknown (t);
7433 }
7434 }
7435 return true;
7436}
7437
Caroline Tice291a3e92011-03-02 21:13:44 +00007438// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7439// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7440// shifted left by 0, 1, 2, or 3 bits.
7441bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007442EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007443{
7444#if 0
7445 if ConditionPassed() then
7446 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7447 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7448 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7449 address = if index then offset_addr else R[n];
7450 data = MemU[address,2];
7451 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007452 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007453 R[t] = SignExtend(data, 32);
7454 else // Can only apply before ARMv7
7455 R[t] = bits(32) UNKNOWN;
7456#endif
7457
7458 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007459
Greg Clayton7bc39082011-03-24 23:53:38 +00007460 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007461 {
7462 uint32_t t;
7463 uint32_t n;
7464 uint32_t m;
7465 bool index;
7466 bool add;
7467 bool wback;
7468 ARM_ShifterType shift_t;
7469 uint32_t shift_n;
7470
7471 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7472 switch (encoding)
7473 {
7474 case eEncodingT1:
7475 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7476 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7477 t = Bits32 (opcode, 2, 0);
7478 n = Bits32 (opcode, 5, 3);
7479 m = Bits32 (opcode, 8, 6);
7480
7481 // index = TRUE; add = TRUE; wback = FALSE;
7482 index = true;
7483 add = true;
7484 wback = false;
7485
7486 // (shift_t, shift_n) = (SRType_LSL, 0);
7487 shift_t = SRType_LSL;
7488 shift_n = 0;
7489
7490 break;
7491
7492 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007493 // if Rn == '1111' then SEE LDRSH (literal);
7494 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007495 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7496 t = Bits32 (opcode, 15, 12);
7497 n = Bits32 (opcode, 19, 16);
7498 m = Bits32 (opcode, 3, 0);
7499
7500 // index = TRUE; add = TRUE; wback = FALSE;
7501 index = true;
7502 add = true;
7503 wback = false;
7504
7505 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7506 shift_t = SRType_LSL;
7507 shift_n = Bits32 (opcode, 5, 4);
7508
7509 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7510 if ((t == 13) || BadReg (m))
7511 return false;
7512
7513 break;
7514
7515 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007516 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007517 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7518 t = Bits32 (opcode, 15, 12);
7519 n = Bits32 (opcode, 19, 16);
7520 m = Bits32 (opcode, 3, 0);
7521
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007522 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007523 index = BitIsSet (opcode, 24);
7524 add = BitIsSet (opcode, 23);
7525 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7526
7527 // (shift_t, shift_n) = (SRType_LSL, 0);
7528 shift_t = SRType_LSL;
7529 shift_n = 0;
7530
7531 // if t == 15 || m == 15 then UNPREDICTABLE;
7532 if ((t == 15) || (m == 15))
7533 return false;
7534
7535 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7536 if (wback && ((n == 15) || (n == t)))
7537 return false;
7538
7539 break;
7540
7541 default:
7542 break;
7543 }
7544
7545 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7546 if (!success)
7547 return false;
7548
7549 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7550 if (!success)
7551 return false;
7552
7553 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7554 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7555
7556 addr_t offset_addr;
7557 addr_t address;
7558
7559 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7560 if (add)
7561 offset_addr = Rn + offset;
7562 else
7563 offset_addr = Rn - offset;
7564
7565 // address = if index then offset_addr else R[n];
7566 if (index)
7567 address = offset_addr;
7568 else
7569 address = Rn;
7570
7571 // data = MemU[address,2];
7572 Register base_reg;
7573 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7574
7575 Register offset_reg;
7576 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7577
7578 EmulateInstruction::Context context;
7579 context.type = eContextRegisterLoad;
7580 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7581
7582 uint64_t data = MemURead (context, address, 2, 0, &success);
7583 if (!success)
7584 return false;
7585
7586 // if wback then R[n] = offset_addr;
7587 if (wback)
7588 {
7589 context.type = eContextAdjustBaseRegister;
7590 context.SetAddress (offset_addr);
7591 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7592 return false;
7593 }
7594
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007595 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007596 if (UnalignedSupport() || BitIsClear (address, 0))
7597 {
7598 // R[t] = SignExtend(data, 32);
7599 context.type = eContextRegisterLoad;
7600 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7601
7602 int64_t signed_data = llvm::SignExtend64<16>(data);
7603 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7604 return false;
7605 }
7606 else // Can only apply before ARMv7
7607 {
7608 // R[t] = bits(32) UNKNOWN;
7609 WriteBits32Unknown (t);
7610 }
7611 }
7612 return true;
7613}
Caroline Tice6bf65162011-03-03 17:42:58 +00007614
7615// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7616// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7617bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007618EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007619{
7620#if 0
7621 if ConditionPassed() then
7622 EncodingSpecificOperations();
7623 rotated = ROR(R[m], rotation);
7624 R[d] = SignExtend(rotated<7:0>, 32);
7625#endif
7626
7627 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007628
Greg Clayton7bc39082011-03-24 23:53:38 +00007629 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007630 {
7631 uint32_t d;
7632 uint32_t m;
7633 uint32_t rotation;
7634
7635 // EncodingSpecificOperations();
7636 switch (encoding)
7637 {
7638 case eEncodingT1:
7639 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7640 d = Bits32 (opcode, 2, 0);
7641 m = Bits32 (opcode, 5, 3);
7642 rotation = 0;
7643
7644 break;
7645
7646 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007647 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007648 d = Bits32 (opcode, 11, 8);
7649 m = Bits32 (opcode, 3, 0);
7650 rotation = Bits32 (opcode, 5, 4) << 3;
7651
7652 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7653 if (BadReg (d) || BadReg (m))
7654 return false;
7655
7656 break;
7657
7658 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007659 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007660 d = Bits32 (opcode, 15, 12);
7661 m = Bits32 (opcode, 3, 0);
7662 rotation = Bits32 (opcode, 11, 10) << 3;
7663
7664 // if d == 15 || m == 15 then UNPREDICTABLE;
7665 if ((d == 15) || (m == 15))
7666 return false;
7667
7668 break;
7669
7670 default:
7671 return false;
7672 }
7673
Caroline Tice868198b2011-03-03 18:04:49 +00007674 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7675 if (!success)
7676 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007677
7678 // rotated = ROR(R[m], rotation);
7679 uint64_t rotated = ROR (Rm, rotation);
7680
7681 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007682 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007683
7684 Register source_reg;
7685 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7686
7687 EmulateInstruction::Context context;
7688 context.type = eContextRegisterLoad;
7689 context.SetRegister (source_reg);
7690
Caroline Tice8ce96d92011-03-03 18:27:17 +00007691 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007692 return false;
7693 }
7694 return true;
7695}
Caroline Tice291a3e92011-03-02 21:13:44 +00007696
Caroline Tice868198b2011-03-03 18:04:49 +00007697// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7698// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7699bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007700EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007701{
7702#if 0
7703 if ConditionPassed() then
7704 EncodingSpecificOperations();
7705 rotated = ROR(R[m], rotation);
7706 R[d] = SignExtend(rotated<15:0>, 32);
7707#endif
7708
7709 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007710
Greg Clayton7bc39082011-03-24 23:53:38 +00007711 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007712 {
7713 uint32_t d;
7714 uint32_t m;
7715 uint32_t rotation;
7716
7717 // EncodingSpecificOperations();
7718 switch (encoding)
7719 {
7720 case eEncodingT1:
7721 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7722 d = Bits32 (opcode, 2, 0);
7723 m = Bits32 (opcode, 5, 3);
7724 rotation = 0;
7725
7726 break;
7727
7728 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007729 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007730 d = Bits32 (opcode, 11, 8);
7731 m = Bits32 (opcode, 3, 0);
7732 rotation = Bits32 (opcode, 5, 4) << 3;
7733
7734 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7735 if (BadReg (d) || BadReg (m))
7736 return false;
7737
7738 break;
7739
7740 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007741 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007742 d = Bits32 (opcode, 15, 12);
7743 m = Bits32 (opcode, 3, 0);
7744 rotation = Bits32 (opcode, 11, 10) << 3;
7745
7746 // if d == 15 || m == 15 then UNPREDICTABLE;
7747 if ((d == 15) || (m == 15))
7748 return false;
7749
7750 break;
7751
7752 default:
7753 return false;
7754 }
7755
7756 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7757 if (!success)
7758 return false;
7759
7760 // rotated = ROR(R[m], rotation);
7761 uint64_t rotated = ROR (Rm, rotation);
7762
7763 // R[d] = SignExtend(rotated<15:0>, 32);
7764 Register source_reg;
7765 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7766
7767 EmulateInstruction::Context context;
7768 context.type = eContextRegisterLoad;
7769 context.SetRegister (source_reg);
7770
Caroline Tice8ce96d92011-03-03 18:27:17 +00007771 int64_t data = llvm::SignExtend64<16> (rotated);
7772 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007773 return false;
7774 }
7775
7776 return true;
7777}
7778
Caroline Tice8ce96d92011-03-03 18:27:17 +00007779// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7780// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7781bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007782EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007783{
7784#if 0
7785 if ConditionPassed() then
7786 EncodingSpecificOperations();
7787 rotated = ROR(R[m], rotation);
7788 R[d] = ZeroExtend(rotated<7:0>, 32);
7789#endif
7790
7791 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007792
Greg Clayton7bc39082011-03-24 23:53:38 +00007793 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007794 {
7795 uint32_t d;
7796 uint32_t m;
7797 uint32_t rotation;
7798
7799 // EncodingSpecificOperations();
7800 switch (encoding)
7801 {
7802 case eEncodingT1:
7803 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7804 d = Bits32 (opcode, 2, 0);
7805 m = Bits32 (opcode, 5, 3);
7806 rotation = 0;
7807
7808 break;
7809
7810 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007811 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007812 d = Bits32 (opcode, 11, 8);
7813 m = Bits32 (opcode, 3, 0);
7814 rotation = Bits32 (opcode, 5, 4) << 3;
7815
7816 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7817 if (BadReg (d) || BadReg (m))
7818 return false;
7819
7820 break;
7821
7822 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007823 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007824 d = Bits32 (opcode, 15, 12);
7825 m = Bits32 (opcode, 3, 0);
7826 rotation = Bits32 (opcode, 11, 10) << 3;
7827
7828 // if d == 15 || m == 15 then UNPREDICTABLE;
7829 if ((d == 15) || (m == 15))
7830 return false;
7831
7832 break;
7833
7834 default:
7835 return false;
7836 }
7837
7838 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7839 if (!success)
7840 return false;
7841
7842 // rotated = ROR(R[m], rotation);
7843 uint64_t rotated = ROR (Rm, rotation);
7844
7845 // R[d] = ZeroExtend(rotated<7:0>, 32);
7846 Register source_reg;
7847 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7848
7849 EmulateInstruction::Context context;
7850 context.type = eContextRegisterLoad;
7851 context.SetRegister (source_reg);
7852
7853 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7854 return false;
7855 }
7856 return true;
7857}
7858
Caroline Tice11555f22011-03-03 18:48:58 +00007859// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7860// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7861bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007862EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007863{
7864#if 0
7865 if ConditionPassed() then
7866 EncodingSpecificOperations();
7867 rotated = ROR(R[m], rotation);
7868 R[d] = ZeroExtend(rotated<15:0>, 32);
7869#endif
7870
7871 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007872
Greg Clayton7bc39082011-03-24 23:53:38 +00007873 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007874 {
7875 uint32_t d;
7876 uint32_t m;
7877 uint32_t rotation;
7878
7879 switch (encoding)
7880 {
7881 case eEncodingT1:
7882 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7883 d = Bits32 (opcode, 2, 0);
7884 m = Bits32 (opcode, 5, 3);
7885 rotation = 0;
7886
7887 break;
7888
7889 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007890 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007891 d = Bits32 (opcode, 11, 8);
7892 m = Bits32 (opcode, 3, 0);
7893 rotation = Bits32 (opcode, 5, 4) << 3;
7894
7895 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7896 if (BadReg (d) || BadReg (m))
7897 return false;
7898
7899 break;
7900
7901 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007902 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007903 d = Bits32 (opcode, 15, 12);
7904 m = Bits32 (opcode, 3, 0);
7905 rotation = Bits32 (opcode, 11, 10) << 3;
7906
7907 // if d == 15 || m == 15 then UNPREDICTABLE;
7908 if ((d == 15) || (m == 15))
7909 return false;
7910
7911 break;
7912
7913 default:
7914 return false;
7915 }
7916
7917 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7918 if (!success)
7919 return false;
7920
7921 // rotated = ROR(R[m], rotation);
7922 uint64_t rotated = ROR (Rm, rotation);
7923
7924 // R[d] = ZeroExtend(rotated<15:0>, 32);
7925 Register source_reg;
7926 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7927
7928 EmulateInstruction::Context context;
7929 context.type = eContextRegisterLoad;
7930 context.SetRegister (source_reg);
7931
7932 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7933 return false;
7934 }
7935 return true;
7936}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007937
7938// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7939// word respectively.
7940bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007941EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007942{
7943#if 0
7944 if ConditionPassed() then
7945 EncodingSpecificOperations();
7946 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7947 UNPREDICTABLE;
7948 else
7949 address = if increment then R[n] else R[n]-8;
7950 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007951 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007952 BranchWritePC(MemA[address,4]);
7953 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7954#endif
7955
7956 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007957
Greg Clayton7bc39082011-03-24 23:53:38 +00007958 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007959 {
7960 uint32_t n;
7961 bool wback;
7962 bool increment;
7963 bool wordhigher;
7964
7965 // EncodingSpecificOperations();
7966 switch (encoding)
7967 {
7968 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007969 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007970 n = Bits32 (opcode, 19, 16);
7971 wback = BitIsSet (opcode, 21);
7972 increment = false;
7973 wordhigher = false;
7974
7975 // if n == 15 then UNPREDICTABLE;
7976 if (n == 15)
7977 return false;
7978
7979 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7980 if (InITBlock() && !LastInITBlock())
7981 return false;
7982
7983 break;
7984
7985 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007986 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007987 n = Bits32 (opcode, 19, 16);
7988 wback = BitIsSet (opcode, 21);
7989 increment = true;
7990 wordhigher = false;
7991
7992 // if n == 15 then UNPREDICTABLE;
7993 if (n == 15)
7994 return false;
7995
7996 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7997 if (InITBlock() && !LastInITBlock())
7998 return false;
7999
8000 break;
8001
8002 case eEncodingA1:
8003 // n = UInt(Rn);
8004 n = Bits32 (opcode, 19, 16);
8005
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008006 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008007 wback = BitIsSet (opcode, 21);
8008 increment = BitIsSet (opcode, 23);
8009 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8010
8011 // if n == 15 then UNPREDICTABLE;
8012 if (n == 15)
8013 return false;
8014
8015 break;
8016
8017 default:
8018 return false;
8019 }
8020
8021 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8022 if (!CurrentModeIsPrivileged ())
8023 // UNPREDICTABLE;
8024 return false;
8025 else
8026 {
8027 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8028 if (!success)
8029 return false;
8030
8031 addr_t address;
8032 // address = if increment then R[n] else R[n]-8;
8033 if (increment)
8034 address = Rn;
8035 else
8036 address = Rn - 8;
8037
8038 // if wordhigher then address = address+4;
8039 if (wordhigher)
8040 address = address + 4;
8041
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008042 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008043 Register base_reg;
8044 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8045
8046 EmulateInstruction::Context context;
8047 context.type = eContextReturnFromException;
8048 context.SetRegisterPlusOffset (base_reg, address - Rn);
8049
8050 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8051 if (!success)
8052 return false;
8053
8054 CPSRWriteByInstr (data, 15, true);
8055
8056 // BranchWritePC(MemA[address,4]);
8057 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8058 if (!success)
8059 return false;
8060
8061 BranchWritePC (context, data2);
8062
8063 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8064 if (wback)
8065 {
8066 context.type = eContextAdjustBaseRegister;
8067 if (increment)
8068 {
8069 context.SetOffset (8);
8070 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8071 return false;
8072 }
8073 else
8074 {
8075 context.SetOffset (-8);
8076 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8077 return false;
8078 }
8079 } // if wback
8080 }
8081 } // if ConditionPassed()
8082 return true;
8083}
Caroline Tice11555f22011-03-03 18:48:58 +00008084
Johnny Chen2115b412011-02-21 23:42:44 +00008085// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8086// and writes the result to the destination register. It can optionally update the condition flags based on
8087// the result.
8088bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008089EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008090{
8091#if 0
8092 // ARM pseudo code...
8093 if ConditionPassed() then
8094 EncodingSpecificOperations();
8095 result = R[n] EOR imm32;
8096 if d == 15 then // Can only occur for ARM encoding
8097 ALUWritePC(result); // setflags is always FALSE here
8098 else
8099 R[d] = result;
8100 if setflags then
8101 APSR.N = result<31>;
8102 APSR.Z = IsZeroBit(result);
8103 APSR.C = carry;
8104 // APSR.V unchanged
8105#endif
8106
8107 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008108
Greg Clayton7bc39082011-03-24 23:53:38 +00008109 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008110 {
8111 uint32_t Rd, Rn;
8112 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8113 bool setflags;
8114 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8115 switch (encoding)
8116 {
8117 case eEncodingT1:
8118 Rd = Bits32(opcode, 11, 8);
8119 Rn = Bits32(opcode, 19, 16);
8120 setflags = BitIsSet(opcode, 20);
8121 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8122 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8123 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008124 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008125 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8126 return false;
8127 break;
8128 case eEncodingA1:
8129 Rd = Bits32(opcode, 15, 12);
8130 Rn = Bits32(opcode, 19, 16);
8131 setflags = BitIsSet(opcode, 20);
8132 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008133
Johnny Chen2115b412011-02-21 23:42:44 +00008134 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008135 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008136 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008137 break;
8138 default:
8139 return false;
8140 }
8141
8142 // Read the first operand.
8143 uint32_t val1 = ReadCoreReg(Rn, &success);
8144 if (!success)
8145 return false;
8146
8147 uint32_t result = val1 ^ imm32;
8148
8149 EmulateInstruction::Context context;
8150 context.type = EmulateInstruction::eContextImmediate;
8151 context.SetNoArgs ();
8152
8153 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8154 return false;
8155 }
8156 return true;
8157}
8158
8159// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8160// optionally-shifted register value, and writes the result to the destination register.
8161// It can optionally update the condition flags based on the result.
8162bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008163EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008164{
8165#if 0
8166 // ARM pseudo code...
8167 if ConditionPassed() then
8168 EncodingSpecificOperations();
8169 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8170 result = R[n] EOR shifted;
8171 if d == 15 then // Can only occur for ARM encoding
8172 ALUWritePC(result); // setflags is always FALSE here
8173 else
8174 R[d] = result;
8175 if setflags then
8176 APSR.N = result<31>;
8177 APSR.Z = IsZeroBit(result);
8178 APSR.C = carry;
8179 // APSR.V unchanged
8180#endif
8181
8182 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008183
Greg Clayton7bc39082011-03-24 23:53:38 +00008184 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008185 {
8186 uint32_t Rd, Rn, Rm;
8187 ARM_ShifterType shift_t;
8188 uint32_t shift_n; // the shift applied to the value read from Rm
8189 bool setflags;
8190 uint32_t carry;
8191 switch (encoding)
8192 {
8193 case eEncodingT1:
8194 Rd = Rn = Bits32(opcode, 2, 0);
8195 Rm = Bits32(opcode, 5, 3);
8196 setflags = !InITBlock();
8197 shift_t = SRType_LSL;
8198 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008199 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008200 case eEncodingT2:
8201 Rd = Bits32(opcode, 11, 8);
8202 Rn = Bits32(opcode, 19, 16);
8203 Rm = Bits32(opcode, 3, 0);
8204 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008205 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8206 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008207 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008208 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008209 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8210 return false;
8211 break;
8212 case eEncodingA1:
8213 Rd = Bits32(opcode, 15, 12);
8214 Rn = Bits32(opcode, 19, 16);
8215 Rm = Bits32(opcode, 3, 0);
8216 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008217 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008218
Johnny Chen2115b412011-02-21 23:42:44 +00008219 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008220 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008221 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008222 break;
8223 default:
8224 return false;
8225 }
8226
8227 // Read the first operand.
8228 uint32_t val1 = ReadCoreReg(Rn, &success);
8229 if (!success)
8230 return false;
8231
8232 // Read the second operand.
8233 uint32_t val2 = ReadCoreReg(Rm, &success);
8234 if (!success)
8235 return false;
8236
8237 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8238 uint32_t result = val1 ^ shifted;
8239
8240 EmulateInstruction::Context context;
8241 context.type = EmulateInstruction::eContextImmediate;
8242 context.SetNoArgs ();
8243
8244 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8245 return false;
8246 }
8247 return true;
8248}
8249
Johnny Chen7c5234d2011-02-18 23:41:11 +00008250// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8251// writes the result to the destination register. It can optionally update the condition flags based
8252// on the result.
8253bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008254EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008255{
8256#if 0
8257 // ARM pseudo code...
8258 if ConditionPassed() then
8259 EncodingSpecificOperations();
8260 result = R[n] OR imm32;
8261 if d == 15 then // Can only occur for ARM encoding
8262 ALUWritePC(result); // setflags is always FALSE here
8263 else
8264 R[d] = result;
8265 if setflags then
8266 APSR.N = result<31>;
8267 APSR.Z = IsZeroBit(result);
8268 APSR.C = carry;
8269 // APSR.V unchanged
8270#endif
8271
8272 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008273
Greg Clayton7bc39082011-03-24 23:53:38 +00008274 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008275 {
8276 uint32_t Rd, Rn;
8277 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8278 bool setflags;
8279 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8280 switch (encoding)
8281 {
8282 case eEncodingT1:
8283 Rd = Bits32(opcode, 11, 8);
8284 Rn = Bits32(opcode, 19, 16);
8285 setflags = BitIsSet(opcode, 20);
8286 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008287 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008288 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008289 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008290 if (BadReg(Rd) || Rn == 13)
8291 return false;
8292 break;
8293 case eEncodingA1:
8294 Rd = Bits32(opcode, 15, 12);
8295 Rn = Bits32(opcode, 19, 16);
8296 setflags = BitIsSet(opcode, 20);
8297 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008298
Johnny Chen7c5234d2011-02-18 23:41:11 +00008299 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008300 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008301 break;
8302 default:
8303 return false;
8304 }
8305
8306 // Read the first operand.
8307 uint32_t val1 = ReadCoreReg(Rn, &success);
8308 if (!success)
8309 return false;
8310
8311 uint32_t result = val1 | imm32;
8312
8313 EmulateInstruction::Context context;
8314 context.type = EmulateInstruction::eContextImmediate;
8315 context.SetNoArgs ();
8316
8317 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8318 return false;
8319 }
8320 return true;
8321}
8322
8323// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8324// value, and writes the result to the destination register. It can optionally update the condition flags based
8325// on the result.
8326bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008327EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008328{
8329#if 0
8330 // ARM pseudo code...
8331 if ConditionPassed() then
8332 EncodingSpecificOperations();
8333 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8334 result = R[n] OR shifted;
8335 if d == 15 then // Can only occur for ARM encoding
8336 ALUWritePC(result); // setflags is always FALSE here
8337 else
8338 R[d] = result;
8339 if setflags then
8340 APSR.N = result<31>;
8341 APSR.Z = IsZeroBit(result);
8342 APSR.C = carry;
8343 // APSR.V unchanged
8344#endif
8345
8346 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008347
Greg Clayton7bc39082011-03-24 23:53:38 +00008348 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008349 {
8350 uint32_t Rd, Rn, Rm;
8351 ARM_ShifterType shift_t;
8352 uint32_t shift_n; // the shift applied to the value read from Rm
8353 bool setflags;
8354 uint32_t carry;
8355 switch (encoding)
8356 {
8357 case eEncodingT1:
8358 Rd = Rn = Bits32(opcode, 2, 0);
8359 Rm = Bits32(opcode, 5, 3);
8360 setflags = !InITBlock();
8361 shift_t = SRType_LSL;
8362 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008363 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008364 case eEncodingT2:
8365 Rd = Bits32(opcode, 11, 8);
8366 Rn = Bits32(opcode, 19, 16);
8367 Rm = Bits32(opcode, 3, 0);
8368 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008369 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8370 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008371 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008372 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008373 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8374 return false;
8375 break;
8376 case eEncodingA1:
8377 Rd = Bits32(opcode, 15, 12);
8378 Rn = Bits32(opcode, 19, 16);
8379 Rm = Bits32(opcode, 3, 0);
8380 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008381 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008382
Johnny Chen7c5234d2011-02-18 23:41:11 +00008383 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008384 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008385 break;
8386 default:
8387 return false;
8388 }
8389
8390 // Read the first operand.
8391 uint32_t val1 = ReadCoreReg(Rn, &success);
8392 if (!success)
8393 return false;
8394
8395 // Read the second operand.
8396 uint32_t val2 = ReadCoreReg(Rm, &success);
8397 if (!success)
8398 return false;
8399
8400 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008401 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008402
8403 EmulateInstruction::Context context;
8404 context.type = EmulateInstruction::eContextImmediate;
8405 context.SetNoArgs ();
8406
8407 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8408 return false;
8409 }
8410 return true;
8411}
8412
Johnny Chened32e7c2011-02-22 23:42:58 +00008413// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8414// the destination register. It can optionally update the condition flags based on the result.
8415bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008416EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008417{
8418#if 0
8419 // ARM pseudo code...
8420 if ConditionPassed() then
8421 EncodingSpecificOperations();
8422 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8423 if d == 15 then // Can only occur for ARM encoding
8424 ALUWritePC(result); // setflags is always FALSE here
8425 else
8426 R[d] = result;
8427 if setflags then
8428 APSR.N = result<31>;
8429 APSR.Z = IsZeroBit(result);
8430 APSR.C = carry;
8431 APSR.V = overflow;
8432#endif
8433
8434 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008435
8436 uint32_t Rd; // the destination register
8437 uint32_t Rn; // the first operand
8438 bool setflags;
8439 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8440 switch (encoding) {
8441 case eEncodingT1:
8442 Rd = Bits32(opcode, 2, 0);
8443 Rn = Bits32(opcode, 5, 3);
8444 setflags = !InITBlock();
8445 imm32 = 0;
8446 break;
8447 case eEncodingT2:
8448 Rd = Bits32(opcode, 11, 8);
8449 Rn = Bits32(opcode, 19, 16);
8450 setflags = BitIsSet(opcode, 20);
8451 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8452 if (BadReg(Rd) || BadReg(Rn))
8453 return false;
8454 break;
8455 case eEncodingA1:
8456 Rd = Bits32(opcode, 15, 12);
8457 Rn = Bits32(opcode, 19, 16);
8458 setflags = BitIsSet(opcode, 20);
8459 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008460
Johnny Chened32e7c2011-02-22 23:42:58 +00008461 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008462 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008463 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008464 break;
8465 default:
8466 return false;
8467 }
8468 // Read the register value from the operand register Rn.
8469 uint32_t reg_val = ReadCoreReg(Rn, &success);
8470 if (!success)
8471 return false;
8472
8473 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8474
8475 EmulateInstruction::Context context;
8476 context.type = EmulateInstruction::eContextImmediate;
8477 context.SetNoArgs ();
8478
8479 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8480 return false;
8481
8482 return true;
8483}
8484
8485// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8486// result to the destination register. It can optionally update the condition flags based on the result.
8487bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008488EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008489{
8490#if 0
8491 // ARM pseudo code...
8492 if ConditionPassed() then
8493 EncodingSpecificOperations();
8494 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8495 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8496 if d == 15 then // Can only occur for ARM encoding
8497 ALUWritePC(result); // setflags is always FALSE here
8498 else
8499 R[d] = result;
8500 if setflags then
8501 APSR.N = result<31>;
8502 APSR.Z = IsZeroBit(result);
8503 APSR.C = carry;
8504 APSR.V = overflow;
8505#endif
8506
8507 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008508
8509 uint32_t Rd; // the destination register
8510 uint32_t Rn; // the first operand
8511 uint32_t Rm; // the second operand
8512 bool setflags;
8513 ARM_ShifterType shift_t;
8514 uint32_t shift_n; // the shift applied to the value read from Rm
8515 switch (encoding) {
8516 case eEncodingT1:
8517 Rd = Bits32(opcode, 11, 8);
8518 Rn = Bits32(opcode, 19, 16);
8519 Rm = Bits32(opcode, 3, 0);
8520 setflags = BitIsSet(opcode, 20);
8521 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8522 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8523 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8524 return false;
8525 break;
8526 case eEncodingA1:
8527 Rd = Bits32(opcode, 15, 12);
8528 Rn = Bits32(opcode, 19, 16);
8529 Rm = Bits32(opcode, 3, 0);
8530 setflags = BitIsSet(opcode, 20);
8531 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008532
Johnny Chened32e7c2011-02-22 23:42:58 +00008533 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008534 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008535 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008536 break;
8537 default:
8538 return false;
8539 }
8540 // Read the register value from register Rn.
8541 uint32_t val1 = ReadCoreReg(Rn, &success);
8542 if (!success)
8543 return false;
8544
8545 // Read the register value from register Rm.
8546 uint32_t val2 = ReadCoreReg(Rm, &success);
8547 if (!success)
8548 return false;
8549
8550 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8551 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8552
8553 EmulateInstruction::Context context;
8554 context.type = EmulateInstruction::eContextImmediate;
8555 context.SetNoArgs();
8556 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8557 return false;
8558
8559 return true;
8560}
8561
Johnny Chen90e607b2011-02-23 00:07:09 +00008562// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8563// an immediate value, and writes the result to the destination register. It can optionally update the condition
8564// flags based on the result.
8565bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008566EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008567{
8568#if 0
8569 // ARM pseudo code...
8570 if ConditionPassed() then
8571 EncodingSpecificOperations();
8572 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8573 if d == 15 then
8574 ALUWritePC(result); // setflags is always FALSE here
8575 else
8576 R[d] = result;
8577 if setflags then
8578 APSR.N = result<31>;
8579 APSR.Z = IsZeroBit(result);
8580 APSR.C = carry;
8581 APSR.V = overflow;
8582#endif
8583
8584 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008585
8586 uint32_t Rd; // the destination register
8587 uint32_t Rn; // the first operand
8588 bool setflags;
8589 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8590 switch (encoding) {
8591 case eEncodingA1:
8592 Rd = Bits32(opcode, 15, 12);
8593 Rn = Bits32(opcode, 19, 16);
8594 setflags = BitIsSet(opcode, 20);
8595 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008596
Johnny Chen90e607b2011-02-23 00:07:09 +00008597 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008598 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008599 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008600 break;
8601 default:
8602 return false;
8603 }
8604 // Read the register value from the operand register Rn.
8605 uint32_t reg_val = ReadCoreReg(Rn, &success);
8606 if (!success)
8607 return false;
8608
8609 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8610
8611 EmulateInstruction::Context context;
8612 context.type = EmulateInstruction::eContextImmediate;
8613 context.SetNoArgs ();
8614
8615 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8616 return false;
8617
8618 return true;
8619}
8620
8621// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8622// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8623// condition flags based on the result.
8624bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008625EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008626{
8627#if 0
8628 // ARM pseudo code...
8629 if ConditionPassed() then
8630 EncodingSpecificOperations();
8631 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8632 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8633 if d == 15 then
8634 ALUWritePC(result); // setflags is always FALSE here
8635 else
8636 R[d] = result;
8637 if setflags then
8638 APSR.N = result<31>;
8639 APSR.Z = IsZeroBit(result);
8640 APSR.C = carry;
8641 APSR.V = overflow;
8642#endif
8643
8644 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008645
8646 uint32_t Rd; // the destination register
8647 uint32_t Rn; // the first operand
8648 uint32_t Rm; // the second operand
8649 bool setflags;
8650 ARM_ShifterType shift_t;
8651 uint32_t shift_n; // the shift applied to the value read from Rm
8652 switch (encoding) {
8653 case eEncodingA1:
8654 Rd = Bits32(opcode, 15, 12);
8655 Rn = Bits32(opcode, 19, 16);
8656 Rm = Bits32(opcode, 3, 0);
8657 setflags = BitIsSet(opcode, 20);
8658 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008659
Johnny Chen90e607b2011-02-23 00:07:09 +00008660 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008661 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008662 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008663 break;
8664 default:
8665 return false;
8666 }
8667 // Read the register value from register Rn.
8668 uint32_t val1 = ReadCoreReg(Rn, &success);
8669 if (!success)
8670 return false;
8671
8672 // Read the register value from register Rm.
8673 uint32_t val2 = ReadCoreReg(Rm, &success);
8674 if (!success)
8675 return false;
8676
8677 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8678 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8679
8680 EmulateInstruction::Context context;
8681 context.type = EmulateInstruction::eContextImmediate;
8682 context.SetNoArgs();
8683 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8684 return false;
8685
8686 return true;
8687}
8688
Johnny Chen9b381772011-02-23 01:01:21 +00008689// Subtract with Carry (immediate) subtracts an immediate value and the value of
8690// NOT (Carry flag) from a register value, and writes the result to the destination register.
8691// It can optionally update the condition flags based on the result.
8692bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008693EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008694{
8695#if 0
8696 // ARM pseudo code...
8697 if ConditionPassed() then
8698 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008699 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008700 if d == 15 then // Can only occur for ARM encoding
8701 ALUWritePC(result); // setflags is always FALSE here
8702 else
8703 R[d] = result;
8704 if setflags then
8705 APSR.N = result<31>;
8706 APSR.Z = IsZeroBit(result);
8707 APSR.C = carry;
8708 APSR.V = overflow;
8709#endif
8710
8711 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008712
8713 uint32_t Rd; // the destination register
8714 uint32_t Rn; // the first operand
8715 bool setflags;
8716 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8717 switch (encoding) {
8718 case eEncodingT1:
8719 Rd = Bits32(opcode, 11, 8);
8720 Rn = Bits32(opcode, 19, 16);
8721 setflags = BitIsSet(opcode, 20);
8722 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8723 if (BadReg(Rd) || BadReg(Rn))
8724 return false;
8725 break;
8726 case eEncodingA1:
8727 Rd = Bits32(opcode, 15, 12);
8728 Rn = Bits32(opcode, 19, 16);
8729 setflags = BitIsSet(opcode, 20);
8730 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008731
Johnny Chen9b381772011-02-23 01:01:21 +00008732 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008733 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008734 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008735 break;
8736 default:
8737 return false;
8738 }
8739 // Read the register value from the operand register Rn.
8740 uint32_t reg_val = ReadCoreReg(Rn, &success);
8741 if (!success)
8742 return false;
8743
8744 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8745
8746 EmulateInstruction::Context context;
8747 context.type = EmulateInstruction::eContextImmediate;
8748 context.SetNoArgs ();
8749
8750 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8751 return false;
8752
8753 return true;
8754}
8755
8756// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8757// NOT (Carry flag) from a register value, and writes the result to the destination register.
8758// It can optionally update the condition flags based on the result.
8759bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008760EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008761{
8762#if 0
8763 // ARM pseudo code...
8764 if ConditionPassed() then
8765 EncodingSpecificOperations();
8766 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8767 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8768 if d == 15 then // Can only occur for ARM encoding
8769 ALUWritePC(result); // setflags is always FALSE here
8770 else
8771 R[d] = result;
8772 if setflags then
8773 APSR.N = result<31>;
8774 APSR.Z = IsZeroBit(result);
8775 APSR.C = carry;
8776 APSR.V = overflow;
8777#endif
8778
8779 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008780
8781 uint32_t Rd; // the destination register
8782 uint32_t Rn; // the first operand
8783 uint32_t Rm; // the second operand
8784 bool setflags;
8785 ARM_ShifterType shift_t;
8786 uint32_t shift_n; // the shift applied to the value read from Rm
8787 switch (encoding) {
8788 case eEncodingT1:
8789 Rd = Rn = Bits32(opcode, 2, 0);
8790 Rm = Bits32(opcode, 5, 3);
8791 setflags = !InITBlock();
8792 shift_t = SRType_LSL;
8793 shift_n = 0;
8794 break;
8795 case eEncodingT2:
8796 Rd = Bits32(opcode, 11, 8);
8797 Rn = Bits32(opcode, 19, 16);
8798 Rm = Bits32(opcode, 3, 0);
8799 setflags = BitIsSet(opcode, 20);
8800 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8801 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8802 return false;
8803 break;
8804 case eEncodingA1:
8805 Rd = Bits32(opcode, 15, 12);
8806 Rn = Bits32(opcode, 19, 16);
8807 Rm = Bits32(opcode, 3, 0);
8808 setflags = BitIsSet(opcode, 20);
8809 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008810
Johnny Chen9b381772011-02-23 01:01:21 +00008811 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008812 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008813 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008814 break;
8815 default:
8816 return false;
8817 }
8818 // Read the register value from register Rn.
8819 uint32_t val1 = ReadCoreReg(Rn, &success);
8820 if (!success)
8821 return false;
8822
8823 // Read the register value from register Rm.
8824 uint32_t val2 = ReadCoreReg(Rm, &success);
8825 if (!success)
8826 return false;
8827
8828 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8829 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8830
8831 EmulateInstruction::Context context;
8832 context.type = EmulateInstruction::eContextImmediate;
8833 context.SetNoArgs();
8834 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8835 return false;
8836
8837 return true;
8838}
8839
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008840// This instruction subtracts an immediate value from a register value, and writes the result
8841// to the destination register. It can optionally update the condition flags based on the result.
8842bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008843EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008844{
8845#if 0
8846 // ARM pseudo code...
8847 if ConditionPassed() then
8848 EncodingSpecificOperations();
8849 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8850 R[d] = result;
8851 if setflags then
8852 APSR.N = result<31>;
8853 APSR.Z = IsZeroBit(result);
8854 APSR.C = carry;
8855 APSR.V = overflow;
8856#endif
8857
8858 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008859
8860 uint32_t Rd; // the destination register
8861 uint32_t Rn; // the first operand
8862 bool setflags;
8863 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8864 switch (encoding) {
8865 case eEncodingT1:
8866 Rd = Bits32(opcode, 2, 0);
8867 Rn = Bits32(opcode, 5, 3);
8868 setflags = !InITBlock();
8869 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8870 break;
8871 case eEncodingT2:
8872 Rd = Rn = Bits32(opcode, 10, 8);
8873 setflags = !InITBlock();
8874 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8875 break;
8876 case eEncodingT3:
8877 Rd = Bits32(opcode, 11, 8);
8878 Rn = Bits32(opcode, 19, 16);
8879 setflags = BitIsSet(opcode, 20);
8880 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8881
8882 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8883 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008884 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008885
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008886 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008887 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008888 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008889
8890 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8891 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8892 return false;
8893 break;
8894 case eEncodingT4:
8895 Rd = Bits32(opcode, 11, 8);
8896 Rn = Bits32(opcode, 19, 16);
8897 setflags = BitIsSet(opcode, 20);
8898 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8899
8900 // if Rn == '1111' then SEE ADR;
8901 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008902 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008903
8904 // if Rn == '1101' then SEE SUB (SP minus immediate);
8905 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008906 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008907
8908 if (BadReg(Rd))
8909 return false;
8910 break;
8911 default:
8912 return false;
8913 }
8914 // Read the register value from the operand register Rn.
8915 uint32_t reg_val = ReadCoreReg(Rn, &success);
8916 if (!success)
8917 return false;
8918
8919 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8920
8921 EmulateInstruction::Context context;
8922 context.type = EmulateInstruction::eContextImmediate;
8923 context.SetNoArgs ();
8924
8925 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8926 return false;
8927
8928 return true;
8929}
8930
8931// This instruction subtracts an immediate value from a register value, and writes the result
8932// to the destination register. It can optionally update the condition flags based on the result.
8933bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008934EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008935{
8936#if 0
8937 // ARM pseudo code...
8938 if ConditionPassed() then
8939 EncodingSpecificOperations();
8940 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8941 if d == 15 then
8942 ALUWritePC(result); // setflags is always FALSE here
8943 else
8944 R[d] = result;
8945 if setflags then
8946 APSR.N = result<31>;
8947 APSR.Z = IsZeroBit(result);
8948 APSR.C = carry;
8949 APSR.V = overflow;
8950#endif
8951
8952 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008953
8954 uint32_t Rd; // the destination register
8955 uint32_t Rn; // the first operand
8956 bool setflags;
8957 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8958 switch (encoding) {
8959 case eEncodingA1:
8960 Rd = Bits32(opcode, 15, 12);
8961 Rn = Bits32(opcode, 19, 16);
8962 setflags = BitIsSet(opcode, 20);
8963 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8964
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008965 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008966 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008967 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008968
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008969 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008970 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008971 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008972
8973 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008974 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008975 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008976 break;
8977 default:
8978 return false;
8979 }
8980 // Read the register value from the operand register Rn.
8981 uint32_t reg_val = ReadCoreReg(Rn, &success);
8982 if (!success)
8983 return false;
8984
8985 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8986
8987 EmulateInstruction::Context context;
8988 context.type = EmulateInstruction::eContextImmediate;
8989 context.SetNoArgs ();
8990
8991 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8992 return false;
8993
8994 return true;
8995}
8996
Johnny Chen2115b412011-02-21 23:42:44 +00008997// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8998// immediate value. It updates the condition flags based on the result, and discards the result.
8999bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009000EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009001{
9002#if 0
9003 // ARM pseudo code...
9004 if ConditionPassed() then
9005 EncodingSpecificOperations();
9006 result = R[n] EOR imm32;
9007 APSR.N = result<31>;
9008 APSR.Z = IsZeroBit(result);
9009 APSR.C = carry;
9010 // APSR.V unchanged
9011#endif
9012
9013 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009014
Greg Clayton7bc39082011-03-24 23:53:38 +00009015 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009016 {
9017 uint32_t Rn;
9018 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9019 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9020 switch (encoding)
9021 {
9022 case eEncodingT1:
9023 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009024 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009025 if (BadReg(Rn))
9026 return false;
9027 break;
9028 case eEncodingA1:
9029 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009030 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009031 break;
9032 default:
9033 return false;
9034 }
9035
9036 // Read the first operand.
9037 uint32_t val1 = ReadCoreReg(Rn, &success);
9038 if (!success)
9039 return false;
9040
9041 uint32_t result = val1 ^ imm32;
9042
9043 EmulateInstruction::Context context;
9044 context.type = EmulateInstruction::eContextImmediate;
9045 context.SetNoArgs ();
9046
9047 if (!WriteFlags(context, result, carry))
9048 return false;
9049 }
9050 return true;
9051}
9052
9053// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9054// optionally-shifted register value. It updates the condition flags based on the result, and discards
9055// the result.
9056bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009057EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009058{
9059#if 0
9060 // ARM pseudo code...
9061 if ConditionPassed() then
9062 EncodingSpecificOperations();
9063 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9064 result = R[n] EOR shifted;
9065 APSR.N = result<31>;
9066 APSR.Z = IsZeroBit(result);
9067 APSR.C = carry;
9068 // APSR.V unchanged
9069#endif
9070
9071 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009072
Greg Clayton7bc39082011-03-24 23:53:38 +00009073 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009074 {
9075 uint32_t Rn, Rm;
9076 ARM_ShifterType shift_t;
9077 uint32_t shift_n; // the shift applied to the value read from Rm
9078 uint32_t carry;
9079 switch (encoding)
9080 {
9081 case eEncodingT1:
9082 Rn = Bits32(opcode, 19, 16);
9083 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009084 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009085 if (BadReg(Rn) || BadReg(Rm))
9086 return false;
9087 break;
9088 case eEncodingA1:
9089 Rn = Bits32(opcode, 19, 16);
9090 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009091 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009092 break;
9093 default:
9094 return false;
9095 }
9096
9097 // Read the first operand.
9098 uint32_t val1 = ReadCoreReg(Rn, &success);
9099 if (!success)
9100 return false;
9101
9102 // Read the second operand.
9103 uint32_t val2 = ReadCoreReg(Rm, &success);
9104 if (!success)
9105 return false;
9106
9107 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9108 uint32_t result = val1 ^ shifted;
9109
9110 EmulateInstruction::Context context;
9111 context.type = EmulateInstruction::eContextImmediate;
9112 context.SetNoArgs ();
9113
9114 if (!WriteFlags(context, result, carry))
9115 return false;
9116 }
9117 return true;
9118}
9119
Johnny Chende3cce32011-02-21 21:24:49 +00009120// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9121// It updates the condition flags based on the result, and discards the result.
9122bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009123EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009124{
9125#if 0
9126 // ARM pseudo code...
9127 if ConditionPassed() then
9128 EncodingSpecificOperations();
9129 result = R[n] AND imm32;
9130 APSR.N = result<31>;
9131 APSR.Z = IsZeroBit(result);
9132 APSR.C = carry;
9133 // APSR.V unchanged
9134#endif
9135
9136 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009137
Greg Clayton7bc39082011-03-24 23:53:38 +00009138 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009139 {
9140 uint32_t Rn;
9141 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9142 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9143 switch (encoding)
9144 {
9145 case eEncodingT1:
9146 Rn = Bits32(opcode, 19, 16);
9147 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9148 if (BadReg(Rn))
9149 return false;
9150 break;
9151 case eEncodingA1:
9152 Rn = Bits32(opcode, 19, 16);
9153 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9154 break;
9155 default:
9156 return false;
9157 }
9158
9159 // Read the first operand.
9160 uint32_t val1 = ReadCoreReg(Rn, &success);
9161 if (!success)
9162 return false;
9163
9164 uint32_t result = val1 & imm32;
9165
9166 EmulateInstruction::Context context;
9167 context.type = EmulateInstruction::eContextImmediate;
9168 context.SetNoArgs ();
9169
9170 if (!WriteFlags(context, result, carry))
9171 return false;
9172 }
9173 return true;
9174}
9175
9176// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9177// It updates the condition flags based on the result, and discards the result.
9178bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009179EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009180{
9181#if 0
9182 // ARM pseudo code...
9183 if ConditionPassed() then
9184 EncodingSpecificOperations();
9185 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9186 result = R[n] AND shifted;
9187 APSR.N = result<31>;
9188 APSR.Z = IsZeroBit(result);
9189 APSR.C = carry;
9190 // APSR.V unchanged
9191#endif
9192
9193 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009194
Greg Clayton7bc39082011-03-24 23:53:38 +00009195 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009196 {
9197 uint32_t Rn, Rm;
9198 ARM_ShifterType shift_t;
9199 uint32_t shift_n; // the shift applied to the value read from Rm
9200 uint32_t carry;
9201 switch (encoding)
9202 {
9203 case eEncodingT1:
9204 Rn = Bits32(opcode, 2, 0);
9205 Rm = Bits32(opcode, 5, 3);
9206 shift_t = SRType_LSL;
9207 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009208 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009209 case eEncodingT2:
9210 Rn = Bits32(opcode, 19, 16);
9211 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009212 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009213 if (BadReg(Rn) || BadReg(Rm))
9214 return false;
9215 break;
9216 case eEncodingA1:
9217 Rn = Bits32(opcode, 19, 16);
9218 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009219 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009220 break;
9221 default:
9222 return false;
9223 }
9224
9225 // Read the first operand.
9226 uint32_t val1 = ReadCoreReg(Rn, &success);
9227 if (!success)
9228 return false;
9229
9230 // Read the second operand.
9231 uint32_t val2 = ReadCoreReg(Rm, &success);
9232 if (!success)
9233 return false;
9234
9235 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9236 uint32_t result = val1 & shifted;
9237
9238 EmulateInstruction::Context context;
9239 context.type = EmulateInstruction::eContextImmediate;
9240 context.SetNoArgs ();
9241
9242 if (!WriteFlags(context, result, carry))
9243 return false;
9244 }
9245 return true;
9246}
Caroline Ticed05b4902011-03-29 21:24:06 +00009247
9248// A8.6.216 SUB (SP minus register)
9249bool
9250EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9251{
9252#if 0
9253 if ConditionPassed() then
9254 EncodingSpecificOperations();
9255 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9256 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), 1’);
9257 if d == 15 then // Can only occur for ARM encoding
9258 ALUWritePC(result); // setflags is always FALSE here
9259 else
9260 R[d] = result;
9261 if setflags then
9262 APSR.N = result<31>;
9263 APSR.Z = IsZeroBit(result);
9264 APSR.C = carry;
9265 APSR.V = overflow;
9266#endif
9267
9268 bool success = false;
9269
9270 if (ConditionPassed(opcode))
9271 {
9272 uint32_t d;
9273 uint32_t m;
9274 bool setflags;
9275 ARM_ShifterType shift_t;
9276 uint32_t shift_n;
9277
9278 switch (encoding)
9279 {
9280 case eEncodingT1:
9281 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9282 d = Bits32 (opcode, 11, 8);
9283 m = Bits32 (opcode, 3, 0);
9284 setflags = BitIsSet (opcode, 20);
9285
9286 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9287 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9288
9289 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9290 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9291 return false;
9292
9293 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9294 if ((d == 15) || BadReg (m))
9295 return false;
9296 break;
9297
9298 case eEncodingA1:
Caroline Ticed05b4902011-03-29 21:24:06 +00009299 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9300 d = Bits32 (opcode, 15, 12);
9301 m = Bits32 (opcode, 3, 0);
9302 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009303
9304 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9305 if (d == 15 && setflags)
9306 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009307
9308 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9309 shift_n = DecodeImmShiftARM (opcode, shift_t);
9310 break;
9311
9312 default:
9313 return false;
9314 }
9315
9316 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9317 uint32_t Rm = ReadCoreReg (m, &success);
9318 if (!success)
9319 return false;
9320
9321 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9322
9323 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’);
9324 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9325 if (!success)
9326 return false;
9327
9328 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9329
9330 EmulateInstruction::Context context;
9331 context.type = eContextSubtraction;
9332 Register sp_reg;
9333 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
9334 Register dwarf_reg;
9335 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
9336 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9337
Caroline Ticeef440002011-03-30 05:40:56 +00009338 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009339 return false;
9340 }
9341 return true;
9342}
9343
9344
9345// A8.6.7 ADD (register-shifted register)
9346bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009347EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009348{
9349#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009350 if ConditionPassed() then
9351 EncodingSpecificOperations();
9352 shift_n = UInt(R[s]<7:0>);
9353 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9354 (result, carry, overflow) = AddWithCarry(R[n], shifted, 0’);
9355 R[d] = result;
9356 if setflags then
9357 APSR.N = result<31>;
9358 APSR.Z = IsZeroBit(result);
9359 APSR.C = carry;
9360 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009361#endif
9362
Caroline Ticec08ed382011-03-29 23:03:16 +00009363 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009364
9365 if (ConditionPassed(opcode))
9366 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009367 uint32_t d;
9368 uint32_t n;
9369 uint32_t m;
9370 uint32_t s;
9371 bool setflags;
9372 ARM_ShifterType shift_t;
9373
Caroline Ticed05b4902011-03-29 21:24:06 +00009374 switch (encoding)
9375 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009376 case eEncodingA1:
9377 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9378 d = Bits32 (opcode, 15, 12);
9379 n = Bits32 (opcode, 19, 16);
9380 m = Bits32 (opcode, 3, 0);
9381 s = Bits32 (opcode, 11, 8);
9382
9383 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type);
9384 setflags = BitIsSet (opcode, 20);
9385 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9386
9387 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9388 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9389 return false;
9390 break;
9391
9392 default:
9393 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009394 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009395
9396 // shift_n = UInt(R[s]<7:0>);
9397 uint32_t Rs = ReadCoreReg (s, &success);
9398 if (!success)
9399 return false;
9400
9401 uint32_t shift_n = Bits32 (Rs, 7, 0);
9402
9403 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9404 uint32_t Rm = ReadCoreReg (m, &success);
9405 if (!success)
9406 return false;
9407
9408 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9409
9410 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’);
9411 uint32_t Rn = ReadCoreReg (n, &success);
9412 if (!success)
9413 return false;
9414
9415 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9416
9417 // R[d] = result;
9418 EmulateInstruction::Context context;
9419 context.type = eContextAddition;
9420 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009421 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
Caroline Ticec08ed382011-03-29 23:03:16 +00009422 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009423 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009424
9425 context.SetRegisterRegisterOperands (reg_n, reg_m);
9426
9427 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9428 return false;
9429
9430 // if setflags then
9431 // APSR.N = result<31>;
9432 // APSR.Z = IsZeroBit(result);
9433 // APSR.C = carry;
9434 // APSR.V = overflow;
9435 if (setflags)
9436 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009437 }
9438 return true;
9439}
9440
9441// A8.6.213 SUB (register)
9442bool
9443EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9444{
9445#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009446 if ConditionPassed() then
9447 EncodingSpecificOperations();
9448 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9449 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), 1’);
9450 if d == 15 then // Can only occur for ARM encoding
9451 ALUWritePC(result); // setflags is always FALSE here
9452 else
9453 R[d] = result;
9454 if setflags then
9455 APSR.N = result<31>;
9456 APSR.Z = IsZeroBit(result);
9457 APSR.C = carry;
9458 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009459#endif
9460
Caroline Tice4cccd532011-03-29 23:44:20 +00009461 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009462
9463 if (ConditionPassed(opcode))
9464 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009465 uint32_t d;
9466 uint32_t n;
9467 uint32_t m;
9468 bool setflags;
9469 ARM_ShifterType shift_t;
9470 uint32_t shift_n;
9471
Caroline Ticed05b4902011-03-29 21:24:06 +00009472 switch (encoding)
9473 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009474 case eEncodingT1:
9475 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9476 d = Bits32 (opcode, 2, 0);
9477 n = Bits32 (opcode, 5, 3);
9478 m = Bits32 (opcode, 8, 6);
9479 setflags = !InITBlock();
9480
9481 // (shift_t, shift_n) = (SRType_LSL, 0);
9482 shift_t = SRType_LSL;
9483 shift_n = 0;
9484
9485 break;
9486
9487 case eEncodingT2:
9488 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register);
9489 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9490 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9491 d = Bits32 (opcode, 11, 8);
9492 n = Bits32 (opcode, 19, 16);
9493 m = Bits32 (opcode, 3, 0);
9494 setflags = BitIsSet (opcode, 20);
9495
9496 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9497 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9498
9499 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9500 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9501 return false;
9502
9503 break;
9504
9505 case eEncodingA1:
Caroline Tice4cccd532011-03-29 23:44:20 +00009506 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9507 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9508 d = Bits32 (opcode, 15, 12);
9509 n = Bits32 (opcode, 19, 16);
9510 m = Bits32 (opcode, 3, 0);
9511 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009512
9513 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9514 if ((d == 15) && setflags)
9515 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009516
9517 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9518 shift_n = DecodeImmShiftARM (opcode, shift_t);
9519
9520 break;
9521
9522 default:
9523 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009524 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009525
9526 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9527 uint32_t Rm = ReadCoreReg (m, &success);
9528 if (!success)
9529 return false;
9530
9531 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9532
9533 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’);
9534 uint32_t Rn = ReadCoreReg (n, &success);
9535 if (!success)
9536 return false;
9537
9538 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9539
9540 // if d == 15 then // Can only occur for ARM encoding
9541 // ALUWritePC(result); // setflags is always FALSE here
9542 // else
9543 // R[d] = result;
9544 // if setflags then
9545 // APSR.N = result<31>;
9546 // APSR.Z = IsZeroBit(result);
9547 // APSR.C = carry;
9548 // APSR.V = overflow;
9549
9550 EmulateInstruction::Context context;
9551 context.type = eContextSubtraction;
9552 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009553 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Tice4cccd532011-03-29 23:44:20 +00009554 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009555 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009556 context.SetRegisterRegisterOperands (reg_n, reg_m);
9557
Caroline Ticeef440002011-03-30 05:40:56 +00009558 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009559 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009560 }
9561 return true;
9562}
Caroline Tice4cccd532011-03-29 23:44:20 +00009563
Caroline Ticed05b4902011-03-29 21:24:06 +00009564// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009565// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9566// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009567bool
9568EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9569{
9570#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009571 if ConditionPassed() then
9572 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9573 address = R[n] + imm32;
9574 if ExclusiveMonitorsPass(address,4) then
9575 MemA[address,4] = R[t];
9576 R[d] = 0;
9577 else
9578 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009579#endif
9580
Caroline Tice5168b6c2011-03-30 05:15:46 +00009581 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009582
9583 if (ConditionPassed(opcode))
9584 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009585 uint32_t d;
9586 uint32_t t;
9587 uint32_t n;
9588 uint32_t imm32;
9589 const uint32_t addr_byte_size = GetAddressByteSize();
9590
Caroline Ticed05b4902011-03-29 21:24:06 +00009591 switch (encoding)
9592 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009593 case eEncodingT1:
9594 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9595 d = Bits32 (opcode, 11, 8);
9596 t = Bits32 (opcode, 15, 12);
9597 n = Bits32 (opcode, 19, 16);
9598 imm32 = Bits32 (opcode, 7, 0) << 2;
9599
9600 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9601 if (BadReg (d) || BadReg (t) || (n == 15))
9602 return false;
9603
9604 // if d == n || d == t then UNPREDICTABLE;
9605 if ((d == n) || (d == t))
9606 return false;
9607
9608 break;
9609
9610 case eEncodingA1:
9611 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9612 d = Bits32 (opcode, 15, 12);
9613 t = Bits32 (opcode, 3, 0);
9614 n = Bits32 (opcode, 19, 16);
9615 imm32 = 0;
9616
9617 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9618 if ((d == 15) || (t == 15) || (n == 15))
9619 return false;
9620
9621 // if d == n || d == t then UNPREDICTABLE;
9622 if ((d == n) || (d == t))
9623 return false;
9624
9625 break;
9626
9627 default:
9628 return false;
9629 }
9630
9631 // address = R[n] + imm32;
9632 uint32_t Rn = ReadCoreReg (n, &success);
9633 if (!success)
9634 return false;
9635
9636 addr_t address = Rn + imm32;
9637
9638 Register base_reg;
9639 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9640 Register data_reg;
9641 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
9642 EmulateInstruction::Context context;
9643 context.type = eContextRegisterStore;
9644 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9645
9646 // if ExclusiveMonitorsPass(address,4) then
9647 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9648 // always return true.
9649 if (true)
9650 {
9651 // MemA[address,4] = R[t];
9652 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9653 if (!success)
9654 return false;
9655
9656 if (!MemAWrite (context, address, Rt, addr_byte_size))
9657 return false;
9658
9659 // R[d] = 0;
9660 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9661 return false;
9662 }
9663 else
9664 {
9665 // R[d] = 1;
9666 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9667 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009668 }
9669 }
9670 return true;
9671}
9672
9673// A8.6.197 STRB (immediate, ARM)
9674bool
9675EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9676{
9677#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009678 if ConditionPassed() then
9679 EncodingSpecificOperations();
9680 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9681 address = if index then offset_addr else R[n];
9682 MemU[address,1] = R[t]<7:0>;
9683 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009684#endif
9685
Caroline Ticeef440002011-03-30 05:40:56 +00009686 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009687
9688 if (ConditionPassed(opcode))
9689 {
Caroline Ticeef440002011-03-30 05:40:56 +00009690 uint32_t t;
9691 uint32_t n;
9692 uint32_t imm32;
9693 bool index;
9694 bool add;
9695 bool wback;
9696
Caroline Ticed05b4902011-03-29 21:24:06 +00009697 switch (encoding)
9698 {
Caroline Ticeef440002011-03-30 05:40:56 +00009699 case eEncodingA1:
9700 // if P == ‘0’ && W == ‘1’ then SEE STRBT;
9701 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9702 t = Bits32 (opcode, 15, 12);
9703 n = Bits32 (opcode, 19, 16);
9704 imm32 = Bits32 (opcode, 11, 0);
9705
9706 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9707 index = BitIsSet (opcode, 24);
9708 add = BitIsSet (opcode, 23);
9709 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9710
9711 // if t == 15 then UNPREDICTABLE;
9712 if (t == 15)
9713 return false;
9714
9715 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9716 if (wback && ((n == 15) || (n == t)))
9717 return false;
9718
9719 break;
9720
9721 default:
9722 return false;
9723 }
9724
9725 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9726 uint32_t Rn = ReadCoreReg (n, &success);
9727 if (!success)
9728 return false;
9729
9730 addr_t offset_addr;
9731 if (add)
9732 offset_addr = Rn + imm32;
9733 else
9734 offset_addr = Rn - imm32;
9735
9736 // address = if index then offset_addr else R[n];
9737 addr_t address;
9738 if (index)
9739 address = offset_addr;
9740 else
9741 address = Rn;
9742
9743 // MemU[address,1] = R[t]<7:0>;
9744 uint32_t Rt = ReadCoreReg (t, &success);
9745 if (!success)
9746 return false;
9747
9748 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009749 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticeef440002011-03-30 05:40:56 +00009750 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009751 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticeef440002011-03-30 05:40:56 +00009752 EmulateInstruction::Context context;
9753 context.type = eContextRegisterStore;
9754 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9755
9756 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9757 return false;
9758
9759 // if wback then R[n] = offset_addr;
9760 if (wback)
9761 {
Caroline Tice523c5542011-04-13 00:42:12 +00009762 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009763 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009764 }
9765 }
9766 return true;
9767}
9768
9769// A8.6.194 STR (immediate, ARM)
9770bool
9771EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9772{
9773#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009774 if ConditionPassed() then
9775 EncodingSpecificOperations();
9776 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9777 address = if index then offset_addr else R[n];
9778 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9779 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009780#endif
9781
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009782 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009783
9784 if (ConditionPassed(opcode))
9785 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009786 uint32_t t;
9787 uint32_t n;
9788 uint32_t imm32;
9789 bool index;
9790 bool add;
9791 bool wback;
9792
9793 const uint32_t addr_byte_size = GetAddressByteSize();
9794
Caroline Ticed05b4902011-03-29 21:24:06 +00009795 switch (encoding)
9796 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009797 case eEncodingA1:
9798 // if P == ‘0’ && W == ‘1’ then SEE STRT;
9799 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH;
9800 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9801 t = Bits32 (opcode, 15, 12);
9802 n = Bits32 (opcode, 19, 16);
9803 imm32 = Bits32 (opcode, 11, 0);
9804
9805 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9806 index = BitIsSet (opcode, 24);
9807 add = BitIsSet (opcode, 23);
9808 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9809
9810 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9811 if (wback && ((n == 15) || (n == t)))
9812 return false;
9813
9814 break;
9815
9816 default:
9817 return false;
9818 }
9819
9820 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9821 uint32_t Rn = ReadCoreReg (n, &success);
9822 if (!success)
9823 return false;
9824
9825 addr_t offset_addr;
9826 if (add)
9827 offset_addr = Rn + imm32;
9828 else
9829 offset_addr = Rn - imm32;
9830
9831 // address = if index then offset_addr else R[n];
9832 addr_t address;
9833 if (index)
9834 address = offset_addr;
9835 else
9836 address = Rn;
9837
9838 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009839 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009840 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009841 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009842 EmulateInstruction::Context context;
9843 context.type = eContextRegisterStore;
9844 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9845
9846 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9847 uint32_t Rt = ReadCoreReg (t, &success);
9848 if (!success)
9849 return false;
9850
9851 if (t == 15)
9852 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009853 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009854 if (!success)
9855 return false;
9856
9857 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9858 return false;
9859 }
9860 else
9861 {
9862 if (!MemUWrite (context, address, Rt, addr_byte_size))
9863 return false;
9864 }
9865
9866 // if wback then R[n] = offset_addr;
9867 if (wback)
9868 {
9869 context.type = eContextAdjustBaseRegister;
9870 context.SetImmediate (offset_addr);
9871
9872 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9873 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009874 }
9875 }
9876 return true;
9877}
9878
Caroline Ticed05b4902011-03-29 21:24:06 +00009879// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009880// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9881// 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 +00009882bool
9883EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9884{
9885#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009886 if ConditionPassed() then
9887 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9888 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9889 address = if index then offset_addr else R[n];
9890 R[t] = MemA[address,4];
9891 R[t2] = MemA[address+4,4];
9892 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009893#endif
9894
Caroline Tice1697dd72011-03-30 17:11:45 +00009895 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009896
9897 if (ConditionPassed(opcode))
9898 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009899 uint32_t t;
9900 uint32_t t2;
9901 uint32_t n;
9902 uint32_t imm32;
9903 bool index;
9904 bool add;
9905 bool wback;
9906
Caroline Ticed05b4902011-03-29 21:24:06 +00009907 switch (encoding)
9908 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009909 case eEncodingT1:
9910 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
9911 //if Rn == ‘1111’ then SEE LDRD (literal);
9912 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9913 t = Bits32 (opcode, 15, 12);
9914 t2 = Bits32 (opcode, 11, 8);
9915 n = Bits32 (opcode, 19, 16);
9916 imm32 = Bits32 (opcode, 7, 0) << 2;
9917
9918 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
9919 index = BitIsSet (opcode, 24);
9920 add = BitIsSet (opcode, 23);
9921 wback = BitIsSet (opcode, 21);
9922
9923 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9924 if (wback && ((n == t) || (n == t2)))
9925 return false;
9926
9927 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9928 if (BadReg (t) || BadReg (t2) || (t == t2))
9929 return false;
9930
9931 break;
9932
9933 case eEncodingA1:
9934 //if Rn == ‘1111’ then SEE LDRD (literal);
9935 //if Rt<0> == ‘1’ then UNPREDICTABLE;
9936 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9937 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009938 if (BitIsSet (t, 0))
9939 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009940 t2 = t + 1;
9941 n = Bits32 (opcode, 19, 16);
9942 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9943
9944 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9945 index = BitIsSet (opcode, 24);
9946 add = BitIsSet (opcode, 23);
9947 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9948
9949 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
9950 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9951 return false;
9952
9953 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9954 if (wback && ((n == t) || (n == t2)))
9955 return false;
9956
9957 //if t2 == 15 then UNPREDICTABLE;
9958 if (t2 == 15)
9959 return false;
9960
9961 break;
9962
9963 default:
9964 return false;
9965 }
9966
9967 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9968 uint32_t Rn = ReadCoreReg (n, &success);
9969 if (!success)
9970 return false;
9971
9972 addr_t offset_addr;
9973 if (add)
9974 offset_addr = Rn + imm32;
9975 else
9976 offset_addr = Rn - imm32;
9977
9978 //address = if index then offset_addr else R[n];
9979 addr_t address;
9980 if (index)
9981 address = offset_addr;
9982 else
9983 address = Rn;
9984
9985 //R[t] = MemA[address,4];
9986 Register base_reg;
9987 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9988
9989 EmulateInstruction::Context context;
9990 context.type = eContextRegisterLoad;
9991 context.SetRegisterPlusOffset (base_reg, address - Rn);
9992
9993 const uint32_t addr_byte_size = GetAddressByteSize();
9994 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
9995 if (!success)
9996 return false;
9997
9998 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
9999 return false;
10000
10001 //R[t2] = MemA[address+4,4];
10002
10003 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10004 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10005 if (!success)
10006 return false;
10007
10008 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10009 return false;
10010
10011 //if wback then R[n] = offset_addr;
10012 if (wback)
10013 {
10014 context.type = eContextAdjustBaseRegister;
10015 context.SetAddress (offset_addr);
10016
10017 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10018 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010019 }
10020 }
10021 return true;
10022}
10023
Caroline Ticed05b4902011-03-29 21:24:06 +000010024// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010025// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10026// 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 +000010027bool
10028EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10029{
10030#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010031 if ConditionPassed() then
10032 EncodingSpecificOperations();
10033 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10034 address = if index then offset_addr else R[n];
10035 R[t] = MemA[address,4];
10036 R[t2] = MemA[address+4,4];
10037 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010038#endif
10039
Caroline Ticeeab301f2011-03-30 17:54:52 +000010040 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010041
10042 if (ConditionPassed(opcode))
10043 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010044 uint32_t t;
10045 uint32_t t2;
10046 uint32_t n;
10047 uint32_t m;
10048 bool index;
10049 bool add;
10050 bool wback;
10051
Caroline Ticed05b4902011-03-29 21:24:06 +000010052 switch (encoding)
10053 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010054 case eEncodingA1:
10055 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10056 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10057 t = Bits32 (opcode, 15, 12);
10058 if (BitIsSet (t, 0))
10059 return false;
10060 t2 = t + 1;
10061 n = Bits32 (opcode, 19, 16);
10062 m = Bits32 (opcode, 3, 0);
10063
10064 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10065 index = BitIsSet (opcode, 24);
10066 add = BitIsSet (opcode, 23);
10067 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10068
10069 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10070 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10071 return false;
10072
10073 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10074 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10075 return false;
10076
10077 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10078 if (wback && ((n == 15) || (n == t) || (n == t2)))
10079 return false;
10080
10081 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10082 if ((ArchVersion() < 6) && wback && (m == n))
10083 return false;
10084 break;
10085
10086 default:
10087 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010088 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010089
Caroline Ticeeab301f2011-03-30 17:54:52 +000010090 uint32_t Rn = ReadCoreReg (n, &success);
10091 if (!success)
10092 return false;
10093 Register base_reg;
10094 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed05b4902011-03-29 21:24:06 +000010095
Caroline Ticeeab301f2011-03-30 17:54:52 +000010096 uint32_t Rm = ReadCoreReg (m, &success);
10097 if (!success)
10098 return false;
10099 Register offset_reg;
10100 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticed05b4902011-03-29 21:24:06 +000010101
Caroline Ticeeab301f2011-03-30 17:54:52 +000010102 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10103 addr_t offset_addr;
10104 if (add)
10105 offset_addr = Rn + Rm;
10106 else
10107 offset_addr = Rn - Rm;
10108
10109 // address = if index then offset_addr else R[n];
10110 addr_t address;
10111 if (index)
10112 address = offset_addr;
10113 else
10114 address = Rn;
10115
10116 EmulateInstruction::Context context;
10117 context.type = eContextRegisterLoad;
10118 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10119
10120 // R[t] = MemA[address,4];
10121 const uint32_t addr_byte_size = GetAddressByteSize();
10122 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10123 if (!success)
10124 return false;
10125
10126 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10127 return false;
10128
10129 // R[t2] = MemA[address+4,4];
10130
10131 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10132 if (!success)
10133 return false;
10134
10135 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10136 return false;
10137
10138 // if wback then R[n] = offset_addr;
10139 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010140 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010141 context.type = eContextAdjustBaseRegister;
10142 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010143
Caroline Ticeeab301f2011-03-30 17:54:52 +000010144 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10145 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010146 }
10147 }
10148 return true;
10149}
Caroline Ticed05b4902011-03-29 21:24:06 +000010150
10151// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010152// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10153// 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 +000010154bool
10155EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10156{
10157#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010158 if ConditionPassed() then
10159 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10160 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10161 address = if index then offset_addr else R[n];
10162 MemA[address,4] = R[t];
10163 MemA[address+4,4] = R[t2];
10164 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010165#endif
10166
Caroline Tice74467fe2011-03-30 19:02:56 +000010167 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010168
Caroline Tice74467fe2011-03-30 19:02:56 +000010169 if (ConditionPassed(opcode))
10170 {
10171 uint32_t t;
10172 uint32_t t2;
10173 uint32_t n;
10174 uint32_t imm32;
10175 bool index;
10176 bool add;
10177 bool wback;
10178
10179 switch (encoding)
10180 {
10181 case eEncodingT1:
10182 // if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10183 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10184 t = Bits32 (opcode, 15, 12);
10185 t2 = Bits32 (opcode, 11, 8);
10186 n = Bits32 (opcode, 19, 16);
10187 imm32 = Bits32 (opcode, 7, 0) << 2;
10188
10189 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
10190 index = BitIsSet (opcode, 24);
10191 add = BitIsSet (opcode, 23);
10192 wback = BitIsSet (opcode, 21);
10193
10194 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10195 if (wback && ((n == t) || (n == t2)))
10196 return false;
10197
10198 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10199 if ((n == 15) || BadReg (t) || BadReg (t2))
10200 return false;
10201
10202 break;
10203
10204 case eEncodingA1:
10205 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10206 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10207 t = Bits32 (opcode, 15, 12);
10208 if (BitIsSet (t, 0))
10209 return false;
10210
10211 t2 = t + 1;
10212 n = Bits32 (opcode, 19, 16);
10213 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10214
10215 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10216 index = BitIsSet (opcode, 24);
10217 add = BitIsSet (opcode, 23);
10218 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10219
10220 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10221 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10222 return false;
10223
10224 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10225 if (wback && ((n == 15) || (n == t) || (n == t2)))
10226 return false;
10227
10228 // if t2 == 15 then UNPREDICTABLE;
10229 if (t2 == 15)
10230 return false;
10231
10232 break;
10233
10234 default:
10235 return false;
10236 }
10237
10238 Register base_reg;
10239 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10240
10241 uint32_t Rn = ReadCoreReg (n, &success);
10242 if (!success)
10243 return false;
10244
10245 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10246 addr_t offset_addr;
10247 if (add)
10248 offset_addr = Rn + imm32;
10249 else
10250 offset_addr = Rn - imm32;
10251
10252 //address = if index then offset_addr else R[n];
10253 addr_t address;
10254 if (index)
10255 address = offset_addr;
10256 else
10257 address = Rn;
10258
10259 //MemA[address,4] = R[t];
10260 Register data_reg;
10261 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10262
10263 uint32_t data = ReadCoreReg (t, &success);
10264 if (!success)
10265 return false;
10266
10267 EmulateInstruction::Context context;
10268 context.type = eContextRegisterStore;
10269 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10270
10271 const uint32_t addr_byte_size = GetAddressByteSize();
10272
10273 if (!MemAWrite (context, address, data, addr_byte_size))
10274 return false;
10275
10276 //MemA[address+4,4] = R[t2];
10277 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t2);
10278 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10279
10280 data = ReadCoreReg (t2, &success);
10281 if (!success)
10282 return false;
10283
10284 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10285 return false;
10286
10287 //if wback then R[n] = offset_addr;
10288 if (wback)
10289 {
10290 context.type = eContextAdjustBaseRegister;
10291 context.SetAddress (offset_addr);
10292
10293 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10294 return false;
10295 }
10296 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010297 return true;
10298}
10299
10300
10301// A8.6.201 STRD (register)
10302bool
10303EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10304{
10305#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010306 if ConditionPassed() then
10307 EncodingSpecificOperations();
10308 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10309 address = if index then offset_addr else R[n];
10310 MemA[address,4] = R[t];
10311 MemA[address+4,4] = R[t2];
10312 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010313#endif
10314
Caroline Tice74467fe2011-03-30 19:02:56 +000010315 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010316
Caroline Tice74467fe2011-03-30 19:02:56 +000010317 if (ConditionPassed(opcode))
10318 {
10319 uint32_t t;
10320 uint32_t t2;
10321 uint32_t n;
10322 uint32_t m;
10323 bool index;
10324 bool add;
10325 bool wback;
10326
10327 switch (encoding)
10328 {
10329 case eEncodingA1:
10330 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10331 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10332 t = Bits32 (opcode, 15, 12);
10333 if (BitIsSet (t, 0))
10334 return false;
10335
10336 t2 = t+1;
10337 n = Bits32 (opcode, 19, 16);
10338 m = Bits32 (opcode, 3, 0);
10339
10340 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10341 index = BitIsSet (opcode, 24);
10342 add = BitIsSet (opcode, 23);
10343 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10344
10345 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10346 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10347 return false;
10348
10349 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10350 if ((t2 == 15) || (m == 15))
10351 return false;
10352
10353 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10354 if (wback && ((n == 15) || (n == t) || (n == t2)))
10355 return false;
10356
10357 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010358 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010359 return false;
10360
10361 break;
10362
10363 default:
10364 return false;
10365 }
10366
10367 Register base_reg;
10368 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10369 Register offset_reg;
10370 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
10371 Register data_reg;
10372 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10373
10374 uint32_t Rn = ReadCoreReg (n, &success);
10375 if (!success)
10376 return false;
10377
10378 uint32_t Rm = ReadCoreReg (m, &success);
10379 if (!success)
10380 return false;
10381
10382 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10383 addr_t offset_addr;
10384 if (add)
10385 offset_addr = Rn + Rm;
10386 else
10387 offset_addr = Rn - Rm;
10388
10389 // address = if index then offset_addr else R[n];
10390 addr_t address;
10391 if (index)
10392 address = offset_addr;
10393 else
10394 address = Rn;
10395 // MemA[address,4] = R[t];
10396 uint32_t Rt = ReadCoreReg (t, &success);
10397 if (!success)
10398 return false;
10399
10400 EmulateInstruction::Context context;
10401 context.type = eContextRegisterStore;
10402 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10403
10404 const uint32_t addr_byte_size = GetAddressByteSize();
10405
10406 if (!MemAWrite (context, address, Rt, addr_byte_size))
10407 return false;
10408
10409 // MemA[address+4,4] = R[t2];
10410 uint32_t Rt2 = ReadCoreReg (t2, &success);
10411 if (!success)
10412 return false;
10413
10414 data_reg.num = dwarf_r0 + t2;
10415
10416 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10417
10418 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10419 return false;
10420
10421 // if wback then R[n] = offset_addr;
10422 if (wback)
10423 {
10424 context.type = eContextAdjustBaseRegister;
10425 context.SetAddress (offset_addr);
10426
10427 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10428 return false;
10429
10430 }
10431 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010432 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010433}
10434
Caroline Tice4f605582011-03-31 00:02:51 +000010435// A8.6.319 VLDM
10436// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10437// an ARM core register.
10438bool
10439EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10440{
10441#if 0
10442 if ConditionPassed() then
10443 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10444 address = if add then R[n] else R[n]-imm32;
10445 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10446 for r = 0 to regs-1
10447 if single_regs then
10448 S[d+r] = MemA[address,4]; address = address+4;
10449 else
10450 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10451 // Combine the word-aligned words in the correct order for current endianness.
10452 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10453#endif
10454
10455 bool success = false;
10456
10457 if (ConditionPassed(opcode))
10458 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010459 bool single_regs;
10460 bool add;
10461 bool wback;
10462 uint32_t d;
10463 uint32_t n;
10464 uint32_t imm32;
10465 uint32_t regs;
10466
Caroline Tice4f605582011-03-31 00:02:51 +000010467 switch (encoding)
10468 {
10469 case eEncodingT1:
10470 case eEncodingA1:
10471 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10472 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10473 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10474 // if P == U && W == ‘1’ then UNDEFINED;
10475 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10476 return false;
10477
10478 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10479 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10480 single_regs = false;
10481 add = BitIsSet (opcode, 23);
10482 wback = BitIsSet (opcode, 21);
10483
10484 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10485 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10486 n = Bits32 (opcode, 19, 16);
10487 imm32 = Bits32 (opcode, 7, 0) << 2;
10488
10489 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FLDMX”.
10490 regs = Bits32 (opcode, 7, 0) / 2;
10491
10492 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10493 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10494 return false;
10495
10496 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10497 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10498 return false;
10499
10500 break;
10501
10502 case eEncodingT2:
10503 case eEncodingA2:
10504 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10505 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10506 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10507 // if P == U && W == ‘1’ then UNDEFINED;
10508 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10509 return false;
10510
10511 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10512 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10513 single_regs = true;
10514 add = BitIsSet (opcode, 23);
10515 wback = BitIsSet (opcode, 21);
10516 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10517 n = Bits32 (opcode, 19, 16);
10518
10519 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10520 imm32 = Bits32 (opcode, 7, 0) << 2;
10521 regs = Bits32 (opcode, 7, 0);
10522
10523 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10524 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10525 return false;
10526
10527 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10528 if ((regs == 0) || ((d + regs) > 32))
10529 return false;
10530 break;
10531
10532 default:
10533 return false;
10534 }
10535
10536 Register base_reg;
10537 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10538
10539 uint32_t Rn = ReadCoreReg (n, &success);
10540 if (!success)
10541 return false;
10542
10543 // address = if add then R[n] else R[n]-imm32;
10544 addr_t address;
10545 if (add)
10546 address = Rn;
10547 else
10548 address = Rn - imm32;
10549
10550 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10551 EmulateInstruction::Context context;
10552
10553 if (wback)
10554 {
10555 uint32_t value;
10556 if (add)
10557 value = Rn + imm32;
10558 else
10559 value = Rn - imm32;
10560
10561 context.type = eContextAdjustBaseRegister;
10562 context.SetImmediateSigned (value - Rn);
10563 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10564 return false;
10565
10566 }
10567
10568 const uint32_t addr_byte_size = GetAddressByteSize();
10569 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10570
10571 context.type = eContextRegisterLoad;
10572
10573 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010574 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010575 {
10576 if (single_regs)
10577 {
10578 // S[d+r] = MemA[address,4]; address = address+4;
10579 context.SetRegisterPlusOffset (base_reg, address - Rn);
10580
10581 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10582 if (!success)
10583 return false;
10584
10585 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10586 return false;
10587
10588 address = address + 4;
10589 }
10590 else
10591 {
10592 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10593 context.SetRegisterPlusOffset (base_reg, address - Rn);
10594 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10595 if (!success)
10596 return false;
10597
10598 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10599 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10600 if (!success)
10601 return false;
10602
10603 address = address + 8;
10604 // // Combine the word-aligned words in the correct order for current endianness.
10605 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10606 uint64_t data;
10607 if (m_byte_order == eByteOrderBig)
10608 {
10609 data = word1;
10610 data = (data << 32) | word2;
10611 }
10612 else
10613 {
10614 data = word2;
10615 data = (data << 32) | word1;
10616 }
10617
10618 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10619 return false;
10620 }
10621 }
10622 }
10623 return true;
10624}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010625
10626// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010627// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10628// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010629bool
10630EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10631{
10632#if 0
10633 if ConditionPassed() then
10634 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10635 address = if add then R[n] else R[n]-imm32;
10636 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10637 for r = 0 to regs-1
10638 if single_regs then
10639 MemA[address,4] = S[d+r]; address = address+4;
10640 else
10641 // Store as two word-aligned words in the correct order for current endianness.
10642 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10643 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10644 address = address+8;
10645#endif
10646
10647 bool success = false;
10648
10649 if (ConditionPassed (opcode))
10650 {
10651 bool single_regs;
10652 bool add;
10653 bool wback;
10654 uint32_t d;
10655 uint32_t n;
10656 uint32_t imm32;
10657 uint32_t regs;
10658
10659 switch (encoding)
10660 {
10661 case eEncodingT1:
10662 case eEncodingA1:
10663 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10664 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10665 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10666 // if P == U && W == ‘1’ then UNDEFINED;
10667 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10668 return false;
10669
10670 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10671 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10672 single_regs = false;
10673 add = BitIsSet (opcode, 23);
10674 wback = BitIsSet (opcode, 21);
10675
10676 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10677 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10678 n = Bits32 (opcode, 19, 16);
10679 imm32 = Bits32 (opcode, 7, 0) << 2;
10680
10681 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FSTMX”.
10682 regs = Bits32 (opcode, 7, 0) / 2;
10683
10684 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10685 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10686 return false;
10687
10688 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10689 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10690 return false;
10691
10692 break;
10693
10694 case eEncodingT2:
10695 case eEncodingA2:
10696 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10697 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10698 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10699 // if P == U && W == ‘1’ then UNDEFINED;
10700 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10701 return false;
10702
10703 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10704 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10705 single_regs = true;
10706 add = BitIsSet (opcode, 23);
10707 wback = BitIsSet (opcode, 21);
10708 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10709 n = Bits32 (opcode, 19, 16);
10710
10711 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10712 imm32 = Bits32 (opcode, 7, 0) << 2;
10713 regs = Bits32 (opcode, 7, 0);
10714
10715 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10716 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10717 return false;
10718
10719 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10720 if ((regs == 0) || ((d + regs) > 32))
10721 return false;
10722
10723 break;
10724
10725 default:
10726 return false;
10727 }
10728
10729 Register base_reg;
10730 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10731
10732 uint32_t Rn = ReadCoreReg (n, &success);
10733 if (!success)
10734 return false;
10735
10736 // address = if add then R[n] else R[n]-imm32;
10737 addr_t address;
10738 if (add)
10739 address = Rn;
10740 else
10741 address = Rn - imm32;
10742
10743 EmulateInstruction::Context context;
10744 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10745 if (wback)
10746 {
10747 uint32_t value;
10748 if (add)
10749 value = Rn + imm32;
10750 else
10751 value = Rn - imm32;
10752
10753 context.type = eContextAdjustBaseRegister;
10754 context.SetRegisterPlusOffset (base_reg, value - Rn);
10755
10756 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10757 return false;
10758 }
10759
10760 const uint32_t addr_byte_size = GetAddressByteSize();
10761 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10762
10763 context.type = eContextRegisterStore;
10764 // for r = 0 to regs-1
10765 for (int r = 0; r < regs; ++r)
10766 {
10767 Register data_reg;
10768 data_reg.SetRegister (eRegisterKindDWARF, 0);
10769 if (single_regs)
10770 {
10771 // MemA[address,4] = S[d+r]; address = address+4;
10772 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10773 if (!success)
10774 return false;
10775
10776 data_reg.num = start_reg + d + r;
10777 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10778 if (!MemAWrite (context, address, data, addr_byte_size))
10779 return false;
10780
10781 address = address + 4;
10782 }
10783 else
10784 {
10785 // // Store as two word-aligned words in the correct order for current endianness.
10786 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10787 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10788 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10789 if (!success)
10790 return false;
10791
10792 data_reg.num = start_reg + d + r;
10793
10794 if (m_byte_order == eByteOrderBig)
10795 {
10796 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10797 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10798 return false;
10799
10800 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10801 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10802 return false;
10803 }
10804 else
10805 {
10806 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10807 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10808 return false;
10809
10810 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10811 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10812 return false;
10813 }
10814 // address = address+8;
10815 address = address + 8;
10816 }
10817 }
10818 }
10819 return true;
10820}
10821
Caroline Tice917ad352011-03-31 05:05:30 +000010822// A8.6.320
10823// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10824// an optional offset.
10825bool
10826EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10827{
10828#if 0
10829 if ConditionPassed() then
10830 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10831 base = if n == 15 then Align(PC,4) else R[n];
10832 address = if add then (base + imm32) else (base - imm32);
10833 if single_reg then
10834 S[d] = MemA[address,4];
10835 else
10836 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10837 // Combine the word-aligned words in the correct order for current endianness.
10838 D[d] = if BigEndian() then word1:word2 else word2:word1;
10839#endif
10840
10841 bool success = false;
10842
10843 if (ConditionPassed (opcode))
10844 {
10845 bool single_reg;
10846 bool add;
10847 uint32_t imm32;
10848 uint32_t d;
10849 uint32_t n;
10850
10851 switch (encoding)
10852 {
10853 case eEncodingT1:
10854 case eEncodingA1:
10855 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10856 single_reg = false;
10857 add = BitIsSet (opcode, 23);
10858 imm32 = Bits32 (opcode, 7, 0) << 2;
10859
10860 // d = UInt(D:Vd); n = UInt(Rn);
10861 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10862 n = Bits32 (opcode, 19, 16);
10863
10864 break;
10865
10866 case eEncodingT2:
10867 case eEncodingA2:
10868 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10869 single_reg = true;
10870 add = BitIsSet (opcode, 23);
10871 imm32 = Bits32 (opcode, 7, 0) << 2;
10872
10873 // d = UInt(Vd:D); n = UInt(Rn);
10874 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10875 n = Bits32 (opcode, 19, 16);
10876
10877 break;
10878
10879 default:
10880 return false;
10881 }
10882 Register base_reg;
10883 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10884
10885 uint32_t Rn = ReadCoreReg (n, &success);
10886 if (!success)
10887 return false;
10888
10889 // base = if n == 15 then Align(PC,4) else R[n];
10890 uint32_t base;
10891 if (n == 15)
10892 base = AlignPC (Rn);
10893 else
10894 base = Rn;
10895
10896 // address = if add then (base + imm32) else (base - imm32);
10897 addr_t address;
10898 if (add)
10899 address = base + imm32;
10900 else
10901 address = base - imm32;
10902
10903 const uint32_t addr_byte_size = GetAddressByteSize();
10904 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
10905
10906 EmulateInstruction::Context context;
10907 context.type = eContextRegisterLoad;
10908 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010909
Caroline Tice917ad352011-03-31 05:05:30 +000010910 if (single_reg)
10911 {
10912 // S[d] = MemA[address,4];
10913 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10914 if (!success)
10915 return false;
10916
10917 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
10918 return false;
10919 }
10920 else
10921 {
10922 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
10923 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10924 if (!success)
10925 return false;
10926
10927 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
10928 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10929 if (!success)
10930 return false;
10931 // // Combine the word-aligned words in the correct order for current endianness.
10932 // D[d] = if BigEndian() then word1:word2 else word2:word1;
10933 uint64_t data64;
10934 if (m_byte_order == eByteOrderBig)
10935 {
10936 data64 = word1;
10937 data64 = (data64 << 32) | word2;
10938 }
10939 else
10940 {
10941 data64 = word2;
10942 data64 = (data64 << 32) | word1;
10943 }
10944
10945 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
10946 return false;
10947 }
10948 }
10949 return true;
10950}
Caroline Tice424652f2011-03-31 05:38:36 +000010951
10952// A8.6.400 VSTR
10953// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
10954// optional offset.
10955bool
10956EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
10957{
10958#if 0
10959 if ConditionPassed() then
10960 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10961 address = if add then (R[n] + imm32) else (R[n] - imm32);
10962 if single_reg then
10963 MemA[address,4] = S[d];
10964 else
10965 // Store as two word-aligned words in the correct order for current endianness.
10966 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
10967 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
10968#endif
10969
10970 bool success = false;
10971
10972 if (ConditionPassed (opcode))
10973 {
10974 bool single_reg;
10975 bool add;
10976 uint32_t imm32;
10977 uint32_t d;
10978 uint32_t n;
10979
10980 switch (encoding)
10981 {
10982 case eEncodingT1:
10983 case eEncodingA1:
10984 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10985 single_reg = false;
10986 add = BitIsSet (opcode, 23);
10987 imm32 = Bits32 (opcode, 7, 0) << 2;
10988
10989 // d = UInt(D:Vd); n = UInt(Rn);
10990 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10991 n = Bits32 (opcode, 19, 16);
10992
10993 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
10994 if ((n == 15) && (CurrentInstrSet() != eModeARM))
10995 return false;
10996
10997 break;
10998
10999 case eEncodingT2:
11000 case eEncodingA2:
11001 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
11002 single_reg = true;
11003 add = BitIsSet (opcode, 23);
11004 imm32 = Bits32 (opcode, 7, 0) << 2;
11005
11006 // d = UInt(Vd:D); n = UInt(Rn);
11007 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11008 n = Bits32 (opcode, 19, 16);
11009
11010 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11011 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11012 return false;
11013
11014 break;
11015
11016 default:
11017 return false;
11018 }
11019
11020 Register base_reg;
11021 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11022
11023 uint32_t Rn = ReadCoreReg (n, &success);
11024 if (!success)
11025 return false;
11026
11027 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11028 addr_t address;
11029 if (add)
11030 address = Rn + imm32;
11031 else
11032 address = Rn - imm32;
11033
11034 const uint32_t addr_byte_size = GetAddressByteSize();
11035 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11036
11037 Register data_reg;
11038 data_reg.SetRegister (eRegisterKindDWARF, start_reg + d);
11039 EmulateInstruction::Context context;
11040 context.type = eContextRegisterStore;
11041 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11042
11043 if (single_reg)
11044 {
11045 // MemA[address,4] = S[d];
11046 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11047 if (!success)
11048 return false;
11049
11050 if (!MemAWrite (context, address, data, addr_byte_size))
11051 return false;
11052 }
11053 else
11054 {
11055 // // Store as two word-aligned words in the correct order for current endianness.
11056 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11057 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11058 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11059 if (!success)
11060 return false;
11061
11062 if (m_byte_order == eByteOrderBig)
11063 {
11064 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11065 return false;
11066
11067 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11068 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11069 return false;
11070 }
11071 else
11072 {
11073 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11074 return false;
11075
11076 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11077 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11078 return false;
11079 }
11080 }
11081 }
11082 return true;
11083}
Caroline Tice9121b352011-03-31 16:41:19 +000011084
11085// A8.6.307 VLDI1 (multiple single elements)
11086// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11087// element of each register is loaded.
11088bool
11089EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11090{
11091#if 0
11092 if ConditionPassed() then
11093 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11094 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11095 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11096 for r = 0 to regs-1
11097 for e = 0 to elements-1
11098 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11099 address = address + ebytes;
11100#endif
11101
11102 bool success = false;
11103
11104 if (ConditionPassed (opcode))
11105 {
11106 uint32_t regs;
11107 uint32_t alignment;
11108 uint32_t ebytes;
11109 uint32_t esize;
11110 uint32_t elements;
11111 uint32_t d;
11112 uint32_t n;
11113 uint32_t m;
11114 bool wback;
11115 bool register_index;
11116
11117 switch (encoding)
11118 {
11119 case eEncodingT1:
11120 case eEncodingA1:
11121 {
11122 // case type of
11123 // when ‘0111’
11124 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11125 // when ‘1010’
11126 // regs = 2; if align == ‘11’ then UNDEFINED;
11127 // when ‘0110’
11128 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11129 // when ‘0010’
11130 // regs = 4;
11131 // otherwise
11132 // SEE “Related encodings”;
11133 uint32_t type = Bits32 (opcode, 11, 8);
11134 uint32_t align = Bits32 (opcode, 5, 4);
11135 if (type == 7) // '0111'
11136 {
11137 regs = 1;
11138 if (BitIsSet (align, 1))
11139 return false;
11140 }
11141 else if (type == 10) // '1010'
11142 {
11143 regs = 2;
11144 if (align == 3)
11145 return false;
11146
11147 }
11148 else if (type == 6) // '0110'
11149 {
11150 regs = 3;
11151 if (BitIsSet (align, 1))
11152 return false;
11153 }
11154 else if (type == 2) // '0010'
11155 {
11156 regs = 4;
11157 }
11158 else
11159 return false;
11160
11161 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11162 if (align == 0)
11163 alignment = 1;
11164 else
11165 alignment = 4 << align;
11166
11167 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11168 ebytes = 1 << Bits32 (opcode, 7, 6);
11169 esize = 8 * ebytes;
11170 elements = 8 / ebytes;
11171
11172 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11173 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11174 n = Bits32 (opcode, 19, 15);
11175 m = Bits32 (opcode, 3, 0);
11176
11177 // wback = (m != 15); register_index = (m != 15 && m != 13);
11178 wback = (m != 15);
11179 register_index = ((m != 15) && (m != 13));
11180
11181 // if d+regs > 32 then UNPREDICTABLE;
11182 if ((d + regs) > 32)
11183 return false;
11184 }
11185 break;
11186
11187 default:
11188 return false;
11189 }
11190
11191 Register base_reg;
11192 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11193
11194 uint32_t Rn = ReadCoreReg (n, &success);
11195 if (!success)
11196 return false;
11197
11198 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11199 addr_t address = Rn;
11200 if ((address % alignment) != 0)
11201 return false;
11202
11203 EmulateInstruction::Context context;
11204 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11205 if (wback)
11206 {
11207 uint32_t Rm = ReadCoreReg (m, &success);
11208 if (!success)
11209 return false;
11210
11211 uint32_t offset;
11212 if (register_index)
11213 offset = Rm;
11214 else
11215 offset = 8 * regs;
11216
11217 uint32_t value = Rn + offset;
11218 context.type = eContextAdjustBaseRegister;
11219 context.SetRegisterPlusOffset (base_reg, offset);
11220
11221 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11222 return false;
11223
11224 }
11225
11226 // for r = 0 to regs-1
11227 for (int r = 0; r < regs; ++r)
11228 {
11229 // for e = 0 to elements-1
11230 uint64_t assembled_data = 0;
11231 for (int e = 0; e < elements; ++e)
11232 {
11233 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11234 context.type = eContextRegisterLoad;
11235 context.SetRegisterPlusOffset (base_reg, address - Rn);
11236 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11237 if (!success)
11238 return false;
11239
11240 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11241
11242 // address = address + ebytes;
11243 address = address + ebytes;
11244 }
11245 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11246 return false;
11247 }
11248 }
11249 return true;
11250}
11251
Caroline Ticeb6281b12011-03-31 17:58:23 +000011252// A8.6.308 VLD1 (single element to one lane)
11253//
11254bool
11255EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11256{
11257#if 0
11258 if ConditionPassed() then
11259 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11260 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11261 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11262 Elem[D[d],index,esize] = MemU[address,ebytes];
11263#endif
11264
11265 bool success = false;
11266
11267 if (ConditionPassed (opcode))
11268 {
11269 uint32_t ebytes;
11270 uint32_t esize;
11271 uint32_t index;
11272 uint32_t alignment;
11273 uint32_t d;
11274 uint32_t n;
11275 uint32_t m;
11276 bool wback;
11277 bool register_index;
11278
11279 switch (encoding)
11280 {
11281 case eEncodingT1:
11282 case eEncodingA1:
11283 {
11284 uint32_t size = Bits32 (opcode, 11, 10);
11285 uint32_t index_align = Bits32 (opcode, 7, 4);
11286 // if size == ‘11’ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011287 if (size == 3)
11288 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011289 // case size of
11290 if (size == 0) // when '00'
11291 {
11292 // if index_align<0> != ‘0’ then UNDEFINED;
11293 if (BitIsClear (index_align, 0))
11294 return false;
11295
11296 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11297 ebytes = 1;
11298 esize = 8;
11299 index = Bits32 (index_align, 3, 1);
11300 alignment = 1;
11301 }
11302 else if (size == 1) // when ‘01’
11303 {
11304 // if index_align<1> != ‘0’ then UNDEFINED;
11305 if (BitIsClear (index_align, 1))
11306 return false;
11307
11308 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11309 ebytes = 2;
11310 esize = 16;
11311 index = Bits32 (index_align, 3, 2);
11312
11313 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11314 if (BitIsClear (index_align, 0))
11315 alignment = 1;
11316 else
11317 alignment = 2;
11318 }
11319 else if (size == 2) // when ‘10’
11320 {
11321 // if index_align<2> != ‘0’ then UNDEFINED;
11322 if (BitIsClear (index_align, 2))
11323 return false;
11324
11325 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11326 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11327 return false;
11328
11329 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11330 ebytes = 4;
11331 esize = 32;
11332 index = Bit32 (index_align, 3);
11333
11334 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11335 if (Bits32 (index_align, 1, 0) == 0)
11336 alignment = 1;
11337 else
11338 alignment = 4;
11339 }
11340 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11341 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11342 n = Bits32 (opcode, 19, 16);
11343 m = Bits32 (opcode, 3, 0);
11344
11345 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11346 wback = (m != 15);
11347 register_index = ((m != 15) && (m != 13));
11348
11349 if (n == 15)
11350 return false;
11351
11352 }
11353 break;
11354
11355 default:
11356 return false;
11357 }
11358
11359 Register base_reg;
11360 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11361
11362 uint32_t Rn = ReadCoreReg (n, &success);
11363 if (!success)
11364 return false;
11365
11366 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11367 addr_t address = Rn;
11368 if ((address % alignment) != 0)
11369 return false;
11370
11371 EmulateInstruction::Context context;
11372 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11373 if (wback)
11374 {
11375 uint32_t Rm = ReadCoreReg (m, &success);
11376 if (!success)
11377 return false;
11378
11379 uint32_t offset;
11380 if (register_index)
11381 offset = Rm;
11382 else
11383 offset = ebytes;
11384
11385 uint32_t value = Rn + offset;
11386
11387 context.type = eContextAdjustBaseRegister;
11388 context.SetRegisterPlusOffset (base_reg, offset);
11389
11390 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11391 return false;
11392 }
11393
11394 // Elem[D[d],index,esize] = MemU[address,ebytes];
11395 uint32_t element = MemURead (context, address, esize, 0, &success);
11396 if (!success)
11397 return false;
11398
11399 element = element << (index * esize);
11400
11401 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11402 if (!success)
11403 return false;
11404
11405 uint64_t all_ones = -1;
11406 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11407 // at element & to the right of element.
11408 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011409 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 +000011410 // now mask should be 0's where element goes & 1's
11411 // everywhere else.
11412
11413 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11414 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11415
11416 context.type = eContextRegisterLoad;
11417 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11418 return false;
11419 }
11420 return true;
11421}
11422
Caroline Tice1e542e32011-03-31 18:44:04 +000011423// A8.6.391 VST1 (multiple single elements)
11424// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11425// interleaving. Every element of each register is stored.
11426bool
11427EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11428{
11429#if 0
11430 if ConditionPassed() then
11431 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11432 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11433 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11434 for r = 0 to regs-1
11435 for e = 0 to elements-1
11436 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11437 address = address + ebytes;
11438#endif
11439
11440 bool success = false;
11441
11442 if (ConditionPassed (opcode))
11443 {
11444 uint32_t regs;
11445 uint32_t alignment;
11446 uint32_t ebytes;
11447 uint32_t esize;
11448 uint32_t elements;
11449 uint32_t d;
11450 uint32_t n;
11451 uint32_t m;
11452 bool wback;
11453 bool register_index;
11454
11455 switch (encoding)
11456 {
11457 case eEncodingT1:
11458 case eEncodingA1:
11459 {
11460 uint32_t type = Bits32 (opcode, 11, 8);
11461 uint32_t align = Bits32 (opcode, 5, 4);
11462
11463 // case type of
11464 if (type == 7) // when ‘0111’
11465 {
11466 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11467 regs = 1;
11468 if (BitIsSet (align, 1))
11469 return false;
11470 }
11471 else if (type == 10) // when ‘1010’
11472 {
11473 // regs = 2; if align == ‘11’ then UNDEFINED;
11474 regs = 2;
11475 if (align == 3)
11476 return false;
11477 }
11478 else if (type == 6) // when ‘0110’
11479 {
11480 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11481 regs = 3;
11482 if (BitIsSet (align, 1))
11483 return false;
11484 }
11485 else if (type == 2) // when ‘0010’
11486 // regs = 4;
11487 regs = 4;
11488 else // otherwise
11489 // SEE “Related encodings”;
11490 return false;
11491
11492 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11493 if (align == 0)
11494 alignment = 0;
11495 else
11496 alignment = 4 << align;
11497
11498 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11499 ebytes = 1 << Bits32 (opcode,7, 6);
11500 esize = 8 * ebytes;
11501 elements = 8 / ebytes;
11502
11503 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11504 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11505 n = Bits32 (opcode, 19, 16);
11506 m = Bits32 (opcode, 3, 0);
11507
11508 // wback = (m != 15); register_index = (m != 15 && m != 13);
11509 wback = (m != 15);
11510 register_index = ((m != 15) && (m != 13));
11511
11512 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11513 if ((d + regs) > 32)
11514 return false;
11515
11516 if (n == 15)
11517 return false;
11518
11519 }
11520 break;
11521
11522 default:
11523 return false;
11524 }
11525
11526 Register base_reg;
11527 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11528
11529 uint32_t Rn = ReadCoreReg (n, &success);
11530 if (!success)
11531 return false;
11532
11533 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11534 addr_t address = Rn;
11535 if ((address % alignment) != 0)
11536 return false;
11537
11538 EmulateInstruction::Context context;
11539 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11540 if (wback)
11541 {
11542 uint32_t Rm = ReadCoreReg (m, &success);
11543 if (!success)
11544 return false;
11545
11546 uint32_t offset;
11547 if (register_index)
11548 offset = Rm;
11549 else
11550 offset = 8 * regs;
11551
11552 context.type = eContextAdjustBaseRegister;
11553 context.SetRegisterPlusOffset (base_reg, offset);
11554
11555 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11556 return false;
11557 }
11558
11559 context.type = eContextRegisterStore;
11560 Register data_reg;
11561 data_reg.SetRegister (eRegisterKindDWARF, 0);
11562 // for r = 0 to regs-1
11563 for (int r = 0; r < regs; ++r)
11564 {
11565 data_reg.num = dwarf_d0 + d + r;
11566 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11567 if (!success)
11568 return false;
11569
11570 // for e = 0 to elements-1
11571 for (int e = 0; e < elements; ++e)
11572 {
11573 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011574 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011575
11576 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11577 if (!MemUWrite (context, address, word, ebytes))
11578 return false;
11579
11580 // address = address + ebytes;
11581 address = address + ebytes;
11582 }
11583 }
11584 }
11585 return true;
11586}
11587
Caroline Tice7b880942011-03-31 19:17:12 +000011588// A8.6.392 VST1 (single element from one lane)
11589// This instruction stores one element to memory from one element of a register.
11590bool
11591EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11592{
11593#if 0
11594 if ConditionPassed() then
11595 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11596 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11597 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11598 MemU[address,ebytes] = Elem[D[d],index,esize];
11599#endif
11600
11601 bool success = false;
11602
11603 if (ConditionPassed (opcode))
11604 {
11605 uint32_t ebytes;
11606 uint32_t esize;
11607 uint32_t index;
11608 uint32_t alignment;
11609 uint32_t d;
11610 uint32_t n;
11611 uint32_t m;
11612 bool wback;
11613 bool register_index;
11614
11615 switch (encoding)
11616 {
11617 case eEncodingT1:
11618 case eEncodingA1:
11619 {
11620 uint32_t size = Bits32 (opcode, 11, 10);
11621 uint32_t index_align = Bits32 (opcode, 7, 4);
11622
11623 // if size == ‘11’ then UNDEFINED;
11624 if (size == 3)
11625 return false;
11626
11627 // case size of
11628 if (size == 0) // when ‘00’
11629 {
11630 // if index_align<0> != ‘0’ then UNDEFINED;
11631 if (BitIsClear (index_align, 0))
11632 return false;
11633 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11634 ebytes = 1;
11635 esize = 8;
11636 index = Bits32 (index_align, 3, 1);
11637 alignment = 1;
11638 }
11639 else if (size == 1) // when ‘01’
11640 {
11641 // if index_align<1> != ‘0’ then UNDEFINED;
11642 if (BitIsClear (index_align, 1))
11643 return false;
11644
11645 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11646 ebytes = 2;
11647 esize = 16;
11648 index = Bits32 (index_align, 3, 2);
11649
11650 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11651 if (BitIsClear (index_align, 0))
11652 alignment = 1;
11653 else
11654 alignment = 2;
11655 }
11656 else if (size == 2) // when ‘10’
11657 {
11658 // if index_align<2> != ‘0’ then UNDEFINED;
11659 if (BitIsClear (index_align, 2))
11660 return false;
11661
11662 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11663 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11664 return false;
11665
11666 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11667 ebytes = 4;
11668 esize = 32;
11669 index = Bit32 (index_align, 3);
11670
11671 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11672 if (Bits32 (index_align, 1, 0) == 0)
11673 alignment = 1;
11674 else
11675 alignment = 4;
11676 }
11677 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11678 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11679 n = Bits32 (opcode, 19, 16);
11680 m = Bits32 (opcode, 3, 0);
11681
11682 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11683 wback = (m != 15);
11684 register_index = ((m != 15) && (m != 13));
11685
11686 if (n == 15)
11687 return false;
11688 }
11689 break;
11690
11691 default:
11692 return false;
11693 }
11694
11695 Register base_reg;
11696 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11697
11698 uint32_t Rn = ReadCoreReg (n, &success);
11699 if (!success)
11700 return false;
11701
11702 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11703 addr_t address = Rn;
11704 if ((address % alignment) != 0)
11705 return false;
11706
11707 EmulateInstruction::Context context;
11708 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11709 if (wback)
11710 {
11711 uint32_t Rm = ReadCoreReg (m, &success);
11712 if (!success)
11713 return false;
11714
11715 uint32_t offset;
11716 if (register_index)
11717 offset = Rm;
11718 else
11719 offset = ebytes;
11720
11721 context.type = eContextAdjustBaseRegister;
11722 context.SetRegisterPlusOffset (base_reg, offset);
11723
11724 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11725 return false;
11726 }
11727
11728 // MemU[address,ebytes] = Elem[D[d],index,esize];
11729 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11730 if (!success)
11731 return false;
11732
11733 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11734
11735 Register data_reg;
11736 data_reg.SetRegister (eRegisterKindDWARF, dwarf_d0 + d);
11737 context.type = eContextRegisterStore;
11738 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11739
11740 if (!MemUWrite (context, address, word, ebytes))
11741 return false;
11742 }
11743 return true;
11744}
11745
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011746// A8.6.309 VLD1 (single element to all lanes)
11747// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011748bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011749EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011750{
11751#if 0
11752 if ConditionPassed() then
11753 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11754 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11755 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11756 replicated_element = Replicate(MemU[address,ebytes], elements);
11757 for r = 0 to regs-1
11758 D[d+r] = replicated_element;
11759#endif
11760
11761 bool success = false;
11762
11763 if (ConditionPassed (opcode))
11764 {
11765 uint32_t ebytes;
11766 uint32_t elements;
11767 uint32_t regs;
11768 uint32_t alignment;
11769 uint32_t d;
11770 uint32_t n;
11771 uint32_t m;
11772 bool wback;
11773 bool register_index;
11774
11775 switch (encoding)
11776 {
11777 case eEncodingT1:
11778 case eEncodingA1:
11779 {
11780 //if size == ‘11’ || (size == ‘00’ && a == ‘1’) then UNDEFINED;
11781 uint32_t size = Bits32 (opcode, 7, 6);
11782 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11783 return false;
11784
11785 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == ‘0’ then 1 else 2;
11786 ebytes = 1 << size;
11787 elements = 8 / ebytes;
11788 if (BitIsClear (opcode, 5))
11789 regs = 1;
11790 else
11791 regs = 2;
11792
11793 //alignment = if a == ‘0’ then 1 else ebytes;
11794 if (BitIsClear (opcode, 4))
11795 alignment = 1;
11796 else
11797 alignment = ebytes;
11798
11799 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11800 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11801 n = Bits32 (opcode, 19, 16);
11802 m = Bits32 (opcode, 3, 0);
11803
11804 //wback = (m != 15); register_index = (m != 15 && m != 13);
11805 wback = (m != 15);
11806 register_index = ((m != 15) && (m != 13));
11807
11808 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11809 if ((d + regs) > 32)
11810 return false;
11811
11812 if (n == 15)
11813 return false;
11814 }
11815 break;
11816
11817 default:
11818 break;
11819 }
11820
11821 Register base_reg;
11822 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
11823
11824 uint32_t Rn = ReadCoreReg (n, &success);
11825 if (!success)
11826 return false;
11827
11828 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11829 addr_t address = Rn;
11830 if ((address % alignment) != 0)
11831 return false;
11832
11833 EmulateInstruction::Context context;
11834 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11835 if (wback)
11836 {
11837 uint32_t Rm = ReadCoreReg (m, &success);
11838 if (!success)
11839 return false;
11840
11841 uint32_t offset;
11842 if (register_index)
11843 offset = Rm;
11844 else
11845 offset = ebytes;
11846
11847 context.type = eContextAdjustBaseRegister;
11848 context.SetRegisterPlusOffset (base_reg, offset);
11849
11850 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11851 return false;
11852 }
11853
11854 // replicated_element = Replicate(MemU[address,ebytes], elements);
11855
11856 context.type = eContextRegisterLoad;
11857 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11858 if (!success)
11859 return false;
11860
11861 uint64_t replicated_element;
11862 uint32_t esize = ebytes * 8;
11863 for (int e = 0; e < elements; ++e)
11864 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11865
11866 // for r = 0 to regs-1
11867 for (int r = 0; r < regs; ++r)
11868 {
11869 // D[d+r] = replicated_element;
11870 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11871 return false;
11872 }
11873 }
11874 return true;
11875}
11876
Caroline Tice1f954f52011-04-11 15:51:10 +000011877// B6.2.13 SUBS PC, LR and related instructions
11878//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
11879// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
11880bool
11881EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
11882{
11883#if 0
11884 if ConditionPassed() then
11885 EncodingSpecificOperations();
11886 if CurrentInstrSet() == InstrSet_ThumbEE then
11887 UNPREDICTABLE;
11888 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11889 case opcode of
11890 when 0000 result = R[n] AND operand2; // AND
11891 when 0001 result = R[n] EOR operand2; // EOR
11892 when 0010 (result, -, -) = AddWithCarry(R[n], NOT(operand2), 1’); // SUB
11893 when 0011 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, 1’); // RSB
11894 when 0100 (result, -, -) = AddWithCarry(R[n], operand2, 0’); // ADD
11895 when 0101 (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
11896 when 0110 (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
11897 when 0111 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
11898 when 1100 result = R[n] OR operand2; // ORR
11899 when 1101 result = operand2; // MOV
11900 when 1110 result = R[n] AND NOT(operand2); // BIC
11901 when 1111 result = NOT(operand2); // MVN
11902 CPSRWriteByInstr(SPSR[], 1111’, TRUE);
11903 BranchWritePC(result);
11904#endif
11905
11906 bool success = false;
11907
11908 if (ConditionPassed (opcode))
11909 {
11910 uint32_t n;
11911 uint32_t m;
11912 uint32_t imm32;
11913 bool register_form;
11914 ARM_ShifterType shift_t;
11915 uint32_t shift_n;
11916 uint32_t code;
11917
11918 switch (encoding)
11919 {
11920 case eEncodingT1:
11921 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
11922 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = ‘0010’; // = SUB
11923 n = 14;
11924 imm32 = Bits32 (opcode, 7, 0);
11925 register_form = false;
11926 code = 2;
11927
11928 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
11929 if (InITBlock() && !LastInITBlock())
11930 return false;
11931
11932 break;
11933
11934 case eEncodingA1:
11935 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
11936 n = Bits32 (opcode, 19, 16);
11937 imm32 = ARMExpandImm (opcode);
11938 register_form = false;
11939 code = Bits32 (opcode, 24, 21);
11940
11941 break;
11942
11943 case eEncodingA2:
11944 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
11945 n = Bits32 (opcode, 19, 16);
11946 m = Bits32 (opcode, 3, 0);
11947 register_form = true;
11948
11949 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
11950 shift_n = DecodeImmShiftARM (opcode, shift_t);
11951
11952 break;
11953
11954 default:
11955 return false;
11956 }
11957
11958 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11959 uint32_t operand2;
11960 if (register_form)
11961 {
11962 uint32_t Rm = ReadCoreReg (m, &success);
11963 if (!success)
11964 return false;
11965
11966 operand2 = Shift (Rm, shift_t, shift_n, APSR_C);
11967
11968 }
11969 else
11970 {
11971 operand2 = imm32;
11972 }
11973
11974 uint32_t Rn = ReadCoreReg (n, &success);
11975 if (!success)
11976 return false;
11977
11978 AddWithCarryResult result;
11979
11980 // case opcode of
11981 switch (code)
11982 {
11983 case 0: // when ‘0000’
11984 // result = R[n] AND operand2; // AND
11985 result.result = Rn & operand2;
11986 break;
11987
11988 case 1: // when ‘0001’
11989 // result = R[n] EOR operand2; // EOR
11990 result.result = Rn ^ operand2;
11991 break;
11992
11993 case 2: // when ‘0010’
11994 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), ‘1’); // SUB
11995 result = AddWithCarry (Rn, ~(operand2), 1);
11996 break;
11997
11998 case 3: // when ‘0011’
11999 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, ‘1’); // RSB
12000 result = AddWithCarry (~(Rn), operand2, 1);
12001 break;
12002
12003 case 4: // when ‘0100’
12004 // (result, -, -) = AddWithCarry(R[n], operand2, ‘0’); // ADD
12005 result = AddWithCarry (Rn, operand2, 0);
12006 break;
12007
12008 case 5: // when ‘0101’
12009 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12010 result = AddWithCarry (Rn, operand2, APSR_C);
12011 break;
12012
12013 case 6: // when ‘0110’
12014 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12015 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12016 break;
12017
12018 case 7: // when ‘0111’
12019 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12020 result = AddWithCarry (~(Rn), operand2, APSR_C);
12021 break;
12022
12023 case 10: // when ‘1100’
12024 // result = R[n] OR operand2; // ORR
12025 result.result = Rn | operand2;
12026 break;
12027
12028 case 11: // when ‘1101’
12029 // result = operand2; // MOV
12030 result.result = operand2;
12031 break;
12032
12033 case 12: // when ‘1110’
12034 // result = R[n] AND NOT(operand2); // BIC
12035 result.result = Rn & ~(operand2);
12036 break;
12037
12038 case 15: // when ‘1111’
12039 // result = NOT(operand2); // MVN
12040 result.result = ~(operand2);
12041 break;
12042
12043 default:
12044 return false;
12045 }
12046 // CPSRWriteByInstr(SPSR[], ‘1111’, TRUE);
12047
12048 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12049 // the best.
12050 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12051 if (!success)
12052 return false;
12053
12054 CPSRWriteByInstr (spsr, 15, true);
12055
12056 // BranchWritePC(result);
12057 EmulateInstruction::Context context;
12058 context.type = eContextAdjustPC;
12059 context.SetImmediate (result.result);
12060
12061 BranchWritePC (context, result.result);
12062 }
12063 return true;
12064}
12065
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012066EmulateInstructionARM::ARMOpcode*
12067EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012068{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012069 static ARMOpcode
12070 g_arm_opcodes[] =
12071 {
12072 //----------------------------------------------------------------------
12073 // Prologue instructions
12074 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012075
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012076 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012077 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12078 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012079
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012080 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012081 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12082 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012083 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012084 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12085 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12086 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012087
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012088 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012089 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12090 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012091
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012092 // push one register
12093 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012094 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012095
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012096 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012097 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12098 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012099
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012100 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012101 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012102 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012103
Caroline Tice4f605582011-03-31 00:02:51 +000012104 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12105 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12106 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12107 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012108
12109 //----------------------------------------------------------------------
12110 // Supervisor Call (previously Software Interrupt)
12111 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012112 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012113
12114 //----------------------------------------------------------------------
12115 // Branch instructions
12116 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012117 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012118 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012119 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12120 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12121 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012122 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012123 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012124 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012125 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012126
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012127 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012128 // Data-processing instructions
12129 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012130 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012131 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012132 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012133 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012134 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012135 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012136 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012137 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012138 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012139 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012140 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012141 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12142 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012143 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012144 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012145 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012146 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012147 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012148 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012149 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012150 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012151 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012152 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012153 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012154 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012155 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012156 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012157 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012158 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012159 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012160 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012161 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012162 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012163 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012164 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012165 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012166 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012167 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012168 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012169 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012170 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012171 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012172 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012173 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012174 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012175 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012176 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012177 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012178 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012179 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012180 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012181 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012182 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012183 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012184 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012185
Caroline Tice89c6d582011-03-29 19:53:44 +000012186 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012187 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12188 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012189 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012190 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012191 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012192 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012193 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012194 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012195 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012196 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012197 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012198 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012199 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012200 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012201 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012202 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012203 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012204 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012205 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012206 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012207 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012208 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012209 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012210 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012211 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012212 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012213 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012214 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012215 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012216 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012217 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012218 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012219 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012220 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012221 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012222 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012223
12224 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012225 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12226 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012227
12228 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012229 // Load instructions
12230 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012231 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12232 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12233 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12234 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12235 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12236 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12237 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12238 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12239 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12240 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12241 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12242 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12243 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12244 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12245 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12246 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12247 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12248 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012249 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12250 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12251 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12252 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012253 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12254 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012255 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012256
12257 //----------------------------------------------------------------------
12258 // Store instructions
12259 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012260 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12261 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12262 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12263 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12264 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12265 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12266 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12267 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12268 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012269 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012270 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012271 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12272 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12273 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12274 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12275 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012276 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012277
Caroline Tice6bf65162011-03-03 17:42:58 +000012278 //----------------------------------------------------------------------
12279 // Other instructions
12280 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012281 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12282 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12283 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12284 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12285 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012286
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012287 };
12288 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12289
12290 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12291 {
12292 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
12293 return &g_arm_opcodes[i];
12294 }
12295 return NULL;
12296}
Greg Clayton64c84432011-01-21 22:02:52 +000012297
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012298
12299EmulateInstructionARM::ARMOpcode*
12300EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +000012301{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012302
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012303 static ARMOpcode
12304 g_thumb_opcodes[] =
12305 {
12306 //----------------------------------------------------------------------
12307 // Prologue instructions
12308 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012309
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012310 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012311 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12312 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12313 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012314
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012315 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012316 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012317 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012318 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012319 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012320 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012321
Johnny Chen864a8e82011-02-18 00:07:39 +000012322 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012323 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012324
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012325 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012326 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12327 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12328 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12329 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12330 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012331
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012332 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012333 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12334 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012335
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012336 //----------------------------------------------------------------------
12337 // Epilogue instructions
12338 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012339
Caroline Tice4f605582011-03-31 00:02:51 +000012340 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12341 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12342 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12343 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12344 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12345 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12346 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012347
12348 //----------------------------------------------------------------------
12349 // Supervisor Call (previously Software Interrupt)
12350 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012351 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012352
12353 //----------------------------------------------------------------------
12354 // If Then makes up to four following instructions conditional.
12355 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012356 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012357
12358 //----------------------------------------------------------------------
12359 // Branch instructions
12360 //----------------------------------------------------------------------
12361 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012362 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12363 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12364 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12365 { 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 +000012366 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012367 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012368 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012369 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12370 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012371 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012372 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012373 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012374 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012375 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012376 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012377 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012378 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012379 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012380 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012381
12382 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012383 // Data-processing instructions
12384 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012385 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012386 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012387 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012388 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12389 { 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 +000012390 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012391 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012392 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012393 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012394 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012395 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12396 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12397 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012398 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012399 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012400 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012401 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12402 { 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 +000012403 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012404 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012405 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012406 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12407 { 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 +000012408 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012409 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012410 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012411 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12412 { 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 +000012413 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012414 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012415 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012416 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12417 { 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 +000012418 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012419 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12420 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012421 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012422 { 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 +000012423 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012424 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012425 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012426 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12427 { 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 +000012428 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012429 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12430 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12431 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12432 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012433 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012434 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12435 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12436 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12437 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012438 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012439 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12440 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012441 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012442 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12443 { 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 +000012444 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012445 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012446 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012447 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012448 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012449 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012450 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012451 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12452 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012453
Johnny Chen7c5234d2011-02-18 23:41:11 +000012454
Johnny Chen338bf542011-02-10 19:29:03 +000012455 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012456 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012457 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012458 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012459 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012460 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012461 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012462 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12463 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12464 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012465 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012466 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012467 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012468 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12469 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012470 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012471 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012472 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012473 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12474 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012475 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012476 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12477 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012478 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012479 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012480 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012481 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012482 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012483 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12484 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012485 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012486 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12487 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012488 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012489 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12490 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012491 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012492 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12493 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012494 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012495 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12496 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012497 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012498 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12499 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012500 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012501 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012502 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012503 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012504 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012505 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12506 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012507 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012508 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012509 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012510 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012511
12512 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012513 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012514
12515 //----------------------------------------------------------------------
12516 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12517 // otherwise the wrong instructions will be selected.
12518 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012519
Caroline Tice080bf612011-04-05 18:46:00 +000012520 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12521 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12522
Johnny Chen26863dc2011-02-09 23:43:29 +000012523 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012524 // Load instructions
12525 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012526 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12527 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12528 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12529 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12530 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12531 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12532 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012533 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012534 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12535 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12536 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12537 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12538 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012539 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012540 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12541 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12542 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12543 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12544 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12545 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12546 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12547 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12548 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12549 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12550 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12551 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12552 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12553 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12554 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12555 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12556 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12557 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12558 { 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 +000012559 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012560 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12561 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12562 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12563 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012564 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12565 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012566 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012567
12568 //----------------------------------------------------------------------
12569 // Store instructions
12570 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012571 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12572 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12573 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12574 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12575 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12576 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12577 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12578 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12579 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12580 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12581 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12582 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12583 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12584 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12585 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12586 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012587 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12588 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12589 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12590 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12591 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012592 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012593
12594 //----------------------------------------------------------------------
12595 // Other instructions
12596 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012597 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12598 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12599 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12600 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12601 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12602 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12603 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12604 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012605 };
12606
12607 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12608 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12609 {
12610 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
12611 return &g_thumb_opcodes[i];
12612 }
12613 return NULL;
12614}
Greg Clayton64c84432011-01-21 22:02:52 +000012615
Greg Clayton31e2a382011-01-30 20:03:56 +000012616bool
Greg Clayton395fc332011-02-15 21:59:32 +000012617EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012618{
Caroline Tice080bf612011-04-05 18:46:00 +000012619 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012620 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012621 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012622 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012623 {
Greg Clayton395fc332011-02-15 21:59:32 +000012624 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12625 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12626 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12627 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12628 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12629 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12630 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12631 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12632 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12633 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +000012634 }
12635 return m_arm_isa != 0;
12636}
12637
Caroline Tice080bf612011-04-05 18:46:00 +000012638bool
12639EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr)
12640{
12641 m_opcode = insn_opcode;
12642
12643 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12644 m_opcode_mode = eModeThumb;
12645 else
12646 {
12647 AddressClass addr_class = inst_addr.GetAddressClass();
12648
12649 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12650 m_opcode_mode = eModeARM;
12651 else if (addr_class == eAddressClassCodeAlternateISA)
12652 m_opcode_mode = eModeThumb;
12653 else
12654 return false;
12655 }
12656 return true;
12657}
Greg Clayton31e2a382011-01-30 20:03:56 +000012658
Greg Clayton64c84432011-01-21 22:02:52 +000012659bool
12660EmulateInstructionARM::ReadInstruction ()
12661{
12662 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012663 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012664 if (success)
12665 {
12666 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12667 if (success)
12668 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012669 Context read_inst_context;
12670 read_inst_context.type = eContextReadOpcode;
12671 read_inst_context.SetNoArgs ();
12672
Greg Claytonb3448432011-03-24 21:19:54 +000012673 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012674 {
Greg Claytonb3448432011-03-24 21:19:54 +000012675 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012676 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012677
12678 if (success)
12679 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012680 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012681 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012682 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012683 }
12684 else
12685 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012686 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012687 }
12688 }
12689 }
12690 else
12691 {
Greg Claytonb3448432011-03-24 21:19:54 +000012692 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012693 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012694 }
12695 }
12696 }
12697 if (!success)
12698 {
Greg Claytonb3448432011-03-24 21:19:54 +000012699 m_opcode_mode = eModeInvalid;
12700 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012701 }
12702 return success;
12703}
12704
Johnny Chenee9b1f72011-02-09 01:00:31 +000012705uint32_t
12706EmulateInstructionARM::ArchVersion ()
12707{
12708 return m_arm_isa;
12709}
12710
Greg Clayton64c84432011-01-21 22:02:52 +000012711bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012712EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012713{
Greg Clayton64c84432011-01-21 22:02:52 +000012714
Greg Clayton7bc39082011-03-24 23:53:38 +000012715 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012716
12717 if (cond == UINT32_MAX)
12718 return false;
12719
12720 bool result = false;
12721 switch (UnsignedBits(cond, 3, 1))
12722 {
Caroline Tice080bf612011-04-05 18:46:00 +000012723 case 0:
12724 if (m_opcode_cpsr == 0)
12725 return true;
12726 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12727 break;
12728 case 1:
12729 if (m_opcode_cpsr == 0)
12730 return true;
12731 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12732 break;
12733 case 2:
12734 if (m_opcode_cpsr == 0)
12735 return true;
12736 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12737 break;
12738 case 3:
12739 if (m_opcode_cpsr == 0)
12740 return true;
12741 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12742 break;
12743 case 4:
12744 if (m_opcode_cpsr == 0)
12745 return true;
12746 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12747 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012748 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012749 if (m_opcode_cpsr == 0)
12750 return true;
12751 else
12752 {
Greg Claytonb3448432011-03-24 21:19:54 +000012753 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12754 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012755 result = n == v;
12756 }
12757 break;
12758 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012759 if (m_opcode_cpsr == 0)
12760 return true;
12761 else
12762 {
Greg Claytonb3448432011-03-24 21:19:54 +000012763 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12764 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12765 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012766 }
12767 break;
12768 case 7:
12769 result = true;
12770 break;
12771 }
12772
12773 if (cond & 1)
12774 result = !result;
12775 return result;
12776}
12777
Johnny Chen9ee056b2011-02-08 00:06:35 +000012778uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012779EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012780{
Greg Claytonb3448432011-03-24 21:19:54 +000012781 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012782 {
12783 default:
12784 case eModeInvalid:
12785 break;
12786
12787 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012788 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012789
12790 case eModeThumb:
12791 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12792 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012793 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012794 const uint32_t byte_size = m_opcode.GetByteSize();
12795 if (byte_size == 2)
12796 {
12797 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12798 return Bits32(opcode, 11, 7);
12799 }
12800 else
12801 {
12802 assert (byte_size == 4);
12803 if (Bits32(opcode, 31, 27) == 0x1e &&
12804 Bits32(opcode, 15, 14) == 0x02 &&
12805 Bits32(opcode, 12, 12) == 0x00 &&
12806 Bits32(opcode, 25, 22) <= 0x0d)
12807 {
12808 return Bits32(opcode, 25, 22);
12809 }
12810 }
12811
12812 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012813 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012814 }
12815 return UINT32_MAX; // Return invalid value
12816}
12817
Johnny Chen9ee056b2011-02-08 00:06:35 +000012818bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012819EmulateInstructionARM::InITBlock()
12820{
12821 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12822}
12823
12824bool
12825EmulateInstructionARM::LastInITBlock()
12826{
12827 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12828}
12829
Caroline Ticeb27771d2011-03-03 22:37:46 +000012830bool
12831EmulateInstructionARM::BadMode (uint32_t mode)
12832{
12833
12834 switch (mode)
12835 {
12836 case 16: return false; // '10000'
12837 case 17: return false; // '10001'
12838 case 18: return false; // '10010'
12839 case 19: return false; // '10011'
12840 case 22: return false; // '10110'
12841 case 23: return false; // '10111'
12842 case 27: return false; // '11011'
12843 case 31: return false; // '11111'
12844 default: return true;
12845 }
12846 return true;
12847}
12848
12849bool
12850EmulateInstructionARM::CurrentModeIsPrivileged ()
12851{
Greg Claytonb3448432011-03-24 21:19:54 +000012852 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012853
12854 if (BadMode (mode))
12855 return false;
12856
12857 if (mode == 16)
12858 return false;
12859
12860 return true;
12861}
12862
12863void
12864EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
12865{
12866 bool privileged = CurrentModeIsPrivileged();
12867
12868 uint32_t tmp_cpsr = 0;
12869
Greg Claytonb3448432011-03-24 21:19:54 +000012870 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012871
12872 if (BitIsSet (bytemask, 3))
12873 {
12874 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
12875 if (affect_execstate)
12876 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
12877 }
12878
12879 if (BitIsSet (bytemask, 2))
12880 {
12881 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
12882 }
12883
12884 if (BitIsSet (bytemask, 1))
12885 {
12886 if (affect_execstate)
12887 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
12888 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
12889 if (privileged)
12890 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
12891 }
12892
12893 if (BitIsSet (bytemask, 0))
12894 {
12895 if (privileged)
12896 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
12897 if (affect_execstate)
12898 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
12899 if (privileged)
12900 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
12901 }
12902
Greg Claytonb3448432011-03-24 21:19:54 +000012903 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012904}
12905
12906
Johnny Chen098ae2d2011-02-12 00:50:05 +000012907bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000012908EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
12909{
12910 addr_t target;
12911
Johnny Chenee9b1f72011-02-09 01:00:31 +000012912 // Check the current instruction set.
12913 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012914 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012915 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000012916 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012917
Johnny Chen9ee056b2011-02-08 00:06:35 +000012918 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012919 return false;
12920
12921 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012922}
12923
12924// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
12925bool
Johnny Chen668b4512011-02-15 21:08:58 +000012926EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012927{
12928 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000012929 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
12930 // we want to record it and issue a WriteRegister callback so the clients
12931 // can track the mode changes accordingly.
12932 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012933
12934 if (BitIsSet(addr, 0))
12935 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012936 if (CurrentInstrSet() != eModeThumb)
12937 {
12938 SelectInstrSet(eModeThumb);
12939 cpsr_changed = true;
12940 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012941 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000012942 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012943 }
12944 else if (BitIsClear(addr, 1))
12945 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012946 if (CurrentInstrSet() != eModeARM)
12947 {
12948 SelectInstrSet(eModeARM);
12949 cpsr_changed = true;
12950 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012951 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000012952 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012953 }
12954 else
12955 return false; // address<1:0> == '10' => UNPREDICTABLE
12956
Johnny Chen0f309db2011-02-09 19:11:32 +000012957 if (cpsr_changed)
12958 {
Johnny Chen558133b2011-02-09 23:59:17 +000012959 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000012960 return false;
12961 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012962 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012963 return false;
12964
12965 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012966}
Greg Clayton64c84432011-01-21 22:02:52 +000012967
Johnny Chenee9b1f72011-02-09 01:00:31 +000012968// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
12969bool
Johnny Chen668b4512011-02-15 21:08:58 +000012970EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000012971{
12972 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000012973 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000012974 else
12975 return BranchWritePC((const Context)context, addr);
12976}
12977
Johnny Chen26863dc2011-02-09 23:43:29 +000012978// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
12979bool
Johnny Chen668b4512011-02-15 21:08:58 +000012980EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000012981{
12982 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000012983 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000012984 else
12985 return BranchWritePC((const Context)context, addr);
12986}
12987
Johnny Chenee9b1f72011-02-09 01:00:31 +000012988EmulateInstructionARM::Mode
12989EmulateInstructionARM::CurrentInstrSet ()
12990{
Greg Claytonb3448432011-03-24 21:19:54 +000012991 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012992}
12993
Greg Claytonb3448432011-03-24 21:19:54 +000012994// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000012995// ReadInstruction() is performed. This function has a side effect of updating
12996// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000012997bool
12998EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
12999{
Greg Claytonb3448432011-03-24 21:19:54 +000013000 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013001 switch (arm_or_thumb)
13002 {
13003 default:
13004 return false;
13005 eModeARM:
13006 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013007 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013008 break;
13009 eModeThumb:
13010 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013011 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013012 break;
13013 }
13014 return true;
13015}
13016
Johnny Chenef21b592011-02-10 01:52:38 +000013017// This function returns TRUE if the processor currently provides support for
13018// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13019// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13020bool
13021EmulateInstructionARM::UnalignedSupport()
13022{
13023 return (ArchVersion() >= ARMv7);
13024}
13025
Johnny Chenbf6ad172011-02-11 01:29:53 +000013026// The main addition and subtraction instructions can produce status information
13027// about both unsigned carry and signed overflow conditions. This status
13028// information can be used to synthesize multi-word additions and subtractions.
13029EmulateInstructionARM::AddWithCarryResult
13030EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13031{
13032 uint32_t result;
13033 uint8_t carry_out;
13034 uint8_t overflow;
13035
13036 uint64_t unsigned_sum = x + y + carry_in;
13037 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13038
13039 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013040// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013041 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013042
13043 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013044 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013045 else
13046 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013047
13048 AddWithCarryResult res = { result, carry_out, overflow };
13049 return res;
13050}
13051
Johnny Chen157b9592011-02-18 21:13:05 +000013052uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013053EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013054{
Johnny Chene39f22d2011-02-19 01:36:13 +000013055 uint32_t reg_kind, reg_num;
13056 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013057 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013058 case SP_REG:
13059 reg_kind = eRegisterKindGeneric;
13060 reg_num = LLDB_REGNUM_GENERIC_SP;
13061 break;
13062 case LR_REG:
13063 reg_kind = eRegisterKindGeneric;
13064 reg_num = LLDB_REGNUM_GENERIC_RA;
13065 break;
13066 case PC_REG:
13067 reg_kind = eRegisterKindGeneric;
13068 reg_num = LLDB_REGNUM_GENERIC_PC;
13069 break;
13070 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013071 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013072 {
13073 reg_kind = eRegisterKindDWARF;
13074 reg_num = dwarf_r0 + num;
13075 }
Johnny Chen157b9592011-02-18 21:13:05 +000013076 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013077 {
13078 assert(0 && "Invalid register number");
13079 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013080 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013081 }
13082 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013083 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013084
13085 // Read our register.
13086 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13087
13088 // When executing an ARM instruction , PC reads as the address of the current
13089 // instruction plus 8.
13090 // When executing a Thumb instruction , PC reads as the address of the current
13091 // instruction plus 4.
13092 if (num == 15)
13093 {
13094 if (CurrentInstrSet() == eModeARM)
13095 val += 8;
13096 else
13097 val += 4;
13098 }
Johnny Chen157b9592011-02-18 21:13:05 +000013099
13100 return val;
13101}
13102
Johnny Chenca67d1c2011-02-17 01:35:27 +000013103// Write the result to the ARM core register Rd, and optionally update the
13104// condition flags based on the result.
13105//
13106// This helper method tries to encapsulate the following pseudocode from the
13107// ARM Architecture Reference Manual:
13108//
13109// if d == 15 then // Can only occur for encoding A1
13110// ALUWritePC(result); // setflags is always FALSE here
13111// else
13112// R[d] = result;
13113// if setflags then
13114// APSR.N = result<31>;
13115// APSR.Z = IsZeroBit(result);
13116// APSR.C = carry;
13117// // APSR.V unchanged
13118//
13119// In the above case, the API client does not pass in the overflow arg, which
13120// defaults to ~0u.
13121bool
Johnny Chen10530c22011-02-17 22:37:12 +000013122EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13123 const uint32_t result,
13124 const uint32_t Rd,
13125 bool setflags,
13126 const uint32_t carry,
13127 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013128{
13129 if (Rd == 15)
13130 {
13131 if (!ALUWritePC (context, result))
13132 return false;
13133 }
13134 else
13135 {
Johnny Chena695f952011-02-23 21:24:25 +000013136 uint32_t reg_kind, reg_num;
13137 switch (Rd)
13138 {
13139 case SP_REG:
13140 reg_kind = eRegisterKindGeneric;
13141 reg_num = LLDB_REGNUM_GENERIC_SP;
13142 break;
13143 case LR_REG:
13144 reg_kind = eRegisterKindGeneric;
13145 reg_num = LLDB_REGNUM_GENERIC_RA;
13146 break;
13147 default:
13148 reg_kind = eRegisterKindDWARF;
13149 reg_num = dwarf_r0 + Rd;
13150 }
13151 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013152 return false;
13153 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013154 return WriteFlags (context, result, carry, overflow);
13155 }
13156 return true;
13157}
13158
13159// This helper method tries to encapsulate the following pseudocode from the
13160// ARM Architecture Reference Manual:
13161//
13162// APSR.N = result<31>;
13163// APSR.Z = IsZeroBit(result);
13164// APSR.C = carry;
13165// APSR.V = overflow
13166//
13167// Default arguments can be specified for carry and overflow parameters, which means
13168// not to update the respective flags.
13169bool
13170EmulateInstructionARM::WriteFlags (Context &context,
13171 const uint32_t result,
13172 const uint32_t carry,
13173 const uint32_t overflow)
13174{
Greg Claytonb3448432011-03-24 21:19:54 +000013175 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013176 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13177 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013178 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013179 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013180 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013181 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013182 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013183 {
13184 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13185 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013186 }
13187 return true;
13188}
13189
Greg Clayton64c84432011-01-21 22:02:52 +000013190bool
13191EmulateInstructionARM::EvaluateInstruction ()
13192{
Johnny Chenc315f862011-02-05 00:46:10 +000013193 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013194 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013195 m_it_session.ITAdvance();
13196
Caroline Tice080bf612011-04-05 18:46:00 +000013197
13198 ARMOpcode *opcode_data;
13199
13200 if (m_opcode_mode == eModeThumb)
13201 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32());
13202 else if (m_opcode_mode == eModeARM)
13203 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32());
13204 else
13205 return false;
13206
13207 if (!opcode_data)
13208 return false;
13209 // Verify that we're the right arch for this opcode
13210
13211 switch (m_arm_isa)
13212 {
13213 case ARMv4:
13214 if (opcode_data->variants != ARMvAll)
13215 return false;
13216 break;
13217
13218 case ARMv4T:
13219 if ((opcode_data->variants!= ARMvAll)
13220 && (opcode_data->variants != ARMV4T_ABOVE))
13221 return false;
13222 break;
13223
13224 case ARMv5T:
13225 case ARMv5TE:
13226 if ((opcode_data->variants != ARMvAll)
13227 && (opcode_data->variants != ARMV4T_ABOVE)
13228 && (opcode_data->variants != ARMV5_ABOVE))
13229 return false;
13230 break;
13231
13232 case ARMv5TEJ:
13233 if ((opcode_data->variants != ARMvAll)
13234 && (opcode_data->variants != ARMV4T_ABOVE)
13235 && (opcode_data->variants != ARMV5_ABOVE)
13236 && (opcode_data->variants != ARMV5J_ABOVE))
13237 return false;
13238 break;
13239
13240 case ARMv6:
13241 case ARMv6K:
13242 if ((opcode_data->variants != ARMvAll)
13243 && (opcode_data->variants != ARMV4T_ABOVE)
13244 && (opcode_data->variants != ARMV5_ABOVE)
13245 && (opcode_data->variants != ARMV5J_ABOVE)
13246 && (opcode_data->variants != ARMV6_ABOVE))
13247 return false;
13248 break;
13249
13250 case ARMv6T2:
13251 case ARMv7:
13252 case ARMv8:
13253 if ((opcode_data->variants != ARMvAll)
13254 && (opcode_data->variants != ARMV4T_ABOVE)
13255 && (opcode_data->variants != ARMV5_ABOVE)
13256 && (opcode_data->variants != ARMV5J_ABOVE)
13257 && (opcode_data->variants != ARMV6_ABOVE)
13258 && (opcode_data->variants != ARMV6T2_ABOVE))
13259 return false;
13260 break;
13261
13262 default:
13263// if (opcode_data->variants != ARMvAll)
13264// return false;
13265 break;
13266 }
13267
13268 // Just for now, for testing purposes.
Caroline Ticeaf591802011-04-05 23:22:54 +000013269 if (m_baton == NULL)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013270 fprintf (stdout, "\nEvaluateInstruction, opcode (0x%x), found = '%s'\n", m_opcode.GetOpcode32(),
13271 opcode_data->name);
13272
13273 bool success;
13274 if (m_baton)
13275 {
13276 uint32_t cpsr_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
13277 if (success)
13278 m_opcode_cpsr = cpsr_value;
13279 }
Caroline Tice080bf612011-04-05 18:46:00 +000013280
Caroline Tice0fe5a532011-04-08 23:33:06 +000013281 uint32_t orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13282 if (!success)
13283 return false;
13284
13285 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); // Call the Emulate... function.
13286 if (!success)
13287 return false;
13288
13289 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13290 if (!success)
13291 return false;
13292
13293 if (m_advance_pc && (after_pc_value == orig_pc_value))
13294 {
13295 if (opcode_data->size == eSize32)
13296 after_pc_value += 4;
13297 else if (opcode_data->size == eSize16)
13298 after_pc_value += 2;
13299
13300 EmulateInstruction::Context context;
13301 context.type = eContextAdvancePC;
13302 context.SetNoArgs();
13303 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13304 return false;
13305
13306 }
13307
13308 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013309}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013310
13311bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013312EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013313{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013314 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013315 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013316 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013317 return false;
13318 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013319
13320 static ConstString opcode_key ("opcode");
13321 static ConstString before_key ("before_state");
13322 static ConstString after_key ("after_state");
13323
13324 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013325
13326 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013327 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013328 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013329 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013330 return false;
13331 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013332 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013333
Caroline Ticedfb2e202011-04-22 05:08:45 +000013334 // If the instruction emulation does not directly update the PC, advance the PC to the next instruction after
13335 // performing the emulation.
13336 SetAdvancePC (true);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013337
13338 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13339 {
13340 m_opcode_mode = eModeARM;
13341 m_opcode.SetOpcode32 (test_opcode);
13342 }
13343 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13344 {
13345 m_opcode_mode = eModeThumb;
13346 if (test_opcode < 0x10000)
13347 m_opcode.SetOpcode16 (test_opcode);
13348 else
13349 m_opcode.SetOpcode32 (test_opcode);
13350
13351 }
13352 else
13353 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013354 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013355 return false;
13356 }
13357
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013358 EmulationStateARM before_state;
13359 EmulationStateARM after_state;
13360
Caroline Ticedfb2e202011-04-22 05:08:45 +000013361 value_sp = test_data->GetValueForKey (before_key);
13362 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013363 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013364 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013365 return false;
13366 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013367
13368 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionaryValue ();
13369 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013370 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013371 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013372 return false;
13373 }
13374
Caroline Ticedfb2e202011-04-22 05:08:45 +000013375 value_sp = test_data->GetValueForKey (after_key);
13376 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013377 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013378 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013379 return false;
13380 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013381
13382 state_dictionary = value_sp->GetAsDictionaryValue ();
13383 if (!after_state.LoadStateFromDictionary (state_dictionary))
13384 {
13385 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13386 return false;
13387 }
13388
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013389 SetBaton ((void *) &before_state);
13390 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13391 &EmulationStateARM::WritePseudoMemory,
13392 &EmulationStateARM::ReadPseudoRegister,
13393 &EmulationStateARM::WritePseudoRegister);
13394
13395 bool success = EvaluateInstruction ();
13396 if (!success)
13397 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013398 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013399 return false;
13400 }
13401
13402 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013403 if (!success)
13404 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13405
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013406 return success;
13407}
13408