blob: f6c52c0d8be149fe76e888e6e7ff88e78501888a [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 *
Greg Clayton888a7332011-04-26 04:39:08 +0000184EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
Caroline Tice080bf612011-04-05 18:46:00 +0000185{
Greg Clayton888a7332011-04-26 04:39:08 +0000186 if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
Caroline Tice080bf612011-04-05 18:46:00 +0000187 {
Greg Clayton888a7332011-04-26 04:39:08 +0000188 if (arch.GetTriple().getArch() == llvm::Triple::arm)
189 {
190 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
191
192 if (emulate_insn_ap.get())
193 return emulate_insn_ap.release();
194 }
195 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
196 {
197 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
198
199 if (emulate_insn_ap.get())
200 return emulate_insn_ap.release();
201 }
Caroline Tice080bf612011-04-05 18:46:00 +0000202 }
203
204 return NULL;
205}
206
207bool
208EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
209{
210 if (arch.GetTriple().getArch () == llvm::Triple::arm)
211 return true;
212 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
213 return true;
214
215 return false;
216}
217
Caroline Ticefa172202011-02-11 22:49:54 +0000218// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
219bool
220EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
221{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000222 EmulateInstruction::Context context;
223 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
224 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000225
226 uint32_t random_data = rand ();
227 const uint32_t addr_byte_size = GetAddressByteSize();
228
Caroline Ticecc96eb52011-02-17 19:20:40 +0000229 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000230 return false;
231
232 return true;
233}
234
Caroline Tice713c2662011-02-11 17:59:55 +0000235// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
236bool
237EmulateInstructionARM::WriteBits32Unknown (int n)
238{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000239 EmulateInstruction::Context context;
240 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
241 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000242
Johnny Chen62ff6f52011-02-11 18:11:22 +0000243 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000244 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
245
246 if (!success)
247 return false;
248
249 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
250 return false;
251
252 return true;
253}
254
Johnny Chen08c25e82011-01-31 18:02:28 +0000255// Push Multiple Registers stores multiple registers to the stack, storing to
256// consecutive memory locations ending just below the address in SP, and updates
257// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000258bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000259EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000260{
261#if 0
262 // ARM pseudo code...
263 if (ConditionPassed())
264 {
265 EncodingSpecificOperations();
266 NullCheckIfThumbEE(13);
267 address = SP - 4*BitCount(registers);
268
269 for (i = 0 to 14)
270 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000271 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000272 {
273 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
274 MemA[address,4] = bits(32) UNKNOWN;
275 else
276 MemA[address,4] = R[i];
277 address = address + 4;
278 }
279 }
280
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000281 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000282 MemA[address,4] = PCStoreValue();
283
284 SP = SP - 4*BitCount(registers);
285 }
286#endif
287
288 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000289 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000290 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000291 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000292 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000293 if (!success)
294 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000295 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000296 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000297 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000298 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000299 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000300 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000301 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000302 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000303 // if BitCount(registers) < 1 then UNPREDICTABLE;
304 if (BitCount(registers) < 1)
305 return false;
306 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000307 case eEncodingT2:
308 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000309 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000310 // if BitCount(registers) < 2 then UNPREDICTABLE;
311 if (BitCount(registers) < 2)
312 return false;
313 break;
314 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000315 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000316 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000317 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000318 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000319 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000320 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000321 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000322 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000323 // Instead of return false, let's handle the following case as well,
324 // which amounts to pushing one reg onto the full descending stacks.
325 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000326 break;
327 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000328 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000329 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000330 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000331 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000332 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000333 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000334 default:
335 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000336 }
Johnny Chence1ca772011-01-25 01:13:00 +0000337 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000338 addr_t addr = sp - sp_offset;
339 uint32_t i;
340
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000341 EmulateInstruction::Context context;
342 context.type = EmulateInstruction::eContextPushRegisterOnStack;
343 Register dwarf_reg;
344 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000345 Register sp_reg;
Greg Clayton888a7332011-04-26 04:39:08 +0000346 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Greg Clayton64c84432011-01-21 22:02:52 +0000347 for (i=0; i<15; ++i)
348 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000349 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000350 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000351 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000352 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000353 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000354 if (!success)
355 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000356 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000357 return false;
358 addr += addr_byte_size;
359 }
360 }
361
Johnny Chen7c1bf922011-02-08 23:49:37 +0000362 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000363 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000364 dwarf_reg.num = dwarf_pc;
365 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000366 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000367 if (!success)
368 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000369 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000370 return false;
371 }
372
373 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000374 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000375
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000376 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000377 return false;
378 }
379 return true;
380}
381
Johnny Chenef85e912011-01-31 23:07:40 +0000382// Pop Multiple Registers loads multiple registers from the stack, loading from
383// consecutive memory locations staring at the address in SP, and updates
384// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000385bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000386EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000387{
388#if 0
389 // ARM pseudo code...
390 if (ConditionPassed())
391 {
392 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
393 address = SP;
394 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000395 if registers<i> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000396 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000397 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000398 if UnalignedAllowed then
399 LoadWritePC(MemU[address,4]);
400 else
401 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000402 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
403 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000404 }
405#endif
406
407 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000408
Greg Clayton7bc39082011-03-24 23:53:38 +0000409 if (ConditionPassed(opcode))
Johnny Chenef85e912011-01-31 23:07:40 +0000410 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000411 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000412 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000413 if (!success)
414 return false;
415 uint32_t registers = 0;
416 uint32_t Rt; // the destination register
417 switch (encoding) {
418 case eEncodingT1:
419 registers = Bits32(opcode, 7, 0);
420 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000421 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000422 registers |= (1u << 15);
423 // if BitCount(registers) < 1 then UNPREDICTABLE;
424 if (BitCount(registers) < 1)
425 return false;
426 break;
427 case eEncodingT2:
428 // Ignore bit 13.
429 registers = Bits32(opcode, 15, 0) & ~0x2000;
430 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000431 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000432 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000433 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
434 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
435 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000436 break;
437 case eEncodingT3:
438 Rt = Bits32(opcode, 15, 12);
439 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000440 if (Rt == 13)
441 return false;
442 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000443 return false;
444 registers = (1u << Rt);
445 break;
446 case eEncodingA1:
447 registers = Bits32(opcode, 15, 0);
448 // Instead of return false, let's handle the following case as well,
449 // which amounts to popping one reg from the full descending stacks.
450 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
451
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000452 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000453 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000454 return false;
455 break;
456 case eEncodingA2:
457 Rt = Bits32(opcode, 15, 12);
458 // if t == 13 then UNPREDICTABLE;
459 if (Rt == dwarf_sp)
460 return false;
461 registers = (1u << Rt);
462 break;
463 default:
464 return false;
465 }
466 addr_t sp_offset = addr_byte_size * BitCount (registers);
467 addr_t addr = sp;
468 uint32_t i, data;
469
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000470 EmulateInstruction::Context context;
471 context.type = EmulateInstruction::eContextPopRegisterOffStack;
472 Register dwarf_reg;
473 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice8ce836d2011-03-16 22:46:55 +0000474 Register sp_reg;
475 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Johnny Chenef85e912011-01-31 23:07:40 +0000476 for (i=0; i<15; ++i)
477 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000478 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000479 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000480 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000481 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000482 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000483 if (!success)
484 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000485 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000486 return false;
487 addr += addr_byte_size;
488 }
489 }
490
Johnny Chen7c1bf922011-02-08 23:49:37 +0000491 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000492 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000493 dwarf_reg.num = dwarf_pc;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000494 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000495 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000496 if (!success)
497 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000498 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000499 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000500 return false;
501 addr += addr_byte_size;
502 }
503
504 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000505 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000506
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000507 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000508 return false;
509 }
510 return true;
511}
512
Johnny Chen5b442b72011-01-27 19:34:30 +0000513// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000514// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000515bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000516EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000517{
518#if 0
519 // ARM pseudo code...
520 if (ConditionPassed())
521 {
522 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000523 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000524 if d == 15 then
525 ALUWritePC(result); // setflags is always FALSE here
526 else
527 R[d] = result;
528 if setflags then
529 APSR.N = result<31>;
530 APSR.Z = IsZeroBit(result);
531 APSR.C = carry;
532 APSR.V = overflow;
533 }
534#endif
535
536 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000537
Greg Clayton7bc39082011-03-24 23:53:38 +0000538 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000539 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000540 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000541 if (!success)
542 return false;
543 uint32_t Rd; // the destination register
544 uint32_t imm32;
545 switch (encoding) {
546 case eEncodingT1:
547 Rd = 7;
548 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
549 break;
550 case eEncodingA1:
551 Rd = Bits32(opcode, 15, 12);
552 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
553 break;
554 default:
555 return false;
556 }
557 addr_t sp_offset = imm32;
558 addr_t addr = sp + sp_offset; // a pointer to the stack area
559
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000560 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +0000561 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000562 Register sp_reg;
563 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
564 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000565
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000566 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000567 return false;
568 }
569 return true;
570}
571
Johnny Chen2ccad832011-01-28 19:57:25 +0000572// Set r7 or ip to the current stack pointer.
573// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000574bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000575EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000576{
577#if 0
578 // ARM pseudo code...
579 if (ConditionPassed())
580 {
581 EncodingSpecificOperations();
582 result = R[m];
583 if d == 15 then
584 ALUWritePC(result); // setflags is always FALSE here
585 else
586 R[d] = result;
587 if setflags then
588 APSR.N = result<31>;
589 APSR.Z = IsZeroBit(result);
590 // APSR.C unchanged
591 // APSR.V unchanged
592 }
593#endif
594
595 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000596
Greg Clayton7bc39082011-03-24 23:53:38 +0000597 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000598 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000599 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000600 if (!success)
601 return false;
602 uint32_t Rd; // the destination register
603 switch (encoding) {
604 case eEncodingT1:
605 Rd = 7;
606 break;
607 case eEncodingA1:
608 Rd = 12;
609 break;
610 default:
611 return false;
612 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000613
614 EmulateInstruction::Context context;
615 context.type = EmulateInstruction::eContextRegisterPlusOffset;
616 Register sp_reg;
617 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
618 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000619
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000620 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000621 return false;
622 }
623 return true;
624}
625
Johnny Chen1c13b622011-01-29 00:11:15 +0000626// Move from high register (r8-r15) to low register (r0-r7).
627// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000628bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000629EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000630{
Greg Clayton7bc39082011-03-24 23:53:38 +0000631 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000632}
633
634// Move from register to register.
635// MOV (register)
636bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000637EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000638{
Johnny Chen1c13b622011-01-29 00:11:15 +0000639#if 0
640 // ARM pseudo code...
641 if (ConditionPassed())
642 {
643 EncodingSpecificOperations();
644 result = R[m];
645 if d == 15 then
646 ALUWritePC(result); // setflags is always FALSE here
647 else
648 R[d] = result;
649 if setflags then
650 APSR.N = result<31>;
651 APSR.Z = IsZeroBit(result);
652 // APSR.C unchanged
653 // APSR.V unchanged
654 }
655#endif
656
657 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000658
Greg Clayton7bc39082011-03-24 23:53:38 +0000659 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000660 {
661 uint32_t Rm; // the source register
662 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000663 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000664 switch (encoding) {
665 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000666 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000667 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000668 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000669 if (Rd == 15 && InITBlock() && !LastInITBlock())
670 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000671 break;
672 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000673 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000674 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000675 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000676 if (InITBlock())
677 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000678 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000679 case eEncodingT3:
680 Rd = Bits32(opcode, 11, 8);
681 Rm = Bits32(opcode, 3, 0);
682 setflags = BitIsSet(opcode, 20);
683 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
684 if (setflags && (BadReg(Rd) || BadReg(Rm)))
685 return false;
686 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
687 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
688 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000689 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000690 case eEncodingA1:
691 Rd = Bits32(opcode, 15, 12);
692 Rm = Bits32(opcode, 3, 0);
693 setflags = BitIsSet(opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +0000694
Johnny Chen01d61572011-02-25 00:23:25 +0000695 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000696 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000697 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000698 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000699 default:
700 return false;
701 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000702 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000703 if (!success)
704 return false;
705
706 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000707 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000708 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000709 Register dwarf_reg;
710 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000711 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000712
Johnny Chen10530c22011-02-17 22:37:12 +0000713 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000714 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000715 }
716 return true;
717}
718
Johnny Chen357c30f2011-02-14 22:04:25 +0000719// Move (immediate) writes an immediate value to the destination register. It
720// can optionally update the condition flags based on the value.
721// MOV (immediate)
722bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000723EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000724{
725#if 0
726 // ARM pseudo code...
727 if (ConditionPassed())
728 {
729 EncodingSpecificOperations();
730 result = imm32;
731 if d == 15 then // Can only occur for ARM encoding
732 ALUWritePC(result); // setflags is always FALSE here
733 else
734 R[d] = result;
735 if setflags then
736 APSR.N = result<31>;
737 APSR.Z = IsZeroBit(result);
738 APSR.C = carry;
739 // APSR.V unchanged
740 }
741#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000742
Greg Clayton7bc39082011-03-24 23:53:38 +0000743 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000744 {
745 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000746 uint32_t imm32; // the immediate value to be written to Rd
747 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
748 bool setflags;
749 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000750 case eEncodingT1:
751 Rd = Bits32(opcode, 10, 8);
752 setflags = !InITBlock();
753 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
754 carry = APSR_C;
755
756 break;
757
758 case eEncodingT2:
759 Rd = Bits32(opcode, 11, 8);
760 setflags = BitIsSet(opcode, 20);
761 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
762 if (BadReg(Rd))
763 return false;
764
765 break;
766
767 case eEncodingT3:
768 {
769 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
770 Rd = Bits32 (opcode, 11, 8);
771 setflags = false;
772 uint32_t imm4 = Bits32 (opcode, 19, 16);
773 uint32_t imm3 = Bits32 (opcode, 14, 12);
774 uint32_t i = Bit32 (opcode, 26);
775 uint32_t imm8 = Bits32 (opcode, 7, 0);
776 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
777
778 // if BadReg(d) then UNPREDICTABLE;
779 if (BadReg (Rd))
780 return false;
781 }
782 break;
783
784 case eEncodingA1:
Caroline Tice89c6d582011-03-29 19:53:44 +0000785 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
786 Rd = Bits32 (opcode, 15, 12);
787 setflags = BitIsSet (opcode, 20);
788 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000789
790 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
791 if ((Rd == 15) && setflags)
792 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000793
794 break;
795
796 case eEncodingA2:
797 {
798 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
799 Rd = Bits32 (opcode, 15, 12);
800 setflags = false;
801 uint32_t imm4 = Bits32 (opcode, 19, 16);
802 uint32_t imm12 = Bits32 (opcode, 11, 0);
803 imm32 = (imm4 << 12) | imm12;
804
805 // if d == 15 then UNPREDICTABLE;
806 if (Rd == 15)
807 return false;
808 }
809 break;
810
811 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000812 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000813 }
814 uint32_t result = imm32;
815
816 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000817 EmulateInstruction::Context context;
818 context.type = EmulateInstruction::eContextImmediate;
819 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000820
Johnny Chen10530c22011-02-17 22:37:12 +0000821 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000822 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000823 }
824 return true;
825}
826
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000827// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
828// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
829// unsigned values.
830//
831// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
832// limited to only a few forms of the instruction.
833bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000834EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000835{
836#if 0
837 if ConditionPassed() then
838 EncodingSpecificOperations();
839 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
840 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
841 result = operand1 * operand2;
842 R[d] = result<31:0>;
843 if setflags then
844 APSR.N = result<31>;
845 APSR.Z = IsZeroBit(result);
846 if ArchVersion() == 4 then
847 APSR.C = bit UNKNOWN;
848 // else APSR.C unchanged
849 // APSR.V always unchanged
850#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000851
Greg Clayton7bc39082011-03-24 23:53:38 +0000852 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000853 {
854 uint32_t d;
855 uint32_t n;
856 uint32_t m;
857 bool setflags;
858
859 // EncodingSpecificOperations();
860 switch (encoding)
861 {
862 case eEncodingT1:
863 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
864 d = Bits32 (opcode, 2, 0);
865 n = Bits32 (opcode, 5, 3);
866 m = Bits32 (opcode, 2, 0);
867 setflags = !InITBlock();
868
869 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
870 if ((ArchVersion() < ARMv6) && (d == n))
871 return false;
872
873 break;
874
875 case eEncodingT2:
876 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
877 d = Bits32 (opcode, 11, 8);
878 n = Bits32 (opcode, 19, 16);
879 m = Bits32 (opcode, 3, 0);
880 setflags = false;
881
882 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
883 if (BadReg (d) || BadReg (n) || BadReg (m))
884 return false;
885
886 break;
887
888 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000889 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000890 d = Bits32 (opcode, 19, 16);
891 n = Bits32 (opcode, 3, 0);
892 m = Bits32 (opcode, 11, 8);
893 setflags = BitIsSet (opcode, 20);
894
895 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
896 if ((d == 15) || (n == 15) || (m == 15))
897 return false;
898
899 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
900 if ((ArchVersion() < ARMv6) && (d == n))
901 return false;
902
903 break;
904
905 default:
906 return false;
907 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000908
909 bool success = false;
910
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000911 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
912 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
913 if (!success)
914 return false;
915
916 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
917 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
918 if (!success)
919 return false;
920
921 // result = operand1 * operand2;
922 uint64_t result = operand1 * operand2;
923
924 // R[d] = result<31:0>;
925 Register op1_reg;
926 Register op2_reg;
927 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
928 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
929
930 EmulateInstruction::Context context;
931 context.type = eContextMultiplication;
932 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
933
934 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
935 return false;
936
937 // if setflags then
938 if (setflags)
939 {
940 // APSR.N = result<31>;
941 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000942 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000943 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
944 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000945 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000946 {
947 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
948 return false;
949 }
950
951 // if ArchVersion() == 4 then
952 // APSR.C = bit UNKNOWN;
953 }
954 }
955 return true;
956}
957
Johnny Chend642a6a2011-02-22 01:01:03 +0000958// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
959// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000960bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000961EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000962{
963#if 0
964 // ARM pseudo code...
965 if (ConditionPassed())
966 {
967 EncodingSpecificOperations();
968 result = NOT(imm32);
969 if d == 15 then // Can only occur for ARM encoding
970 ALUWritePC(result); // setflags is always FALSE here
971 else
972 R[d] = result;
973 if setflags then
974 APSR.N = result<31>;
975 APSR.Z = IsZeroBit(result);
976 APSR.C = carry;
977 // APSR.V unchanged
978 }
979#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000980
Greg Clayton7bc39082011-03-24 23:53:38 +0000981 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000982 {
983 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000984 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
985 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000986 bool setflags;
987 switch (encoding) {
988 case eEncodingT1:
989 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000990 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000991 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000992 break;
993 case eEncodingA1:
994 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000995 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000996 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000997
Johnny Chend642a6a2011-02-22 01:01:03 +0000998 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +0000999 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001000 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001001 break;
1002 default:
1003 return false;
1004 }
1005 uint32_t result = ~imm32;
1006
1007 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001008 EmulateInstruction::Context context;
1009 context.type = EmulateInstruction::eContextImmediate;
1010 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001011
Johnny Chen10530c22011-02-17 22:37:12 +00001012 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001013 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001014 }
1015 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001016}
1017
Johnny Chend642a6a2011-02-22 01:01:03 +00001018// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1019// It can optionally update the condition flags based on the result.
1020bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001021EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001022{
1023#if 0
1024 // ARM pseudo code...
1025 if (ConditionPassed())
1026 {
1027 EncodingSpecificOperations();
1028 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1029 result = NOT(shifted);
1030 if d == 15 then // Can only occur for ARM encoding
1031 ALUWritePC(result); // setflags is always FALSE here
1032 else
1033 R[d] = result;
1034 if setflags then
1035 APSR.N = result<31>;
1036 APSR.Z = IsZeroBit(result);
1037 APSR.C = carry;
1038 // APSR.V unchanged
1039 }
1040#endif
1041
Greg Clayton7bc39082011-03-24 23:53:38 +00001042 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001043 {
1044 uint32_t Rm; // the source register
1045 uint32_t Rd; // the destination register
1046 ARM_ShifterType shift_t;
1047 uint32_t shift_n; // the shift applied to the value read from Rm
1048 bool setflags;
1049 uint32_t carry; // the carry bit after the shift operation
1050 switch (encoding) {
1051 case eEncodingT1:
1052 Rd = Bits32(opcode, 2, 0);
1053 Rm = Bits32(opcode, 5, 3);
1054 setflags = !InITBlock();
1055 shift_t = SRType_LSL;
1056 shift_n = 0;
1057 if (InITBlock())
1058 return false;
1059 break;
1060 case eEncodingT2:
1061 Rd = Bits32(opcode, 11, 8);
1062 Rm = Bits32(opcode, 3, 0);
1063 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001064 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001065 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001066 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001067 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001068 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001069 case eEncodingA1:
1070 Rd = Bits32(opcode, 15, 12);
1071 Rm = Bits32(opcode, 3, 0);
1072 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001073 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001074 break;
1075 default:
1076 return false;
1077 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001078 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001079 uint32_t value = ReadCoreReg(Rm, &success);
1080 if (!success)
1081 return false;
1082
1083 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1084 uint32_t result = ~shifted;
1085
1086 // The context specifies that an immediate is to be moved into Rd.
1087 EmulateInstruction::Context context;
1088 context.type = EmulateInstruction::eContextImmediate;
1089 context.SetNoArgs ();
1090
1091 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1092 return false;
1093 }
1094 return true;
1095}
1096
Johnny Chen788e0552011-01-27 22:52:23 +00001097// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1098// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001099bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001100EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001101{
1102#if 0
1103 // ARM pseudo code...
1104 if (ConditionPassed())
1105 {
1106 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1107 base = Align(PC,4);
1108 address = if add then (base + imm32) else (base - imm32);
1109 data = MemU[address,4];
1110 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001111 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1112 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001113 R[t] = data;
1114 else // Can only apply before ARMv7
1115 if CurrentInstrSet() == InstrSet_ARM then
1116 R[t] = ROR(data, 8*UInt(address<1:0>));
1117 else
1118 R[t] = bits(32) UNKNOWN;
1119 }
1120#endif
1121
Greg Clayton7bc39082011-03-24 23:53:38 +00001122 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001123 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001124 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001125 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001126 if (!success)
1127 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001128
1129 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001130 EmulateInstruction::Context context;
1131 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1132 Register pc_reg;
1133 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1134 context.SetRegisterPlusOffset (pc_reg, 0);
1135
Johnny Chenc9de9102011-02-11 19:12:30 +00001136 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001137 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001138 bool add; // +imm32 or -imm32?
1139 addr_t base; // the base address
1140 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001141 uint32_t data; // the literal data value from the PC relative load
1142 switch (encoding) {
1143 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001144 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001145 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001146 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001147 break;
1148 case eEncodingT2:
1149 Rt = Bits32(opcode, 15, 12);
1150 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1151 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001152 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001153 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001154 break;
1155 default:
1156 return false;
1157 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001158
Johnny Chene39f22d2011-02-19 01:36:13 +00001159 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001160 if (add)
1161 address = base + imm32;
1162 else
1163 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001164
1165 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001166 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001167 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001168 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001169
1170 if (Rt == 15)
1171 {
1172 if (Bits32(address, 1, 0) == 0)
1173 {
1174 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001175 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001176 return false;
1177 }
1178 else
1179 return false;
1180 }
1181 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1182 {
1183 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1184 return false;
1185 }
1186 else // We don't handle ARM for now.
1187 return false;
1188
Johnny Chen788e0552011-01-27 22:52:23 +00001189 }
1190 return true;
1191}
1192
Johnny Chen5b442b72011-01-27 19:34:30 +00001193// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001194// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001195bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001196EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001197{
1198#if 0
1199 // ARM pseudo code...
1200 if (ConditionPassed())
1201 {
1202 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001203 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001204 if d == 15 then // Can only occur for ARM encoding
1205 ALUWritePC(result); // setflags is always FALSE here
1206 else
1207 R[d] = result;
1208 if setflags then
1209 APSR.N = result<31>;
1210 APSR.Z = IsZeroBit(result);
1211 APSR.C = carry;
1212 APSR.V = overflow;
1213 }
1214#endif
1215
1216 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001217
Greg Clayton7bc39082011-03-24 23:53:38 +00001218 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001219 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001220 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001221 if (!success)
1222 return false;
1223 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001224 uint32_t d;
1225 bool setflags;
1226 switch (encoding)
1227 {
1228 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001229 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001230 d = Bits32 (opcode, 10, 8);
1231 setflags = false;
1232 imm32 = (Bits32 (opcode, 7, 0) << 2);
1233
1234 break;
1235
1236 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001237 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001238 d = 13;
1239 setflags = false;
1240 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1241
1242 break;
1243
1244 default:
1245 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001246 }
1247 addr_t sp_offset = imm32;
1248 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1249
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001250 EmulateInstruction::Context context;
1251 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice080bf612011-04-05 18:46:00 +00001252 Register sp_reg;
Greg Clayton888a7332011-04-26 04:39:08 +00001253 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Caroline Tice080bf612011-04-05 18:46:00 +00001254 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001255
Caroline Ticee2212882011-03-22 22:38:28 +00001256 if (d == 15)
1257 {
1258 if (!ALUWritePC (context, addr))
1259 return false;
1260 }
1261 else
1262 {
1263 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1264 return false;
1265 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001266 }
1267 return true;
1268}
1269
1270// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001271// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001272bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001273EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001274{
1275#if 0
1276 // ARM pseudo code...
1277 if (ConditionPassed())
1278 {
1279 EncodingSpecificOperations();
1280 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001281 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001282 if d == 15 then
1283 ALUWritePC(result); // setflags is always FALSE here
1284 else
1285 R[d] = result;
1286 if setflags then
1287 APSR.N = result<31>;
1288 APSR.Z = IsZeroBit(result);
1289 APSR.C = carry;
1290 APSR.V = overflow;
1291 }
1292#endif
1293
1294 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001295
Greg Clayton7bc39082011-03-24 23:53:38 +00001296 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001297 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001298 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001299 if (!success)
1300 return false;
1301 uint32_t Rm; // the second operand
1302 switch (encoding) {
1303 case eEncodingT2:
1304 Rm = Bits32(opcode, 6, 3);
1305 break;
1306 default:
1307 return false;
1308 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001309 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001310 if (!success)
1311 return false;
1312
1313 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1314
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001315 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +00001316 context.type = EmulateInstruction::eContextAddition;
1317 Register sp_reg;
Greg Clayton888a7332011-04-26 04:39:08 +00001318 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Caroline Tice080bf612011-04-05 18:46:00 +00001319 Register other_reg;
1320 other_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1321 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001322
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001323 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001324 return false;
1325 }
1326 return true;
1327}
1328
Johnny Chen9b8d7832011-02-02 01:13:56 +00001329// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1330// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1331// from Thumb to ARM.
1332// BLX (immediate)
1333bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001334EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001335{
1336#if 0
1337 // ARM pseudo code...
1338 if (ConditionPassed())
1339 {
1340 EncodingSpecificOperations();
1341 if CurrentInstrSet() == InstrSet_ARM then
1342 LR = PC - 4;
1343 else
1344 LR = PC<31:1> : '1';
1345 if targetInstrSet == InstrSet_ARM then
1346 targetAddress = Align(PC,4) + imm32;
1347 else
1348 targetAddress = PC + imm32;
1349 SelectInstrSet(targetInstrSet);
1350 BranchWritePC(targetAddress);
1351 }
1352#endif
1353
Greg Clayton7bc39082011-03-24 23:53:38 +00001354 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001355
Greg Clayton7bc39082011-03-24 23:53:38 +00001356 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001357 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001358 EmulateInstruction::Context context;
1359 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001360 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001361 if (!success)
1362 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001363 addr_t lr; // next instruction address
1364 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001365 int32_t imm32; // PC-relative offset
1366 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001367 case eEncodingT1:
1368 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001369 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001370 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001371 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001372 uint32_t J1 = Bit32(opcode, 13);
1373 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001374 uint32_t imm11 = Bits32(opcode, 10, 0);
1375 uint32_t I1 = !(J1 ^ S);
1376 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001377 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001378 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001379 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001380 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001381 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001382 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001383 break;
1384 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001385 case eEncodingT2:
1386 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001387 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001388 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001389 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001390 uint32_t J1 = Bit32(opcode, 13);
1391 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001392 uint32_t imm10L = Bits32(opcode, 10, 1);
1393 uint32_t I1 = !(J1 ^ S);
1394 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001395 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001396 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001397 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001398 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001399 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001400 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001401 break;
1402 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001403 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001404 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001405 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001406 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001407 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001408 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001409 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001410 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001411 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001412 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001413 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001414 break;
1415 default:
1416 return false;
1417 }
1418 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1419 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001420 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001421 return false;
1422 }
1423 return true;
1424}
1425
1426// Branch with Link and Exchange (register) calls a subroutine at an address and
1427// instruction set specified by a register.
1428// BLX (register)
1429bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001430EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001431{
1432#if 0
1433 // ARM pseudo code...
1434 if (ConditionPassed())
1435 {
1436 EncodingSpecificOperations();
1437 target = R[m];
1438 if CurrentInstrSet() == InstrSet_ARM then
1439 next_instr_addr = PC - 4;
1440 LR = next_instr_addr;
1441 else
1442 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001443 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001444 BXWritePC(target);
1445 }
1446#endif
1447
1448 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001449
Greg Clayton7bc39082011-03-24 23:53:38 +00001450 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001451 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001452 EmulateInstruction::Context context;
1453 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001454 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001455 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001456 if (!success)
1457 return false;
1458 uint32_t Rm; // the register with the target address
1459 switch (encoding) {
1460 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001461 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001462 Rm = Bits32(opcode, 6, 3);
1463 // if m == 15 then UNPREDICTABLE;
1464 if (Rm == 15)
1465 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001466 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001467 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001468 break;
1469 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001470 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001471 Rm = Bits32(opcode, 3, 0);
1472 // if m == 15 then UNPREDICTABLE;
1473 if (Rm == 15)
1474 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001475 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001476 default:
1477 return false;
1478 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001479 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001480 if (!success)
1481 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001482 Register dwarf_reg;
1483 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1484 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001485 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1486 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001487 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001488 return false;
1489 }
1490 return true;
1491}
1492
Johnny Chenab3b3512011-02-12 00:10:51 +00001493// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001494bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001495EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001496{
1497#if 0
1498 // ARM pseudo code...
1499 if (ConditionPassed())
1500 {
1501 EncodingSpecificOperations();
1502 BXWritePC(R[m]);
1503 }
1504#endif
1505
Greg Clayton7bc39082011-03-24 23:53:38 +00001506 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001507 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001508 EmulateInstruction::Context context;
1509 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001510 uint32_t Rm; // the register with the target address
1511 switch (encoding) {
1512 case eEncodingT1:
1513 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001514 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001515 return false;
1516 break;
1517 case eEncodingA1:
1518 Rm = Bits32(opcode, 3, 0);
1519 break;
1520 default:
1521 return false;
1522 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001523 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001524 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001525 if (!success)
1526 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001527
1528 Register dwarf_reg;
1529 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001530 context.SetRegister (dwarf_reg);
1531 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001532 return false;
1533 }
1534 return true;
1535}
1536
Johnny Chen59e6ab72011-02-24 21:01:20 +00001537// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1538// address and instruction set specified by a register as though it were a BX instruction.
1539//
1540// TODO: Emulate Jazelle architecture?
1541// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1542bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001543EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001544{
1545#if 0
1546 // ARM pseudo code...
1547 if (ConditionPassed())
1548 {
1549 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001550 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001551 BXWritePC(R[m]);
1552 else
1553 if JazelleAcceptsExecution() then
1554 SwitchToJazelleExecution();
1555 else
1556 SUBARCHITECTURE_DEFINED handler call;
1557 }
1558#endif
1559
Greg Clayton7bc39082011-03-24 23:53:38 +00001560 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001561 {
1562 EmulateInstruction::Context context;
1563 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1564 uint32_t Rm; // the register with the target address
1565 switch (encoding) {
1566 case eEncodingT1:
1567 Rm = Bits32(opcode, 19, 16);
1568 if (BadReg(Rm))
1569 return false;
1570 if (InITBlock() && !LastInITBlock())
1571 return false;
1572 break;
1573 case eEncodingA1:
1574 Rm = Bits32(opcode, 3, 0);
1575 if (Rm == 15)
1576 return false;
1577 break;
1578 default:
1579 return false;
1580 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001581 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001582 addr_t target = ReadCoreReg (Rm, &success);
1583 if (!success)
1584 return false;
1585
1586 Register dwarf_reg;
1587 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1588 context.SetRegister (dwarf_reg);
1589 if (!BXWritePC(context, target))
1590 return false;
1591 }
1592 return true;
1593}
1594
Johnny Chen0d0148e2011-01-28 02:26:08 +00001595// Set r7 to point to some ip offset.
1596// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001597bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001598EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001599{
1600#if 0
1601 // ARM pseudo code...
1602 if (ConditionPassed())
1603 {
1604 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001605 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001606 if d == 15 then // Can only occur for ARM encoding
1607 ALUWritePC(result); // setflags is always FALSE here
1608 else
1609 R[d] = result;
1610 if setflags then
1611 APSR.N = result<31>;
1612 APSR.Z = IsZeroBit(result);
1613 APSR.C = carry;
1614 APSR.V = overflow;
1615 }
1616#endif
1617
Greg Clayton7bc39082011-03-24 23:53:38 +00001618 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001619 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001620 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001621 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001622 if (!success)
1623 return false;
1624 uint32_t imm32;
1625 switch (encoding) {
1626 case eEncodingA1:
1627 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1628 break;
1629 default:
1630 return false;
1631 }
1632 addr_t ip_offset = imm32;
1633 addr_t addr = ip - ip_offset; // the adjusted ip value
1634
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001635 EmulateInstruction::Context context;
1636 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1637 Register dwarf_reg;
1638 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1639 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001640
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001641 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001642 return false;
1643 }
1644 return true;
1645}
1646
1647// Set ip to point to some stack offset.
1648// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001649bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001650EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001651{
1652#if 0
1653 // ARM pseudo code...
1654 if (ConditionPassed())
1655 {
1656 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001657 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001658 if d == 15 then // Can only occur for ARM encoding
1659 ALUWritePC(result); // setflags is always FALSE here
1660 else
1661 R[d] = result;
1662 if setflags then
1663 APSR.N = result<31>;
1664 APSR.Z = IsZeroBit(result);
1665 APSR.C = carry;
1666 APSR.V = overflow;
1667 }
1668#endif
1669
Greg Clayton7bc39082011-03-24 23:53:38 +00001670 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001671 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001672 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001673 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001674 if (!success)
1675 return false;
1676 uint32_t imm32;
1677 switch (encoding) {
1678 case eEncodingA1:
1679 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1680 break;
1681 default:
1682 return false;
1683 }
1684 addr_t sp_offset = imm32;
1685 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1686
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001687 EmulateInstruction::Context context;
1688 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1689 Register dwarf_reg;
1690 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1691 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001692
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001693 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001694 return false;
1695 }
1696 return true;
1697}
1698
Johnny Chenc9e747f2011-02-23 01:55:07 +00001699// This instruction subtracts an immediate value from the SP value, and writes
1700// the result to the destination register.
1701//
1702// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001703bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001704EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001705{
1706#if 0
1707 // ARM pseudo code...
1708 if (ConditionPassed())
1709 {
1710 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001711 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001712 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001713 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001714 else
1715 R[d] = result;
1716 if setflags then
1717 APSR.N = result<31>;
1718 APSR.Z = IsZeroBit(result);
1719 APSR.C = carry;
1720 APSR.V = overflow;
1721 }
1722#endif
1723
1724 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001725 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001726 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001727 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001728 if (!success)
1729 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001730
1731 uint32_t Rd;
1732 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001733 uint32_t imm32;
1734 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001735 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001736 Rd = 13;
1737 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001738 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001739 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001740 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001741 Rd = Bits32(opcode, 11, 8);
1742 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001743 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001744 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001745 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001746 if (Rd == 15 && !setflags)
1747 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001748 break;
1749 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001750 Rd = Bits32(opcode, 11, 8);
1751 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001752 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001753 if (Rd == 15)
1754 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001755 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001756 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001757 Rd = Bits32(opcode, 15, 12);
1758 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001759 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001760
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001761 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001762 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001763 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001764 break;
1765 default:
1766 return false;
1767 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001768 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1769
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001770 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001771 if (Rd == 13)
1772 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001773 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1774 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001775 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001776 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001777 }
1778 else
1779 {
1780 context.type = EmulateInstruction::eContextImmediate;
1781 context.SetNoArgs ();
1782 }
1783
1784 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001785 return false;
1786 }
1787 return true;
1788}
1789
Johnny Chen08c25e82011-01-31 18:02:28 +00001790// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001791bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001792EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001793{
1794#if 0
1795 // ARM pseudo code...
1796 if (ConditionPassed())
1797 {
1798 EncodingSpecificOperations();
1799 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1800 address = if index then offset_addr else R[n];
1801 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1802 if wback then R[n] = offset_addr;
1803 }
1804#endif
1805
1806 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001807
Greg Clayton7bc39082011-03-24 23:53:38 +00001808 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001809 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001810 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001811 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001812 if (!success)
1813 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001814 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001815 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001816 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1817
1818 bool index;
1819 bool add;
1820 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001821 switch (encoding) {
1822 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001823 Rt = Bits32(opcode, 15, 12);
1824 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001825 Rn = Bits32 (opcode, 19, 16);
1826
1827 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1828 return false;
1829
1830 index = BitIsSet (opcode, 24);
1831 add = BitIsSet (opcode, 23);
1832 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1833
1834 if (wback && ((Rn == 15) || (Rn == Rt)))
1835 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001836 break;
1837 default:
1838 return false;
1839 }
Caroline Tice3e407972011-03-18 19:41:00 +00001840 addr_t offset_addr;
1841 if (add)
1842 offset_addr = sp + imm12;
1843 else
1844 offset_addr = sp - imm12;
1845
1846 addr_t addr;
1847 if (index)
1848 addr = offset_addr;
1849 else
1850 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001851
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001852 EmulateInstruction::Context context;
1853 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001854 Register sp_reg;
Greg Clayton888a7332011-04-26 04:39:08 +00001855 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Caroline Tice3e407972011-03-18 19:41:00 +00001856 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001857 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001858 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001859 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001860 if (!success)
1861 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001862 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001863 return false;
1864 }
1865 else
1866 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001867 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001868 if (!success)
1869 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001870 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001871 return false;
1872 }
1873
Caroline Tice3e407972011-03-18 19:41:00 +00001874
1875 if (wback)
1876 {
1877 context.type = EmulateInstruction::eContextAdjustStackPointer;
1878 context.SetImmediateSigned (addr - sp);
1879 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1880 return false;
1881 }
Johnny Chence1ca772011-01-25 01:13:00 +00001882 }
1883 return true;
1884}
1885
Johnny Chen08c25e82011-01-31 18:02:28 +00001886// Vector Push stores multiple extension registers to the stack.
1887// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001888bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001889EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001890{
1891#if 0
1892 // ARM pseudo code...
1893 if (ConditionPassed())
1894 {
1895 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1896 address = SP - imm32;
1897 SP = SP - imm32;
1898 if single_regs then
1899 for r = 0 to regs-1
1900 MemA[address,4] = S[d+r]; address = address+4;
1901 else
1902 for r = 0 to regs-1
1903 // Store as two word-aligned words in the correct order for current endianness.
1904 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1905 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1906 address = address+8;
1907 }
1908#endif
1909
1910 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001911
Greg Clayton7bc39082011-03-24 23:53:38 +00001912 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001913 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001914 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001915 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001916 if (!success)
1917 return false;
1918 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001919 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001920 uint32_t imm32; // stack offset
1921 uint32_t regs; // number of registers
1922 switch (encoding) {
1923 case eEncodingT1:
1924 case eEncodingA1:
1925 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001926 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001927 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1928 // If UInt(imm8) is odd, see "FSTMX".
1929 regs = Bits32(opcode, 7, 0) / 2;
1930 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1931 if (regs == 0 || regs > 16 || (d + regs) > 32)
1932 return false;
1933 break;
1934 case eEncodingT2:
1935 case eEncodingA2:
1936 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001937 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001938 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1939 regs = Bits32(opcode, 7, 0);
1940 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1941 if (regs == 0 || regs > 16 || (d + regs) > 32)
1942 return false;
1943 break;
1944 default:
1945 return false;
1946 }
1947 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1948 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1949 addr_t sp_offset = imm32;
1950 addr_t addr = sp - sp_offset;
1951 uint32_t i;
1952
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001953 EmulateInstruction::Context context;
1954 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1955 Register dwarf_reg;
1956 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001957 Register sp_reg;
Greg Clayton888a7332011-04-26 04:39:08 +00001958 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001959 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001960 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001961 dwarf_reg.num = start_reg + d + i;
1962 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001963 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001964 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001965 if (!success)
1966 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001967 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001968 return false;
1969 addr += reg_byte_size;
1970 }
1971
1972 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001973 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001974
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001975 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001976 return false;
1977 }
1978 return true;
1979}
1980
Johnny Chen587a0a42011-02-01 18:35:28 +00001981// Vector Pop loads multiple extension registers from the stack.
1982// It also updates SP to point just above the loaded data.
1983bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001984EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00001985{
1986#if 0
1987 // ARM pseudo code...
1988 if (ConditionPassed())
1989 {
1990 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1991 address = SP;
1992 SP = SP + imm32;
1993 if single_regs then
1994 for r = 0 to regs-1
1995 S[d+r] = MemA[address,4]; address = address+4;
1996 else
1997 for r = 0 to regs-1
1998 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1999 // Combine the word-aligned words in the correct order for current endianness.
2000 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2001 }
2002#endif
2003
2004 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002005
Greg Clayton7bc39082011-03-24 23:53:38 +00002006 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002007 {
2008 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002009 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002010 if (!success)
2011 return false;
2012 bool single_regs;
2013 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2014 uint32_t imm32; // stack offset
2015 uint32_t regs; // number of registers
2016 switch (encoding) {
2017 case eEncodingT1:
2018 case eEncodingA1:
2019 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002020 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002021 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2022 // If UInt(imm8) is odd, see "FLDMX".
2023 regs = Bits32(opcode, 7, 0) / 2;
2024 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2025 if (regs == 0 || regs > 16 || (d + regs) > 32)
2026 return false;
2027 break;
2028 case eEncodingT2:
2029 case eEncodingA2:
2030 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002031 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002032 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2033 regs = Bits32(opcode, 7, 0);
2034 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2035 if (regs == 0 || regs > 16 || (d + regs) > 32)
2036 return false;
2037 break;
2038 default:
2039 return false;
2040 }
2041 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2042 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2043 addr_t sp_offset = imm32;
2044 addr_t addr = sp;
2045 uint32_t i;
2046 uint64_t data; // uint64_t to accomodate 64-bit registers.
2047
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002048 EmulateInstruction::Context context;
2049 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2050 Register dwarf_reg;
2051 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002052 Register sp_reg;
Greg Clayton888a7332011-04-26 04:39:08 +00002053 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002054 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002055 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002056 dwarf_reg.num = start_reg + d + i;
2057 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002058 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002059 if (!success)
2060 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002061 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002062 return false;
2063 addr += reg_byte_size;
2064 }
2065
2066 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002067 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002068
2069 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2070 return false;
2071 }
2072 return true;
2073}
2074
Johnny Chenb77be412011-02-04 00:40:18 +00002075// SVC (previously SWI)
2076bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002077EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002078{
2079#if 0
2080 // ARM pseudo code...
2081 if (ConditionPassed())
2082 {
2083 EncodingSpecificOperations();
2084 CallSupervisor();
2085 }
2086#endif
2087
2088 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002089
Greg Clayton7bc39082011-03-24 23:53:38 +00002090 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002091 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002092 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002093 addr_t lr; // next instruction address
2094 if (!success)
2095 return false;
2096 uint32_t imm32; // the immediate constant
2097 uint32_t mode; // ARM or Thumb mode
2098 switch (encoding) {
2099 case eEncodingT1:
2100 lr = (pc + 2) | 1u; // return address
2101 imm32 = Bits32(opcode, 7, 0);
2102 mode = eModeThumb;
2103 break;
2104 case eEncodingA1:
2105 lr = pc + 4; // return address
2106 imm32 = Bits32(opcode, 23, 0);
2107 mode = eModeARM;
2108 break;
2109 default:
2110 return false;
2111 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002112
2113 EmulateInstruction::Context context;
2114 context.type = EmulateInstruction::eContextSupervisorCall;
2115 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002116 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2117 return false;
2118 }
2119 return true;
2120}
2121
Johnny Chenc315f862011-02-05 00:46:10 +00002122// If Then makes up to four following instructions (the IT block) conditional.
2123bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002124EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002125{
2126#if 0
2127 // ARM pseudo code...
2128 EncodingSpecificOperations();
2129 ITSTATE.IT<7:0> = firstcond:mask;
2130#endif
2131
Johnny Chenc315f862011-02-05 00:46:10 +00002132 m_it_session.InitIT(Bits32(opcode, 7, 0));
2133 return true;
2134}
2135
Johnny Chen3b620b32011-02-07 20:11:47 +00002136// Branch causes a branch to a target address.
2137bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002138EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002139{
2140#if 0
2141 // ARM pseudo code...
2142 if (ConditionPassed())
2143 {
2144 EncodingSpecificOperations();
2145 BranchWritePC(PC + imm32);
2146 }
2147#endif
2148
2149 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002150
Greg Clayton7bc39082011-03-24 23:53:38 +00002151 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002152 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002153 EmulateInstruction::Context context;
2154 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002155 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002156 if (!success)
2157 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002158 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002159 int32_t imm32; // PC-relative offset
2160 switch (encoding) {
2161 case eEncodingT1:
2162 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2163 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002164 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002165 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002166 break;
2167 case eEncodingT2:
2168 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002169 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002170 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002171 break;
2172 case eEncodingT3:
2173 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2174 {
Johnny Chenbd599902011-02-10 21:39:01 +00002175 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002176 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002177 uint32_t J1 = Bit32(opcode, 13);
2178 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002179 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002180 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002181 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002182 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002183 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002184 break;
2185 }
2186 case eEncodingT4:
2187 {
Johnny Chenbd599902011-02-10 21:39:01 +00002188 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002189 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002190 uint32_t J1 = Bit32(opcode, 13);
2191 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002192 uint32_t imm11 = Bits32(opcode, 10, 0);
2193 uint32_t I1 = !(J1 ^ S);
2194 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002195 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002196 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002197 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002198 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002199 break;
2200 }
2201 case eEncodingA1:
2202 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002203 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002204 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002205 break;
2206 default:
2207 return false;
2208 }
2209 if (!BranchWritePC(context, target))
2210 return false;
2211 }
2212 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002213}
2214
Johnny Chen53ebab72011-02-08 23:21:57 +00002215// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2216// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2217// CBNZ, CBZ
2218bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002219EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002220{
2221#if 0
2222 // ARM pseudo code...
2223 EncodingSpecificOperations();
2224 if nonzero ^ IsZero(R[n]) then
2225 BranchWritePC(PC + imm32);
2226#endif
2227
2228 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002229
2230 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002231 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002232 if (!success)
2233 return false;
2234
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002235 EmulateInstruction::Context context;
2236 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002237 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002238 if (!success)
2239 return false;
2240
2241 addr_t target; // target address
2242 uint32_t imm32; // PC-relative offset to branch forward
2243 bool nonzero;
2244 switch (encoding) {
2245 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002246 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002247 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002248 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002249 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002250 break;
2251 default:
2252 return false;
2253 }
2254 if (nonzero ^ (reg_val == 0))
2255 if (!BranchWritePC(context, target))
2256 return false;
2257
2258 return true;
2259}
2260
Johnny Chen60299ec2011-02-17 19:34:27 +00002261// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2262// A base register provides a pointer to the table, and a second register supplies an index into the table.
2263// The branch length is twice the value of the byte returned from the table.
2264//
2265// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2266// A base register provides a pointer to the table, and a second register supplies an index into the table.
2267// The branch length is twice the value of the halfword returned from the table.
2268// TBB, TBH
2269bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002270EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002271{
2272#if 0
2273 // ARM pseudo code...
2274 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2275 if is_tbh then
2276 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2277 else
2278 halfwords = UInt(MemU[R[n]+R[m], 1]);
2279 BranchWritePC(PC + 2*halfwords);
2280#endif
2281
2282 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002283
2284 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2285 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2286 bool is_tbh; // true if table branch halfword
2287 switch (encoding) {
2288 case eEncodingT1:
2289 Rn = Bits32(opcode, 19, 16);
2290 Rm = Bits32(opcode, 3, 0);
2291 is_tbh = BitIsSet(opcode, 4);
2292 if (Rn == 13 || BadReg(Rm))
2293 return false;
2294 if (InITBlock() && !LastInITBlock())
2295 return false;
2296 break;
2297 default:
2298 return false;
2299 }
2300
2301 // Read the address of the table from the operand register Rn.
2302 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002303 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002304 if (!success)
2305 return false;
2306
2307 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002308 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002309 if (!success)
2310 return false;
2311
2312 // the offsetted table address
2313 addr_t addr = base + (is_tbh ? index*2 : index);
2314
2315 // PC-relative offset to branch forward
2316 EmulateInstruction::Context context;
2317 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002318 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002319 if (!success)
2320 return false;
2321
Johnny Chene39f22d2011-02-19 01:36:13 +00002322 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002323 if (!success)
2324 return false;
2325
2326 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002327 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002328 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2329 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2330
2331 if (!BranchWritePC(context, target))
2332 return false;
2333
2334 return true;
2335}
2336
Caroline Ticedcc11b32011-03-02 23:57:02 +00002337// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2338// It can optionally update the condition flags based on the result.
2339bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002340EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002341{
2342#if 0
2343 if ConditionPassed() then
2344 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002345 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002346 R[d] = result;
2347 if setflags then
2348 APSR.N = result<31>;
2349 APSR.Z = IsZeroBit(result);
2350 APSR.C = carry;
2351 APSR.V = overflow;
2352#endif
2353
2354 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002355
Greg Clayton7bc39082011-03-24 23:53:38 +00002356 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002357 {
2358 uint32_t d;
2359 uint32_t n;
2360 bool setflags;
2361 uint32_t imm32;
2362 uint32_t carry_out;
2363
2364 //EncodingSpecificOperations();
2365 switch (encoding)
2366 {
2367 case eEncodingT1:
2368 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2369 d = Bits32 (opcode, 2, 0);
2370 n = Bits32 (opcode, 5, 3);
2371 setflags = !InITBlock();
2372 imm32 = Bits32 (opcode, 8,6);
2373
2374 break;
2375
2376 case eEncodingT2:
2377 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2378 d = Bits32 (opcode, 10, 8);
2379 n = Bits32 (opcode, 10, 8);
2380 setflags = !InITBlock();
2381 imm32 = Bits32 (opcode, 7, 0);
2382
2383 break;
2384
2385 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002386 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2387 // if Rn == '1101' then SEE ADD (SP plus immediate);
2388 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002389 d = Bits32 (opcode, 11, 8);
2390 n = Bits32 (opcode, 19, 16);
2391 setflags = BitIsSet (opcode, 20);
2392 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2393
2394 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2395 if (BadReg (d) || (n == 15))
2396 return false;
2397
2398 break;
2399
2400 case eEncodingT4:
2401 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002402 // if Rn == '1111' then SEE ADR;
2403 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002404 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2405 d = Bits32 (opcode, 11, 8);
2406 n = Bits32 (opcode, 19, 16);
2407 setflags = false;
2408 uint32_t i = Bit32 (opcode, 26);
2409 uint32_t imm3 = Bits32 (opcode, 14, 12);
2410 uint32_t imm8 = Bits32 (opcode, 7, 0);
2411 imm32 = (i << 11) | (imm3 << 8) | imm8;
2412
2413 // if BadReg(d) then UNPREDICTABLE;
2414 if (BadReg (d))
2415 return false;
2416
2417 break;
2418 }
2419 default:
2420 return false;
2421 }
2422
2423 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2424 if (!success)
2425 return false;
2426
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002427 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002428 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2429
2430 Register reg_n;
2431 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2432
2433 EmulateInstruction::Context context;
2434 context.type = eContextAddition;
2435 context.SetRegisterPlusOffset (reg_n, imm32);
2436
2437 //R[d] = result;
2438 //if setflags then
2439 //APSR.N = result<31>;
2440 //APSR.Z = IsZeroBit(result);
2441 //APSR.C = carry;
2442 //APSR.V = overflow;
2443 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2444 return false;
2445
2446 }
2447 return true;
2448}
2449
Johnny Chen8fa20592011-02-18 01:22:22 +00002450// This instruction adds an immediate value to a register value, and writes the result to the destination
2451// register. It can optionally update the condition flags based on the result.
2452bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002453EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002454{
2455#if 0
2456 // ARM pseudo code...
2457 if ConditionPassed() then
2458 EncodingSpecificOperations();
2459 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2460 if d == 15 then
2461 ALUWritePC(result); // setflags is always FALSE here
2462 else
2463 R[d] = result;
2464 if setflags then
2465 APSR.N = result<31>;
2466 APSR.Z = IsZeroBit(result);
2467 APSR.C = carry;
2468 APSR.V = overflow;
2469#endif
2470
2471 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002472
Greg Clayton7bc39082011-03-24 23:53:38 +00002473 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002474 {
2475 uint32_t Rd, Rn;
2476 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2477 bool setflags;
2478 switch (encoding)
2479 {
2480 case eEncodingA1:
2481 Rd = Bits32(opcode, 15, 12);
2482 Rn = Bits32(opcode, 19, 16);
2483 setflags = BitIsSet(opcode, 20);
2484 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2485 break;
2486 default:
2487 return false;
2488 }
2489
Johnny Chen8fa20592011-02-18 01:22:22 +00002490 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002491 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002492 if (!success)
2493 return false;
2494
2495 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2496
2497 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +00002498 context.type = EmulateInstruction::eContextAddition;
2499 Register dwarf_reg;
2500 dwarf_reg.SetRegister (eRegisterKindDWARF, Rn);
2501 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002502
2503 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2504 return false;
2505 }
2506 return true;
2507}
2508
Johnny Chend761dcf2011-02-17 22:03:29 +00002509// This instruction adds a register value and an optionally-shifted register value, and writes the result
2510// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002511bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002512EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002513{
2514#if 0
2515 // ARM pseudo code...
2516 if ConditionPassed() then
2517 EncodingSpecificOperations();
2518 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2519 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2520 if d == 15 then
2521 ALUWritePC(result); // setflags is always FALSE here
2522 else
2523 R[d] = result;
2524 if setflags then
2525 APSR.N = result<31>;
2526 APSR.Z = IsZeroBit(result);
2527 APSR.C = carry;
2528 APSR.V = overflow;
2529#endif
2530
2531 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002532
Greg Clayton7bc39082011-03-24 23:53:38 +00002533 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002534 {
2535 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002536 ARM_ShifterType shift_t;
2537 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002538 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002539 switch (encoding)
2540 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002541 case eEncodingT1:
2542 Rd = Bits32(opcode, 2, 0);
2543 Rn = Bits32(opcode, 5, 3);
2544 Rm = Bits32(opcode, 8, 6);
2545 setflags = !InITBlock();
2546 shift_t = SRType_LSL;
2547 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002548 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002549 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002550 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002551 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002552 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002553 shift_t = SRType_LSL;
2554 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002555 if (Rn == 15 && Rm == 15)
2556 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002557 if (Rd == 15 && InITBlock() && !LastInITBlock())
2558 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002559 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002560 case eEncodingA1:
2561 Rd = Bits32(opcode, 15, 12);
2562 Rn = Bits32(opcode, 19, 16);
2563 Rm = Bits32(opcode, 3, 0);
2564 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002565 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002566 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002567 default:
2568 return false;
2569 }
2570
Johnny Chen26863dc2011-02-09 23:43:29 +00002571 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002572 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002573 if (!success)
2574 return false;
2575
2576 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002577 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002578 if (!success)
2579 return false;
2580
Johnny Chene97c0d52011-02-18 19:32:20 +00002581 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002582 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002583
2584 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002585 context.type = EmulateInstruction::eContextAddition;
2586 Register op1_reg;
2587 Register op2_reg;
2588 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2589 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2590 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002591
Johnny Chen10530c22011-02-17 22:37:12 +00002592 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002593 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002594 }
2595 return true;
2596}
2597
Johnny Chen34075cb2011-02-22 01:56:31 +00002598// Compare Negative (immediate) adds a register value and an immediate value.
2599// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002600bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002601EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002602{
2603#if 0
2604 // ARM pseudo code...
2605 if ConditionPassed() then
2606 EncodingSpecificOperations();
2607 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2608 APSR.N = result<31>;
2609 APSR.Z = IsZeroBit(result);
2610 APSR.C = carry;
2611 APSR.V = overflow;
2612#endif
2613
2614 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002615
2616 uint32_t Rn; // the first operand
2617 uint32_t imm32; // the immediate value to be compared with
2618 switch (encoding) {
2619 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002620 Rn = Bits32(opcode, 19, 16);
2621 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2622 if (Rn == 15)
2623 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002624 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002625 case eEncodingA1:
2626 Rn = Bits32(opcode, 19, 16);
2627 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2628 break;
2629 default:
2630 return false;
2631 }
2632 // Read the register value from the operand register Rn.
2633 uint32_t reg_val = ReadCoreReg(Rn, &success);
2634 if (!success)
2635 return false;
2636
Johnny Chen078fbc62011-02-22 19:48:22 +00002637 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002638
2639 EmulateInstruction::Context context;
2640 context.type = EmulateInstruction::eContextImmediate;
2641 context.SetNoArgs ();
2642 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2643 return false;
2644
2645 return true;
2646}
2647
2648// Compare Negative (register) adds a register value and an optionally-shifted register value.
2649// It updates the condition flags based on the result, and discards the result.
2650bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002651EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002652{
2653#if 0
2654 // ARM pseudo code...
2655 if ConditionPassed() then
2656 EncodingSpecificOperations();
2657 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2658 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2659 APSR.N = result<31>;
2660 APSR.Z = IsZeroBit(result);
2661 APSR.C = carry;
2662 APSR.V = overflow;
2663#endif
2664
2665 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002666
2667 uint32_t Rn; // the first operand
2668 uint32_t Rm; // the second operand
2669 ARM_ShifterType shift_t;
2670 uint32_t shift_n; // the shift applied to the value read from Rm
2671 switch (encoding) {
2672 case eEncodingT1:
2673 Rn = Bits32(opcode, 2, 0);
2674 Rm = Bits32(opcode, 5, 3);
2675 shift_t = SRType_LSL;
2676 shift_n = 0;
2677 break;
2678 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002679 Rn = Bits32(opcode, 19, 16);
2680 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002681 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002682 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2683 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002684 return false;
2685 break;
2686 case eEncodingA1:
2687 Rn = Bits32(opcode, 19, 16);
2688 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002689 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002690 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002691 default:
2692 return false;
2693 }
2694 // Read the register value from register Rn.
2695 uint32_t val1 = ReadCoreReg(Rn, &success);
2696 if (!success)
2697 return false;
2698
2699 // Read the register value from register Rm.
2700 uint32_t val2 = ReadCoreReg(Rm, &success);
2701 if (!success)
2702 return false;
2703
2704 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002705 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002706
2707 EmulateInstruction::Context context;
2708 context.type = EmulateInstruction::eContextImmediate;
2709 context.SetNoArgs();
2710 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2711 return false;
2712
2713 return true;
2714}
2715
2716// Compare (immediate) subtracts an immediate value from a register value.
2717// It updates the condition flags based on the result, and discards the result.
2718bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002719EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002720{
2721#if 0
2722 // ARM pseudo code...
2723 if ConditionPassed() then
2724 EncodingSpecificOperations();
2725 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2726 APSR.N = result<31>;
2727 APSR.Z = IsZeroBit(result);
2728 APSR.C = carry;
2729 APSR.V = overflow;
2730#endif
2731
2732 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002733
2734 uint32_t Rn; // the first operand
2735 uint32_t imm32; // the immediate value to be compared with
2736 switch (encoding) {
2737 case eEncodingT1:
2738 Rn = Bits32(opcode, 10, 8);
2739 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002740 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002741 case eEncodingT2:
2742 Rn = Bits32(opcode, 19, 16);
2743 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2744 if (Rn == 15)
2745 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002746 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002747 case eEncodingA1:
2748 Rn = Bits32(opcode, 19, 16);
2749 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002750 break;
2751 default:
2752 return false;
2753 }
2754 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002755 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002756 if (!success)
2757 return false;
2758
Johnny Chen10530c22011-02-17 22:37:12 +00002759 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2760
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002761 EmulateInstruction::Context context;
2762 context.type = EmulateInstruction::eContextImmediate;
2763 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002764 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2765 return false;
2766
Johnny Chend4dc4442011-02-11 02:02:56 +00002767 return true;
2768}
2769
Johnny Chen34075cb2011-02-22 01:56:31 +00002770// Compare (register) subtracts an optionally-shifted register value from a register value.
2771// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002772bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002773EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002774{
2775#if 0
2776 // ARM pseudo code...
2777 if ConditionPassed() then
2778 EncodingSpecificOperations();
2779 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2780 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2781 APSR.N = result<31>;
2782 APSR.Z = IsZeroBit(result);
2783 APSR.C = carry;
2784 APSR.V = overflow;
2785#endif
2786
2787 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002788
2789 uint32_t Rn; // the first operand
2790 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002791 ARM_ShifterType shift_t;
2792 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002793 switch (encoding) {
2794 case eEncodingT1:
2795 Rn = Bits32(opcode, 2, 0);
2796 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002797 shift_t = SRType_LSL;
2798 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002799 break;
2800 case eEncodingT2:
2801 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2802 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002803 shift_t = SRType_LSL;
2804 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002805 if (Rn < 8 && Rm < 8)
2806 return false;
2807 if (Rn == 15 || Rm == 15)
2808 return false;
2809 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002810 case eEncodingA1:
2811 Rn = Bits32(opcode, 19, 16);
2812 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002813 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002814 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002815 default:
2816 return false;
2817 }
2818 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002819 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002820 if (!success)
2821 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002822
Johnny Chene4a4d302011-02-11 21:53:58 +00002823 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002824 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002825 if (!success)
2826 return false;
2827
Johnny Chen34075cb2011-02-22 01:56:31 +00002828 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2829 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002830
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002831 EmulateInstruction::Context context;
2832 context.type = EmulateInstruction::eContextImmediate;
2833 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002834 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2835 return false;
2836
Johnny Chene4a4d302011-02-11 21:53:58 +00002837 return true;
2838}
2839
Johnny Chen82f16aa2011-02-15 20:10:55 +00002840// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2841// shifting in copies of its sign bit, and writes the result to the destination register. It can
2842// optionally update the condition flags based on the result.
2843bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002844EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002845{
2846#if 0
2847 // ARM pseudo code...
2848 if ConditionPassed() then
2849 EncodingSpecificOperations();
2850 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2851 if d == 15 then // Can only occur for ARM encoding
2852 ALUWritePC(result); // setflags is always FALSE here
2853 else
2854 R[d] = result;
2855 if setflags then
2856 APSR.N = result<31>;
2857 APSR.Z = IsZeroBit(result);
2858 APSR.C = carry;
2859 // APSR.V unchanged
2860#endif
2861
Greg Clayton7bc39082011-03-24 23:53:38 +00002862 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002863}
2864
2865// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2866// shifting in copies of its sign bit, and writes the result to the destination register.
2867// The variable number of bits is read from the bottom byte of a register. It can optionally update
2868// the condition flags based on the result.
2869bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002870EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002871{
2872#if 0
2873 // ARM pseudo code...
2874 if ConditionPassed() then
2875 EncodingSpecificOperations();
2876 shift_n = UInt(R[m]<7:0>);
2877 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2878 R[d] = result;
2879 if setflags then
2880 APSR.N = result<31>;
2881 APSR.Z = IsZeroBit(result);
2882 APSR.C = carry;
2883 // APSR.V unchanged
2884#endif
2885
Greg Clayton7bc39082011-03-24 23:53:38 +00002886 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002887}
2888
2889// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2890// shifting in zeros, and writes the result to the destination register. It can optionally
2891// update the condition flags based on the result.
2892bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002893EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002894{
2895#if 0
2896 // ARM pseudo code...
2897 if ConditionPassed() then
2898 EncodingSpecificOperations();
2899 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2900 if d == 15 then // Can only occur for ARM encoding
2901 ALUWritePC(result); // setflags is always FALSE here
2902 else
2903 R[d] = result;
2904 if setflags then
2905 APSR.N = result<31>;
2906 APSR.Z = IsZeroBit(result);
2907 APSR.C = carry;
2908 // APSR.V unchanged
2909#endif
2910
Greg Clayton7bc39082011-03-24 23:53:38 +00002911 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002912}
2913
2914// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2915// shifting in zeros, and writes the result to the destination register. The variable number
2916// of bits is read from the bottom byte of a register. It can optionally update the condition
2917// flags based on the result.
2918bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002919EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002920{
2921#if 0
2922 // ARM pseudo code...
2923 if ConditionPassed() then
2924 EncodingSpecificOperations();
2925 shift_n = UInt(R[m]<7:0>);
2926 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2927 R[d] = result;
2928 if setflags then
2929 APSR.N = result<31>;
2930 APSR.Z = IsZeroBit(result);
2931 APSR.C = carry;
2932 // APSR.V unchanged
2933#endif
2934
Greg Clayton7bc39082011-03-24 23:53:38 +00002935 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002936}
2937
2938// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2939// shifting in zeros, and writes the result to the destination register. It can optionally
2940// update the condition flags based on the result.
2941bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002942EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002943{
2944#if 0
2945 // ARM pseudo code...
2946 if ConditionPassed() then
2947 EncodingSpecificOperations();
2948 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2949 if d == 15 then // Can only occur for ARM encoding
2950 ALUWritePC(result); // setflags is always FALSE here
2951 else
2952 R[d] = result;
2953 if setflags then
2954 APSR.N = result<31>;
2955 APSR.Z = IsZeroBit(result);
2956 APSR.C = carry;
2957 // APSR.V unchanged
2958#endif
2959
Greg Clayton7bc39082011-03-24 23:53:38 +00002960 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002961}
2962
2963// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2964// shifting in zeros, and writes the result to the destination register. The variable number
2965// of bits is read from the bottom byte of a register. It can optionally update the condition
2966// flags based on the result.
2967bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002968EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002969{
2970#if 0
2971 // ARM pseudo code...
2972 if ConditionPassed() then
2973 EncodingSpecificOperations();
2974 shift_n = UInt(R[m]<7:0>);
2975 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2976 R[d] = result;
2977 if setflags then
2978 APSR.N = result<31>;
2979 APSR.Z = IsZeroBit(result);
2980 APSR.C = carry;
2981 // APSR.V unchanged
2982#endif
2983
Greg Clayton7bc39082011-03-24 23:53:38 +00002984 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002985}
2986
Johnny Cheneeab4852011-02-16 22:14:44 +00002987// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2988// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2989// It can optionally update the condition flags based on the result.
2990bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002991EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002992{
2993#if 0
2994 // ARM pseudo code...
2995 if ConditionPassed() then
2996 EncodingSpecificOperations();
2997 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2998 if d == 15 then // Can only occur for ARM encoding
2999 ALUWritePC(result); // setflags is always FALSE here
3000 else
3001 R[d] = result;
3002 if setflags then
3003 APSR.N = result<31>;
3004 APSR.Z = IsZeroBit(result);
3005 APSR.C = carry;
3006 // APSR.V unchanged
3007#endif
3008
Greg Clayton7bc39082011-03-24 23:53:38 +00003009 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003010}
3011
3012// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3013// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3014// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3015// flags based on the result.
3016bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003017EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003018{
3019#if 0
3020 // ARM pseudo code...
3021 if ConditionPassed() then
3022 EncodingSpecificOperations();
3023 shift_n = UInt(R[m]<7:0>);
3024 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3025 R[d] = result;
3026 if setflags then
3027 APSR.N = result<31>;
3028 APSR.Z = IsZeroBit(result);
3029 APSR.C = carry;
3030 // APSR.V unchanged
3031#endif
3032
Greg Clayton7bc39082011-03-24 23:53:38 +00003033 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003034}
3035
3036// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3037// with the carry flag shifted into bit [31].
3038//
3039// RRX can optionally update the condition flags based on the result.
3040// In that case, bit [0] is shifted into the carry flag.
3041bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003042EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003043{
3044#if 0
3045 // ARM pseudo code...
3046 if ConditionPassed() then
3047 EncodingSpecificOperations();
3048 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3049 if d == 15 then // Can only occur for ARM encoding
3050 ALUWritePC(result); // setflags is always FALSE here
3051 else
3052 R[d] = result;
3053 if setflags then
3054 APSR.N = result<31>;
3055 APSR.Z = IsZeroBit(result);
3056 APSR.C = carry;
3057 // APSR.V unchanged
3058#endif
3059
Greg Clayton7bc39082011-03-24 23:53:38 +00003060 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003061}
3062
Johnny Chen41a0a152011-02-16 01:27:54 +00003063bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003064EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003065{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003066 assert(shift_type == SRType_ASR
3067 || shift_type == SRType_LSL
3068 || shift_type == SRType_LSR
3069 || shift_type == SRType_ROR
3070 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003071
Johnny Chen82f16aa2011-02-15 20:10:55 +00003072 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003073
Greg Clayton7bc39082011-03-24 23:53:38 +00003074 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003075 {
Johnny Chene7f89532011-02-15 23:22:46 +00003076 uint32_t Rd; // the destination register
3077 uint32_t Rm; // the first operand register
3078 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003079 uint32_t carry; // the carry bit after the shift operation
3080 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003081
3082 // Special case handling!
3083 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003084 ARMEncoding use_encoding = encoding;
3085 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003086 {
3087 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3088 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003089 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003090 }
3091
Greg Clayton7bc39082011-03-24 23:53:38 +00003092 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003093 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003094 // Due to the above special case handling!
3095 assert(shift_type != SRType_ROR);
3096
Johnny Chen82f16aa2011-02-15 20:10:55 +00003097 Rd = Bits32(opcode, 2, 0);
3098 Rm = Bits32(opcode, 5, 3);
3099 setflags = !InITBlock();
3100 imm5 = Bits32(opcode, 10, 6);
3101 break;
3102 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003103 // A8.6.141 RRX
3104 assert(shift_type != SRType_RRX);
3105
Johnny Chen82f16aa2011-02-15 20:10:55 +00003106 Rd = Bits32(opcode, 11, 8);
3107 Rm = Bits32(opcode, 3, 0);
3108 setflags = BitIsSet(opcode, 20);
3109 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3110 if (BadReg(Rd) || BadReg(Rm))
3111 return false;
3112 break;
3113 case eEncodingA1:
3114 Rd = Bits32(opcode, 15, 12);
3115 Rm = Bits32(opcode, 3, 0);
3116 setflags = BitIsSet(opcode, 20);
3117 imm5 = Bits32(opcode, 11, 7);
3118 break;
3119 default:
3120 return false;
3121 }
3122
Johnny Cheneeab4852011-02-16 22:14:44 +00003123 // A8.6.139 ROR (immediate)
3124 if (shift_type == SRType_ROR && imm5 == 0)
3125 shift_type = SRType_RRX;
3126
Johnny Chen82f16aa2011-02-15 20:10:55 +00003127 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003128 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003129 if (!success)
3130 return false;
3131
Johnny Cheneeab4852011-02-16 22:14:44 +00003132 // Decode the shift amount if not RRX.
3133 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003134
Johnny Chene97c0d52011-02-18 19:32:20 +00003135 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003136
3137 // The context specifies that an immediate is to be moved into Rd.
3138 EmulateInstruction::Context context;
3139 context.type = EmulateInstruction::eContextImmediate;
3140 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003141
Johnny Chen10530c22011-02-17 22:37:12 +00003142 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003143 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003144 }
3145 return true;
3146}
3147
Johnny Chene7f89532011-02-15 23:22:46 +00003148bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003149EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003150{
Johnny Chen41a0a152011-02-16 01:27:54 +00003151 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003152
3153 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003154
Greg Clayton7bc39082011-03-24 23:53:38 +00003155 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003156 {
3157 uint32_t Rd; // the destination register
3158 uint32_t Rn; // the first operand register
3159 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3160 uint32_t carry; // the carry bit after the shift operation
3161 bool setflags;
3162 switch (encoding) {
3163 case eEncodingT1:
3164 Rd = Bits32(opcode, 2, 0);
3165 Rn = Rd;
3166 Rm = Bits32(opcode, 5, 3);
3167 setflags = !InITBlock();
3168 break;
3169 case eEncodingT2:
3170 Rd = Bits32(opcode, 11, 8);
3171 Rn = Bits32(opcode, 19, 16);
3172 Rm = Bits32(opcode, 3, 0);
3173 setflags = BitIsSet(opcode, 20);
3174 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3175 return false;
3176 break;
3177 case eEncodingA1:
3178 Rd = Bits32(opcode, 15, 12);
3179 Rn = Bits32(opcode, 3, 0);
3180 Rm = Bits32(opcode, 11, 8);
3181 setflags = BitIsSet(opcode, 20);
3182 if (Rd == 15 || Rn == 15 || Rm == 15)
3183 return false;
3184 break;
3185 default:
3186 return false;
3187 }
3188
3189 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003190 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003191 if (!success)
3192 return false;
3193 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003194 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003195 if (!success)
3196 return false;
3197
3198 // Get the shift amount.
3199 uint32_t amt = Bits32(val, 7, 0);
3200
Johnny Chene97c0d52011-02-18 19:32:20 +00003201 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003202
3203 // The context specifies that an immediate is to be moved into Rd.
3204 EmulateInstruction::Context context;
3205 context.type = EmulateInstruction::eContextImmediate;
3206 context.SetNoArgs ();
3207
Johnny Chen10530c22011-02-17 22:37:12 +00003208 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003209 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003210 }
3211 return true;
3212}
3213
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003214// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003215// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003216// can be written back to the base register.
3217bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003218EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003219{
3220#if 0
3221 // ARM pseudo code...
3222 if ConditionPassed()
3223 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3224 address = R[n];
3225
3226 for i = 0 to 14
3227 if registers<i> == '1' then
3228 R[i] = MemA[address, 4]; address = address + 4;
3229 if registers<15> == '1' then
3230 LoadWritePC (MemA[address, 4]);
3231
3232 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3233 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3234
3235#endif
3236
3237 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003238
Greg Clayton7bc39082011-03-24 23:53:38 +00003239 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003240 {
3241 uint32_t n;
3242 uint32_t registers = 0;
3243 bool wback;
3244 const uint32_t addr_byte_size = GetAddressByteSize();
3245 switch (encoding)
3246 {
3247 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003248 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003249 n = Bits32 (opcode, 10, 8);
3250 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003251 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003252 wback = BitIsClear (registers, n);
3253 // if BitCount(registers) < 1 then UNPREDICTABLE;
3254 if (BitCount(registers) < 1)
3255 return false;
3256 break;
3257 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003258 // if W == '1' && Rn == '1101' then SEE POP;
3259 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003260 n = Bits32 (opcode, 19, 16);
3261 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003262 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003263 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003264
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003265 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003266 if ((n == 15)
3267 || (BitCount (registers) < 2)
3268 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3269 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003270
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003271 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003272 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003273 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003274
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003275 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003276 if (wback
3277 && BitIsSet (registers, n))
3278 return false;
3279 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003280
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003281 case eEncodingA1:
3282 n = Bits32 (opcode, 19, 16);
3283 registers = Bits32 (opcode, 15, 0);
3284 wback = BitIsSet (opcode, 21);
3285 if ((n == 15)
3286 || (BitCount (registers) < 1))
3287 return false;
3288 break;
3289 default:
3290 return false;
3291 }
3292
3293 int32_t offset = 0;
3294 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3295 if (!success)
3296 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003297
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003298 EmulateInstruction::Context context;
3299 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3300 Register dwarf_reg;
3301 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3302 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003303
3304 for (int i = 0; i < 14; ++i)
3305 {
3306 if (BitIsSet (registers, i))
3307 {
Caroline Tice85aab332011-02-08 23:56:10 +00003308 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003309 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003310 if (wback && (n == 13)) // Pop Instruction
3311 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3312
3313 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003314 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003315 if (!success)
3316 return false;
3317
3318 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3319 return false;
3320
3321 offset += addr_byte_size;
3322 }
3323 }
3324
3325 if (BitIsSet (registers, 15))
3326 {
3327 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003328 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003329 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003330 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003331 if (!success)
3332 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003333 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003334 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003335 return false;
3336 }
3337
3338 if (wback && BitIsClear (registers, n))
3339 {
Caroline Ticefa172202011-02-11 22:49:54 +00003340 // R[n] = R[n] + 4 * BitCount (registers)
3341 int32_t offset = addr_byte_size * BitCount (registers);
3342 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003343 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003344
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003345 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3346 return false;
3347 }
3348 if (wback && BitIsSet (registers, n))
3349 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003350 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003351 }
3352 return true;
3353}
Caroline Tice713c2662011-02-11 17:59:55 +00003354
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003355// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3356// The consecutive memory locations end at this address and the address just below the lowest of those locations
3357// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003358bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003359EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003360{
3361#if 0
3362 // ARM pseudo code...
3363 if ConditionPassed() then
3364 EncodingSpecificOperations();
3365 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003366
Caroline Tice713c2662011-02-11 17:59:55 +00003367 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003368 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003369 R[i] = MemA[address,4]; address = address + 4;
3370
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003371 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003372 LoadWritePC(MemA[address,4]);
3373
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003374 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3375 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003376#endif
3377
3378 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003379
Greg Clayton7bc39082011-03-24 23:53:38 +00003380 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003381 {
3382 uint32_t n;
3383 uint32_t registers = 0;
3384 bool wback;
3385 const uint32_t addr_byte_size = GetAddressByteSize();
3386
3387 // EncodingSpecificOperations();
3388 switch (encoding)
3389 {
3390 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003391 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003392 n = Bits32 (opcode, 19, 16);
3393 registers = Bits32 (opcode, 15, 0);
3394 wback = BitIsSet (opcode, 21);
3395
3396 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3397 if ((n == 15) || (BitCount (registers) < 1))
3398 return false;
3399
3400 break;
3401
3402 default:
3403 return false;
3404 }
3405 // address = R[n] - 4*BitCount(registers) + 4;
3406
3407 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003408 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003409
3410 if (!success)
3411 return false;
3412
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003413 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003414
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003415 EmulateInstruction::Context context;
3416 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3417 Register dwarf_reg;
3418 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3419 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003420
3421 // for i = 0 to 14
3422 for (int i = 0; i < 14; ++i)
3423 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003424 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003425 if (BitIsSet (registers, i))
3426 {
3427 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003428 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003429 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003430 if (!success)
3431 return false;
3432 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3433 return false;
3434 offset += addr_byte_size;
3435 }
3436 }
3437
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003438 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003439 // LoadWritePC(MemA[address,4]);
3440 if (BitIsSet (registers, 15))
3441 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003442 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003443 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003444 if (!success)
3445 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003446 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003447 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003448 return false;
3449 }
3450
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003451 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003452 if (wback && BitIsClear (registers, n))
3453 {
Caroline Tice713c2662011-02-11 17:59:55 +00003454 if (!success)
3455 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003456
3457 offset = (addr_byte_size * BitCount (registers)) * -1;
3458 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003459 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003460 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003461 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3462 return false;
3463 }
3464
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003465 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003466 if (wback && BitIsSet (registers, n))
3467 return WriteBits32Unknown (n);
3468 }
3469 return true;
3470}
3471
3472// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3473// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3474// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003475bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003476EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003477{
3478#if 0
3479 // ARM pseudo code...
3480 if ConditionPassed() then
3481 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3482 address = R[n] - 4*BitCount(registers);
3483
3484 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003485 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003486 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003487 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003488 LoadWritePC(MemA[address,4]);
3489
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003490 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3491 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003492#endif
3493
3494 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003495
Greg Clayton7bc39082011-03-24 23:53:38 +00003496 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003497 {
3498 uint32_t n;
3499 uint32_t registers = 0;
3500 bool wback;
3501 const uint32_t addr_byte_size = GetAddressByteSize();
3502 switch (encoding)
3503 {
3504 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003505 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003506 n = Bits32 (opcode, 19, 16);
3507 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003508 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003509 wback = BitIsSet (opcode, 21);
3510
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003511 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003512 if ((n == 15)
3513 || (BitCount (registers) < 2)
3514 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3515 return false;
3516
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003517 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003518 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003519 return false;
3520
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003521 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003522 if (wback && BitIsSet (registers, n))
3523 return false;
3524
3525 break;
3526
3527 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003528 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003529 n = Bits32 (opcode, 19, 16);
3530 registers = Bits32 (opcode, 15, 0);
3531 wback = BitIsSet (opcode, 21);
3532
3533 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3534 if ((n == 15) || (BitCount (registers) < 1))
3535 return false;
3536
3537 break;
3538
3539 default:
3540 return false;
3541 }
3542
Caroline Tice713c2662011-02-11 17:59:55 +00003543 // address = R[n] - 4*BitCount(registers);
3544
Caroline Tice0b29e242011-02-08 23:16:02 +00003545 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003546 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003547
3548 if (!success)
3549 return false;
3550
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003551 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003552 EmulateInstruction::Context context;
3553 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3554 Register dwarf_reg;
3555 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003556 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003557
3558 for (int i = 0; i < 14; ++i)
3559 {
3560 if (BitIsSet (registers, i))
3561 {
3562 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003563 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003564 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003565 if (!success)
3566 return false;
3567
3568 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3569 return false;
3570
3571 offset += addr_byte_size;
3572 }
3573 }
3574
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003575 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003576 // LoadWritePC(MemA[address,4]);
3577 if (BitIsSet (registers, 15))
3578 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003579 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003580 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003581 if (!success)
3582 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003583 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003584 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003585 return false;
3586 }
3587
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003588 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003589 if (wback && BitIsClear (registers, n))
3590 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003591 if (!success)
3592 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003593
3594 offset = (addr_byte_size * BitCount (registers)) * -1;
3595 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003596 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003597 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003598 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3599 return false;
3600 }
3601
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003602 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003603 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003604 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003605 }
3606 return true;
3607}
Caroline Tice85aab332011-02-08 23:56:10 +00003608
Caroline Tice713c2662011-02-11 17:59:55 +00003609// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3610// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3611// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003612bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003613EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003614{
3615#if 0
3616 if ConditionPassed() then
3617 EncodingSpecificOperations();
3618 address = R[n] + 4;
3619
3620 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003621 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003622 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003623 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003624 LoadWritePC(MemA[address,4]);
3625
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003626 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3627 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003628#endif
3629
3630 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003631
Greg Clayton7bc39082011-03-24 23:53:38 +00003632 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003633 {
3634 uint32_t n;
3635 uint32_t registers = 0;
3636 bool wback;
3637 const uint32_t addr_byte_size = GetAddressByteSize();
3638 switch (encoding)
3639 {
3640 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003641 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003642 n = Bits32 (opcode, 19, 16);
3643 registers = Bits32 (opcode, 15, 0);
3644 wback = BitIsSet (opcode, 21);
3645
3646 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3647 if ((n == 15) || (BitCount (registers) < 1))
3648 return false;
3649
3650 break;
3651 default:
3652 return false;
3653 }
3654 // address = R[n] + 4;
3655
3656 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003657 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003658
3659 if (!success)
3660 return false;
3661
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003662 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003663
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003664 EmulateInstruction::Context context;
3665 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3666 Register dwarf_reg;
3667 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3668 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003669
3670 for (int i = 0; i < 14; ++i)
3671 {
3672 if (BitIsSet (registers, i))
3673 {
3674 // R[i] = MemA[address,4]; address = address + 4;
3675
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003676 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003677 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003678 if (!success)
3679 return false;
3680
3681 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3682 return false;
3683
3684 offset += addr_byte_size;
3685 }
3686 }
3687
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003688 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003689 // LoadWritePC(MemA[address,4]);
3690 if (BitIsSet (registers, 15))
3691 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003692 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003693 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003694 if (!success)
3695 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003696 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003697 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003698 return false;
3699 }
3700
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003701 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003702 if (wback && BitIsClear (registers, n))
3703 {
Caroline Tice85aab332011-02-08 23:56:10 +00003704 if (!success)
3705 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003706
3707 offset = addr_byte_size * BitCount (registers);
3708 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003709 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003710 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003711 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3712 return false;
3713 }
3714
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003715 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003716 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003717 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003718 }
3719 return true;
3720}
Caroline Tice0b29e242011-02-08 23:16:02 +00003721
Johnny Chenef21b592011-02-10 01:52:38 +00003722// Load Register (immediate) calculates an address from a base register value and
3723// an immediate offset, loads a word from memory, and writes to a register.
3724// LDR (immediate, Thumb)
3725bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003726EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003727{
3728#if 0
3729 // ARM pseudo code...
3730 if (ConditionPassed())
3731 {
3732 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3733 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3734 address = if index then offset_addr else R[n];
3735 data = MemU[address,4];
3736 if wback then R[n] = offset_addr;
3737 if t == 15 then
3738 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3739 elsif UnalignedSupport() || address<1:0> = '00' then
3740 R[t] = data;
3741 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3742 }
3743#endif
3744
3745 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003746
Greg Clayton7bc39082011-03-24 23:53:38 +00003747 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003748 {
3749 uint32_t Rt; // the destination register
3750 uint32_t Rn; // the base register
3751 uint32_t imm32; // the immediate offset used to form the address
3752 addr_t offset_addr; // the offset address
3753 addr_t address; // the calculated address
3754 uint32_t data; // the literal data value from memory load
3755 bool add, index, wback;
3756 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003757 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003758 Rt = Bits32(opcode, 2, 0);
3759 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003760 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3761 // index = TRUE; add = TRUE; wback = FALSE
3762 add = true;
3763 index = true;
3764 wback = false;
3765
3766 break;
3767
3768 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003769 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003770 Rt = Bits32 (opcode, 10, 8);
3771 Rn = 13;
3772 imm32 = Bits32 (opcode, 7, 0) << 2;
3773
3774 // index = TRUE; add = TRUE; wback = FALSE;
3775 index = true;
3776 add = true;
3777 wback = false;
3778
3779 break;
3780
3781 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003782 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003783 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3784 Rt = Bits32 (opcode, 15, 12);
3785 Rn = Bits32 (opcode, 19, 16);
3786 imm32 = Bits32 (opcode, 11, 0);
3787
3788 // index = TRUE; add = TRUE; wback = FALSE;
3789 index = true;
3790 add = true;
3791 wback = false;
3792
3793 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3794 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3795 return false;
3796
3797 break;
3798
3799 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003800 // if Rn == '1111' then SEE LDR (literal);
3801 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3802 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3803 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003804 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3805 return false;
3806
3807 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3808 Rt = Bits32 (opcode, 15, 12);
3809 Rn = Bits32 (opcode, 19, 16);
3810 imm32 = Bits32 (opcode, 7, 0);
3811
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003812 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003813 index = BitIsSet (opcode, 10);
3814 add = BitIsSet (opcode, 9);
3815 wback = BitIsSet (opcode, 8);
3816
3817 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3818 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3819 return false;
3820
3821 break;
3822
3823 default:
3824 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003825 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003826 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003827 if (!success)
3828 return false;
3829 if (add)
3830 offset_addr = base + imm32;
3831 else
3832 offset_addr = base - imm32;
3833
3834 address = (index ? offset_addr : base);
3835
Caroline Ticebaf1f642011-03-24 19:23:45 +00003836 Register base_reg;
3837 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003838 if (wback)
3839 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003840 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003841 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3842 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003843
Johnny Chenef21b592011-02-10 01:52:38 +00003844 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3845 return false;
3846 }
3847
3848 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003849 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003850 context.type = EmulateInstruction::eContextRegisterLoad;
3851 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003852
3853 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003854 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003855 if (!success)
3856 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003857
3858 if (Rt == 15)
3859 {
3860 if (Bits32(address, 1, 0) == 0)
3861 {
Johnny Chen668b4512011-02-15 21:08:58 +00003862 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003863 return false;
3864 }
3865 else
3866 return false;
3867 }
3868 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3869 {
3870 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3871 return false;
3872 }
3873 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003874 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003875 }
3876 return true;
3877}
3878
Caroline Ticeaf556562011-02-15 18:42:15 +00003879// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3880// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3881// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003882bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003883EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003884{
3885#if 0
3886 if ConditionPassed() then
3887 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3888 address = R[n];
3889
3890 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003891 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003892 if i == n && wback && i != LowestSetBit(registers) then
3893 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3894 else
3895 MemA[address,4] = R[i];
3896 address = address + 4;
3897
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003898 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003899 MemA[address,4] = PCStoreValue();
3900 if wback then R[n] = R[n] + 4*BitCount(registers);
3901#endif
3902
3903 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003904
Greg Clayton7bc39082011-03-24 23:53:38 +00003905 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003906 {
3907 uint32_t n;
3908 uint32_t registers = 0;
3909 bool wback;
3910 const uint32_t addr_byte_size = GetAddressByteSize();
3911
3912 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3913 switch (encoding)
3914 {
3915 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003916 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003917 n = Bits32 (opcode, 10, 8);
3918 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003919 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003920 wback = true;
3921
3922 // if BitCount(registers) < 1 then UNPREDICTABLE;
3923 if (BitCount (registers) < 1)
3924 return false;
3925
3926 break;
3927
3928 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003929 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003930 n = Bits32 (opcode, 19, 16);
3931 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003932 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003933 wback = BitIsSet (opcode, 21);
3934
3935 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3936 if ((n == 15) || (BitCount (registers) < 2))
3937 return false;
3938
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003939 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003940 if (wback && BitIsSet (registers, n))
3941 return false;
3942
3943 break;
3944
3945 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003946 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003947 n = Bits32 (opcode, 19, 16);
3948 registers = Bits32 (opcode, 15, 0);
3949 wback = BitIsSet (opcode, 21);
3950
3951 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3952 if ((n == 15) || (BitCount (registers) < 1))
3953 return false;
3954
3955 break;
3956
3957 default:
3958 return false;
3959 }
3960
3961 // address = R[n];
3962 int32_t offset = 0;
3963 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3964 if (!success)
3965 return false;
3966
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003967 EmulateInstruction::Context context;
3968 context.type = EmulateInstruction::eContextRegisterStore;
3969 Register base_reg;
3970 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003971
3972 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003973 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003974 for (int i = 0; i < 14; ++i)
3975 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003976 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003977 if (BitIsSet (registers, i))
3978 {
3979 if (i < lowest_set_bit)
3980 lowest_set_bit = i;
3981 // if i == n && wback && i != LowestSetBit(registers) then
3982 if ((i == n) && wback && (i != lowest_set_bit))
3983 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3984 WriteBits32UnknownToMemory (address + offset);
3985 else
3986 {
3987 // MemA[address,4] = R[i];
3988 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3989 if (!success)
3990 return false;
3991
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003992 Register data_reg;
3993 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3994 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003995 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003996 return false;
3997 }
3998
3999 // address = address + 4;
4000 offset += addr_byte_size;
4001 }
4002 }
4003
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004004 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004005 // MemA[address,4] = PCStoreValue();
4006 if (BitIsSet (registers, 15))
4007 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004008 Register pc_reg;
4009 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4010 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004011 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004012 if (!success)
4013 return false;
4014
Caroline Tice8d681f52011-03-17 23:50:16 +00004015 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004016 return false;
4017 }
4018
4019 // if wback then R[n] = R[n] + 4*BitCount(registers);
4020 if (wback)
4021 {
4022 offset = addr_byte_size * BitCount (registers);
4023 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004024 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004025 addr_t data = address + offset;
4026 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4027 return false;
4028 }
4029 }
4030 return true;
4031}
4032
Caroline Ticeaf556562011-02-15 18:42:15 +00004033// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4034// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4035// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004036bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004037EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004038{
4039#if 0
4040 if ConditionPassed() then
4041 EncodingSpecificOperations();
4042 address = R[n] - 4*BitCount(registers) + 4;
4043
4044 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004045 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004046 if i == n && wback && i != LowestSetBit(registers) then
4047 MemA[address,4] = bits(32) UNKNOWN;
4048 else
4049 MemA[address,4] = R[i];
4050 address = address + 4;
4051
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004052 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004053 MemA[address,4] = PCStoreValue();
4054
4055 if wback then R[n] = R[n] - 4*BitCount(registers);
4056#endif
4057
4058 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004059
Greg Clayton7bc39082011-03-24 23:53:38 +00004060 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004061 {
4062 uint32_t n;
4063 uint32_t registers = 0;
4064 bool wback;
4065 const uint32_t addr_byte_size = GetAddressByteSize();
4066
4067 // EncodingSpecificOperations();
4068 switch (encoding)
4069 {
4070 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004071 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004072 n = Bits32 (opcode, 19, 16);
4073 registers = Bits32 (opcode, 15, 0);
4074 wback = BitIsSet (opcode, 21);
4075
4076 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4077 if ((n == 15) || (BitCount (registers) < 1))
4078 return false;
4079 break;
4080 default:
4081 return false;
4082 }
4083
4084 // address = R[n] - 4*BitCount(registers) + 4;
4085 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004086 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004087 if (!success)
4088 return false;
4089
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004090 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004091
4092 EmulateInstruction::Context context;
4093 context.type = EmulateInstruction::eContextRegisterStore;
4094 Register base_reg;
4095 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4096
4097 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004098 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004099 for (int i = 0; i < 14; ++i)
4100 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004101 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004102 if (BitIsSet (registers, i))
4103 {
4104 if (i < lowest_bit_set)
4105 lowest_bit_set = i;
4106 //if i == n && wback && i != LowestSetBit(registers) then
4107 if ((i == n) && wback && (i != lowest_bit_set))
4108 // MemA[address,4] = bits(32) UNKNOWN;
4109 WriteBits32UnknownToMemory (address + offset);
4110 else
4111 {
4112 // MemA[address,4] = R[i];
4113 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4114 if (!success)
4115 return false;
4116
4117 Register data_reg;
4118 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004119 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004120 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004121 return false;
4122 }
4123
4124 // address = address + 4;
4125 offset += addr_byte_size;
4126 }
4127 }
4128
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004129 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004130 // MemA[address,4] = PCStoreValue();
4131 if (BitIsSet (registers, 15))
4132 {
4133 Register pc_reg;
4134 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4135 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004136 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004137 if (!success)
4138 return false;
4139
Caroline Tice8d681f52011-03-17 23:50:16 +00004140 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004141 return false;
4142 }
4143
4144 // if wback then R[n] = R[n] - 4*BitCount(registers);
4145 if (wback)
4146 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004147 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004148 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4149 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004150 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004151 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4152 return false;
4153 }
4154 }
4155 return true;
4156}
4157
Caroline Ticeaf556562011-02-15 18:42:15 +00004158// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4159// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4160// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004161bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004162EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004163{
4164#if 0
4165 if ConditionPassed() then
4166 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4167 address = R[n] - 4*BitCount(registers);
4168
4169 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004170 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004171 if i == n && wback && i != LowestSetBit(registers) then
4172 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4173 else
4174 MemA[address,4] = R[i];
4175 address = address + 4;
4176
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004177 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004178 MemA[address,4] = PCStoreValue();
4179
4180 if wback then R[n] = R[n] - 4*BitCount(registers);
4181#endif
4182
4183
4184 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004185
Greg Clayton7bc39082011-03-24 23:53:38 +00004186 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004187 {
4188 uint32_t n;
4189 uint32_t registers = 0;
4190 bool wback;
4191 const uint32_t addr_byte_size = GetAddressByteSize();
4192
4193 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4194 switch (encoding)
4195 {
4196 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004197 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004198 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4199 {
4200 // See PUSH
4201 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004202 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004203 n = Bits32 (opcode, 19, 16);
4204 registers = Bits32 (opcode, 15, 0);
4205 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4206 wback = BitIsSet (opcode, 21);
4207 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4208 if ((n == 15) || BitCount (registers) < 2)
4209 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004210 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004211 if (wback && BitIsSet (registers, n))
4212 return false;
4213 break;
4214
4215 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004216 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004217 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4218 {
4219 // See Push
4220 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004221 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004222 n = Bits32 (opcode, 19, 16);
4223 registers = Bits32 (opcode, 15, 0);
4224 wback = BitIsSet (opcode, 21);
4225 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4226 if ((n == 15) || BitCount (registers) < 1)
4227 return false;
4228 break;
4229
4230 default:
4231 return false;
4232 }
4233
4234 // address = R[n] - 4*BitCount(registers);
4235
4236 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004237 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004238 if (!success)
4239 return false;
4240
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004241 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004242
4243 EmulateInstruction::Context context;
4244 context.type = EmulateInstruction::eContextRegisterStore;
4245 Register base_reg;
4246 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4247
4248 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004249 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004250 for (int i = 0; i < 14; ++i)
4251 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004252 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004253 if (BitIsSet (registers, i))
4254 {
4255 if (i < lowest_set_bit)
4256 lowest_set_bit = i;
4257 // if i == n && wback && i != LowestSetBit(registers) then
4258 if ((i == n) && wback && (i != lowest_set_bit))
4259 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4260 WriteBits32UnknownToMemory (address + offset);
4261 else
4262 {
4263 // MemA[address,4] = R[i];
4264 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4265 if (!success)
4266 return false;
4267
4268 Register data_reg;
4269 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004270 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004271 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004272 return false;
4273 }
4274
4275 // address = address + 4;
4276 offset += addr_byte_size;
4277 }
4278 }
4279
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004280 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004281 // MemA[address,4] = PCStoreValue();
4282 if (BitIsSet (registers, 15))
4283 {
4284 Register pc_reg;
4285 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4286 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004287 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004288 if (!success)
4289 return false;
4290
Caroline Tice8d681f52011-03-17 23:50:16 +00004291 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004292 return false;
4293 }
4294
4295 // if wback then R[n] = R[n] - 4*BitCount(registers);
4296 if (wback)
4297 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004298 offset = (addr_byte_size * BitCount (registers)) * -1;
4299 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4300 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004301 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004302 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4303 return false;
4304 }
4305 }
4306 return true;
4307}
4308
4309// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4310// from a base register. The consecutive memory locations start just above this address, and the address of the last
4311// of those locations can optionally be written back to the base register.
4312bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004313EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004314{
4315#if 0
4316 if ConditionPassed() then
4317 EncodingSpecificOperations();
4318 address = R[n] + 4;
4319
4320 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004321 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004322 if i == n && wback && i != LowestSetBit(registers) then
4323 MemA[address,4] = bits(32) UNKNOWN;
4324 else
4325 MemA[address,4] = R[i];
4326 address = address + 4;
4327
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004328 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004329 MemA[address,4] = PCStoreValue();
4330
4331 if wback then R[n] = R[n] + 4*BitCount(registers);
4332#endif
4333
4334 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004335
Greg Clayton7bc39082011-03-24 23:53:38 +00004336 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004337 {
4338 uint32_t n;
4339 uint32_t registers = 0;
4340 bool wback;
4341 const uint32_t addr_byte_size = GetAddressByteSize();
4342
4343 // EncodingSpecificOperations();
4344 switch (encoding)
4345 {
4346 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004347 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004348 n = Bits32 (opcode, 19, 16);
4349 registers = Bits32 (opcode, 15, 0);
4350 wback = BitIsSet (opcode, 21);
4351
4352 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4353 if ((n == 15) && (BitCount (registers) < 1))
4354 return false;
4355 break;
4356 default:
4357 return false;
4358 }
4359 // address = R[n] + 4;
4360
4361 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004362 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004363 if (!success)
4364 return false;
4365
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004366 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004367
4368 EmulateInstruction::Context context;
4369 context.type = EmulateInstruction::eContextRegisterStore;
4370 Register base_reg;
4371 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4372
4373 uint32_t lowest_set_bit = 14;
4374 // for i = 0 to 14
4375 for (int i = 0; i < 14; ++i)
4376 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004377 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004378 if (BitIsSet (registers, i))
4379 {
4380 if (i < lowest_set_bit)
4381 lowest_set_bit = i;
4382 // if i == n && wback && i != LowestSetBit(registers) then
4383 if ((i == n) && wback && (i != lowest_set_bit))
4384 // MemA[address,4] = bits(32) UNKNOWN;
4385 WriteBits32UnknownToMemory (address + offset);
4386 // else
4387 else
4388 {
4389 // MemA[address,4] = R[i];
4390 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4391 if (!success)
4392 return false;
4393
4394 Register data_reg;
4395 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004396 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004397 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004398 return false;
4399 }
4400
4401 // address = address + 4;
4402 offset += addr_byte_size;
4403 }
4404 }
4405
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004406 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004407 // MemA[address,4] = PCStoreValue();
4408 if (BitIsSet (registers, 15))
4409 {
4410 Register pc_reg;
4411 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4412 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004413 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004414 if (!success)
4415 return false;
4416
Caroline Tice8d681f52011-03-17 23:50:16 +00004417 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004418 return false;
4419 }
4420
4421 // if wback then R[n] = R[n] + 4*BitCount(registers);
4422 if (wback)
4423 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004424 offset = addr_byte_size * BitCount (registers);
4425 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4426 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004427 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004428 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4429 return false;
4430 }
4431 }
4432 return true;
4433}
Caroline Tice7fac8572011-02-15 22:53:54 +00004434
4435// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4436// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4437bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004438EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004439{
4440#if 0
4441 if ConditionPassed() then
4442 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4443 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4444 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004445 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004446 MemU[address,4] = R[t];
4447 else // Can only occur before ARMv7
4448 MemU[address,4] = bits(32) UNKNOWN;
4449 if wback then R[n] = offset_addr;
4450#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004451
Caroline Tice7fac8572011-02-15 22:53:54 +00004452 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004453
Greg Clayton7bc39082011-03-24 23:53:38 +00004454 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004455 {
4456 const uint32_t addr_byte_size = GetAddressByteSize();
4457
4458 uint32_t t;
4459 uint32_t n;
4460 uint32_t imm32;
4461 bool index;
4462 bool add;
4463 bool wback;
4464 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4465 switch (encoding)
4466 {
4467 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004468 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004469 t = Bits32 (opcode, 2, 0);
4470 n = Bits32 (opcode, 5, 3);
4471 imm32 = Bits32 (opcode, 10, 6) << 2;
4472
4473 // index = TRUE; add = TRUE; wback = FALSE;
4474 index = true;
4475 add = false;
4476 wback = false;
4477 break;
4478
4479 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004480 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004481 t = Bits32 (opcode, 10, 8);
4482 n = 13;
4483 imm32 = Bits32 (opcode, 7, 0) << 2;
4484
4485 // index = TRUE; add = TRUE; wback = FALSE;
4486 index = true;
4487 add = true;
4488 wback = false;
4489 break;
4490
4491 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004492 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004493 if (Bits32 (opcode, 19, 16) == 15)
4494 return false;
4495
4496 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4497 t = Bits32 (opcode, 15, 12);
4498 n = Bits32 (opcode, 19, 16);
4499 imm32 = Bits32 (opcode, 11, 0);
4500
4501 // index = TRUE; add = TRUE; wback = FALSE;
4502 index = true;
4503 add = true;
4504 wback = false;
4505
4506 // if t == 15 then UNPREDICTABLE;
4507 if (t == 15)
4508 return false;
4509 break;
4510
4511 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004512 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4513 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4514 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004515 if ((Bits32 (opcode, 19, 16) == 15)
4516 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4517 return false;
4518
4519 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4520 t = Bits32 (opcode, 15, 12);
4521 n = Bits32 (opcode, 19, 16);
4522 imm32 = Bits32 (opcode, 7, 0);
4523
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004524 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004525 index = BitIsSet (opcode, 10);
4526 add = BitIsSet (opcode, 9);
4527 wback = BitIsSet (opcode, 8);
4528
4529 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4530 if ((t == 15) || (wback && (n == t)))
4531 return false;
4532 break;
4533
4534 default:
4535 return false;
4536 }
4537
4538 addr_t offset_addr;
4539 addr_t address;
4540
4541 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004542 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004543 if (!success)
4544 return false;
4545
4546 if (add)
4547 offset_addr = base_address + imm32;
4548 else
4549 offset_addr = base_address - imm32;
4550
4551 // address = if index then offset_addr else R[n];
4552 if (index)
4553 address = offset_addr;
4554 else
4555 address = base_address;
4556
4557 EmulateInstruction::Context context;
4558 context.type = eContextRegisterStore;
4559 Register base_reg;
4560 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4561
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004562 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004563 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4564 {
4565 // MemU[address,4] = R[t];
4566 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4567 if (!success)
4568 return false;
4569
4570 Register data_reg;
4571 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4572 int32_t offset = address - base_address;
4573 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004574 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004575 return false;
4576 }
4577 else
4578 {
4579 // MemU[address,4] = bits(32) UNKNOWN;
4580 WriteBits32UnknownToMemory (address);
4581 }
4582
4583 // if wback then R[n] = offset_addr;
4584 if (wback)
4585 {
4586 context.type = eContextRegisterLoad;
4587 context.SetAddress (offset_addr);
4588 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4589 return false;
4590 }
4591 }
4592 return true;
4593}
Caroline Ticeaf556562011-02-15 18:42:15 +00004594
Caroline Tice3fd63e92011-02-16 00:33:43 +00004595// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4596// word from a register to memory. The offset register value can optionally be shifted.
4597bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004598EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004599{
4600#if 0
4601 if ConditionPassed() then
4602 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4603 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4604 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4605 address = if index then offset_addr else R[n];
4606 if t == 15 then // Only possible for encoding A1
4607 data = PCStoreValue();
4608 else
4609 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004610 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004611 MemU[address,4] = data;
4612 else // Can only occur before ARMv7
4613 MemU[address,4] = bits(32) UNKNOWN;
4614 if wback then R[n] = offset_addr;
4615#endif
4616
4617 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004618
Greg Clayton7bc39082011-03-24 23:53:38 +00004619 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004620 {
4621 const uint32_t addr_byte_size = GetAddressByteSize();
4622
4623 uint32_t t;
4624 uint32_t n;
4625 uint32_t m;
4626 ARM_ShifterType shift_t;
4627 uint32_t shift_n;
4628 bool index;
4629 bool add;
4630 bool wback;
4631
4632 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4633 switch (encoding)
4634 {
4635 case eEncodingT1:
4636 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4637 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4638 t = Bits32 (opcode, 2, 0);
4639 n = Bits32 (opcode, 5, 3);
4640 m = Bits32 (opcode, 8, 6);
4641
4642 // index = TRUE; add = TRUE; wback = FALSE;
4643 index = true;
4644 add = true;
4645 wback = false;
4646
4647 // (shift_t, shift_n) = (SRType_LSL, 0);
4648 shift_t = SRType_LSL;
4649 shift_n = 0;
4650 break;
4651
4652 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004653 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004654 if (Bits32 (opcode, 19, 16) == 15)
4655 return false;
4656
4657 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4658 t = Bits32 (opcode, 15, 12);
4659 n = Bits32 (opcode, 19, 16);
4660 m = Bits32 (opcode, 3, 0);
4661
4662 // index = TRUE; add = TRUE; wback = FALSE;
4663 index = true;
4664 add = true;
4665 wback = false;
4666
4667 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4668 shift_t = SRType_LSL;
4669 shift_n = Bits32 (opcode, 5, 4);
4670
4671 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4672 if ((t == 15) || (BadReg (m)))
4673 return false;
4674 break;
4675
4676 case eEncodingA1:
4677 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004678 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004679 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4680 t = Bits32 (opcode, 15, 12);
4681 n = Bits32 (opcode, 19, 16);
4682 m = Bits32 (opcode, 3, 0);
4683
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004684 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004685 index = BitIsSet (opcode, 24);
4686 add = BitIsSet (opcode, 23);
4687 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4688
4689 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4690 uint32_t typ = Bits32 (opcode, 6, 5);
4691 uint32_t imm5 = Bits32 (opcode, 11, 7);
4692 shift_n = DecodeImmShift(typ, imm5, shift_t);
4693
4694 // if m == 15 then UNPREDICTABLE;
4695 if (m == 15)
4696 return false;
4697
4698 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4699 if (wback && ((n == 15) || (n == t)))
4700 return false;
4701
4702 break;
4703 }
4704 default:
4705 return false;
4706 }
4707
4708 addr_t offset_addr;
4709 addr_t address;
4710 int32_t offset = 0;
4711
4712 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4713 if (!success)
4714 return false;
4715
4716 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4717 if (!success)
4718 return false;
4719
4720 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004721 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004722
4723 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4724 if (add)
4725 offset_addr = base_address + offset;
4726 else
4727 offset_addr = base_address - offset;
4728
4729 // address = if index then offset_addr else R[n];
4730 if (index)
4731 address = offset_addr;
4732 else
4733 address = base_address;
4734
4735 uint32_t data;
4736 // if t == 15 then // Only possible for encoding A1
4737 if (t == 15)
4738 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004739 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004740 else
4741 // data = R[t];
4742 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4743
4744 if (!success)
4745 return false;
4746
4747 EmulateInstruction::Context context;
4748 context.type = eContextRegisterStore;
4749
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004750 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004751 if (UnalignedSupport ()
4752 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4753 || CurrentInstrSet() == eModeARM)
4754 {
4755 // MemU[address,4] = data;
4756
4757 Register base_reg;
4758 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4759
4760 Register data_reg;
4761 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4762
4763 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004764 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004765 return false;
4766
4767 }
4768 else
4769 // MemU[address,4] = bits(32) UNKNOWN;
4770 WriteBits32UnknownToMemory (address);
4771
4772 // if wback then R[n] = offset_addr;
4773 if (wback)
4774 {
4775 context.type = eContextRegisterLoad;
4776 context.SetAddress (offset_addr);
4777 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4778 return false;
4779 }
4780
4781 }
4782 return true;
4783}
Caroline Tice73a29de2011-02-16 20:22:22 +00004784
4785bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004786EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004787{
4788#if 0
4789 if ConditionPassed() then
4790 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4791 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4792 address = if index then offset_addr else R[n];
4793 MemU[address,1] = R[t]<7:0>;
4794 if wback then R[n] = offset_addr;
4795#endif
4796
4797
4798 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004799
Greg Clayton7bc39082011-03-24 23:53:38 +00004800 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004801 {
4802 uint32_t t;
4803 uint32_t n;
4804 uint32_t imm32;
4805 bool index;
4806 bool add;
4807 bool wback;
4808 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4809 switch (encoding)
4810 {
4811 case eEncodingT1:
4812 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4813 t = Bits32 (opcode, 2, 0);
4814 n = Bits32 (opcode, 5, 3);
4815 imm32 = Bits32 (opcode, 10, 6);
4816
4817 // index = TRUE; add = TRUE; wback = FALSE;
4818 index = true;
4819 add = true;
4820 wback = false;
4821 break;
4822
4823 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004824 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004825 if (Bits32 (opcode, 19, 16) == 15)
4826 return false;
4827
4828 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4829 t = Bits32 (opcode, 15, 12);
4830 n = Bits32 (opcode, 19, 16);
4831 imm32 = Bits32 (opcode, 11, 0);
4832
4833 // index = TRUE; add = TRUE; wback = FALSE;
4834 index = true;
4835 add = true;
4836 wback = false;
4837
4838 // if BadReg(t) then UNPREDICTABLE;
4839 if (BadReg (t))
4840 return false;
4841 break;
4842
4843 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004844 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4845 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004846 if (Bits32 (opcode, 19, 16) == 15)
4847 return false;
4848
4849 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4850 t = Bits32 (opcode, 15, 12);
4851 n = Bits32 (opcode, 19, 16);
4852 imm32 = Bits32 (opcode, 7, 0);
4853
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004854 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004855 index = BitIsSet (opcode, 10);
4856 add = BitIsSet (opcode, 9);
4857 wback = BitIsSet (opcode, 8);
4858
4859 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4860 if ((BadReg (t)) || (wback && (n == t)))
4861 return false;
4862 break;
4863
4864 default:
4865 return false;
4866 }
4867
4868 addr_t offset_addr;
4869 addr_t address;
4870 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4871 if (!success)
4872 return false;
4873
4874 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4875 if (add)
4876 offset_addr = base_address + imm32;
4877 else
4878 offset_addr = base_address - imm32;
4879
4880 // address = if index then offset_addr else R[n];
4881 if (index)
4882 address = offset_addr;
4883 else
4884 address = base_address;
4885
Caroline Ticecc96eb52011-02-17 19:20:40 +00004886 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004887 Register base_reg;
4888 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4889
4890 Register data_reg;
4891 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4892
4893 EmulateInstruction::Context context;
4894 context.type = eContextRegisterStore;
4895 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4896
4897 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4898 if (!success)
4899 return false;
4900
4901 data = Bits32 (data, 7, 0);
4902
Caroline Ticecc96eb52011-02-17 19:20:40 +00004903 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004904 return false;
4905
4906 // if wback then R[n] = offset_addr;
4907 if (wback)
4908 {
4909 context.type = eContextRegisterLoad;
4910 context.SetAddress (offset_addr);
4911 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4912 return false;
4913 }
4914
4915 }
4916
4917 return true;
4918}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004919
4920// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4921// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4922bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004923EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004924{
4925#if 0
4926 if ConditionPassed() then
4927 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4928 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4929 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4930 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004931 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004932 MemU[address,2] = R[t]<15:0>;
4933 else // Can only occur before ARMv7
4934 MemU[address,2] = bits(16) UNKNOWN;
4935 if wback then R[n] = offset_addr;
4936#endif
4937
4938 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004939
Greg Clayton7bc39082011-03-24 23:53:38 +00004940 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004941 {
4942 uint32_t t;
4943 uint32_t n;
4944 uint32_t m;
4945 bool index;
4946 bool add;
4947 bool wback;
4948 ARM_ShifterType shift_t;
4949 uint32_t shift_n;
4950
4951 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4952 switch (encoding)
4953 {
4954 case eEncodingT1:
4955 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4956 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4957 t = Bits32 (opcode, 2, 0);
4958 n = Bits32 (opcode, 5, 3);
4959 m = Bits32 (opcode, 8, 6);
4960
4961 // index = TRUE; add = TRUE; wback = FALSE;
4962 index = true;
4963 add = true;
4964 wback = false;
4965
4966 // (shift_t, shift_n) = (SRType_LSL, 0);
4967 shift_t = SRType_LSL;
4968 shift_n = 0;
4969
4970 break;
4971
4972 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004973 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004974 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4975 t = Bits32 (opcode, 15, 12);
4976 n = Bits32 (opcode, 19, 16);
4977 m = Bits32 (opcode, 3, 0);
4978 if (n == 15)
4979 return false;
4980
4981 // index = TRUE; add = TRUE; wback = FALSE;
4982 index = true;
4983 add = true;
4984 wback = false;
4985
4986 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4987 shift_t = SRType_LSL;
4988 shift_n = Bits32 (opcode, 5, 4);
4989
4990 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4991 if (BadReg (t) || BadReg (m))
4992 return false;
4993
4994 break;
4995
4996 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004997 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004998 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4999 t = Bits32 (opcode, 15, 12);
5000 n = Bits32 (opcode, 19, 16);
5001 m = Bits32 (opcode, 3, 0);
5002
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005003 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005004 index = BitIsSet (opcode, 24);
5005 add = BitIsSet (opcode, 23);
5006 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5007
5008 // (shift_t, shift_n) = (SRType_LSL, 0);
5009 shift_t = SRType_LSL;
5010 shift_n = 0;
5011
5012 // if t == 15 || m == 15 then UNPREDICTABLE;
5013 if ((t == 15) || (m == 15))
5014 return false;
5015
5016 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5017 if (wback && ((n == 15) || (n == t)))
5018 return false;
5019
5020 break;
5021
5022 default:
5023 return false;
5024 }
5025
5026 uint32_t Rm = ReadCoreReg (m, &success);
5027 if (!success)
5028 return false;
5029
5030 uint32_t Rn = ReadCoreReg (n, &success);
5031 if (!success)
5032 return false;
5033
5034 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5035 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5036
5037 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5038 addr_t offset_addr;
5039 if (add)
5040 offset_addr = Rn + offset;
5041 else
5042 offset_addr = Rn - offset;
5043
5044 // address = if index then offset_addr else R[n];
5045 addr_t address;
5046 if (index)
5047 address = offset_addr;
5048 else
5049 address = Rn;
5050
5051 EmulateInstruction::Context context;
5052 context.type = eContextRegisterStore;
5053 Register base_reg;
5054 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5055 Register offset_reg;
5056 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5057
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005058 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005059 if (UnalignedSupport() || BitIsClear (address, 0))
5060 {
5061 // MemU[address,2] = R[t]<15:0>;
5062 uint32_t Rt = ReadCoreReg (t, &success);
5063 if (!success)
5064 return false;
5065
5066 EmulateInstruction::Context context;
5067 context.type = eContextRegisterStore;
5068 Register base_reg;
5069 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5070 Register offset_reg;
5071 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5072 Register data_reg;
5073 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5074 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5075
5076 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5077 return false;
5078 }
5079 else // Can only occur before ARMv7
5080 {
5081 // MemU[address,2] = bits(16) UNKNOWN;
5082 }
5083
5084 // if wback then R[n] = offset_addr;
5085 if (wback)
5086 {
5087 context.type = eContextAdjustBaseRegister;
5088 context.SetAddress (offset_addr);
5089 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5090 return false;
5091 }
5092 }
5093
5094 return true;
5095}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005096
Johnny Chen157b9592011-02-18 21:13:05 +00005097// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5098// and writes the result to the destination register. It can optionally update the condition flags
5099// based on the result.
5100bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005101EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005102{
5103#if 0
5104 // ARM pseudo code...
5105 if ConditionPassed() then
5106 EncodingSpecificOperations();
5107 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5108 if d == 15 then // Can only occur for ARM encoding
5109 ALUWritePC(result); // setflags is always FALSE here
5110 else
5111 R[d] = result;
5112 if setflags then
5113 APSR.N = result<31>;
5114 APSR.Z = IsZeroBit(result);
5115 APSR.C = carry;
5116 APSR.V = overflow;
5117#endif
5118
5119 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005120
Greg Clayton7bc39082011-03-24 23:53:38 +00005121 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005122 {
5123 uint32_t Rd, Rn;
5124 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5125 bool setflags;
5126 switch (encoding)
5127 {
5128 case eEncodingT1:
5129 Rd = Bits32(opcode, 11, 8);
5130 Rn = Bits32(opcode, 19, 16);
5131 setflags = BitIsSet(opcode, 20);
5132 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5133 if (BadReg(Rd) || BadReg(Rn))
5134 return false;
5135 break;
5136 case eEncodingA1:
5137 Rd = Bits32(opcode, 15, 12);
5138 Rn = Bits32(opcode, 19, 16);
5139 setflags = BitIsSet(opcode, 20);
5140 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005141
Johnny Chen157b9592011-02-18 21:13:05 +00005142 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005143 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005144 break;
5145 default:
5146 return false;
5147 }
5148
5149 // Read the first operand.
5150 int32_t val1 = ReadCoreReg(Rn, &success);
5151 if (!success)
5152 return false;
5153
5154 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5155
5156 EmulateInstruction::Context context;
5157 context.type = EmulateInstruction::eContextImmediate;
5158 context.SetNoArgs ();
5159
5160 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5161 return false;
5162 }
5163 return true;
5164}
5165
5166// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5167// register value, and writes the result to the destination register. It can optionally update the
5168// condition flags based on the result.
5169bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005170EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005171{
5172#if 0
5173 // ARM pseudo code...
5174 if ConditionPassed() then
5175 EncodingSpecificOperations();
5176 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5177 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5178 if d == 15 then // Can only occur for ARM encoding
5179 ALUWritePC(result); // setflags is always FALSE here
5180 else
5181 R[d] = result;
5182 if setflags then
5183 APSR.N = result<31>;
5184 APSR.Z = IsZeroBit(result);
5185 APSR.C = carry;
5186 APSR.V = overflow;
5187#endif
5188
5189 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005190
Greg Clayton7bc39082011-03-24 23:53:38 +00005191 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005192 {
5193 uint32_t Rd, Rn, Rm;
5194 ARM_ShifterType shift_t;
5195 uint32_t shift_n; // the shift applied to the value read from Rm
5196 bool setflags;
5197 switch (encoding)
5198 {
5199 case eEncodingT1:
5200 Rd = Rn = Bits32(opcode, 2, 0);
5201 Rm = Bits32(opcode, 5, 3);
5202 setflags = !InITBlock();
5203 shift_t = SRType_LSL;
5204 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005205 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005206 case eEncodingT2:
5207 Rd = Bits32(opcode, 11, 8);
5208 Rn = Bits32(opcode, 19, 16);
5209 Rm = Bits32(opcode, 3, 0);
5210 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005211 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005212 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5213 return false;
5214 break;
5215 case eEncodingA1:
5216 Rd = Bits32(opcode, 15, 12);
5217 Rn = Bits32(opcode, 19, 16);
5218 Rm = Bits32(opcode, 3, 0);
5219 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005220 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005221
Johnny Chen157b9592011-02-18 21:13:05 +00005222 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005223 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005224 break;
5225 default:
5226 return false;
5227 }
5228
5229 // Read the first operand.
5230 int32_t val1 = ReadCoreReg(Rn, &success);
5231 if (!success)
5232 return false;
5233
5234 // Read the second operand.
5235 int32_t val2 = ReadCoreReg(Rm, &success);
5236 if (!success)
5237 return false;
5238
5239 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5240 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5241
5242 EmulateInstruction::Context context;
5243 context.type = EmulateInstruction::eContextImmediate;
5244 context.SetNoArgs ();
5245
5246 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5247 return false;
5248 }
5249 return true;
5250}
5251
Johnny Chena695f952011-02-23 21:24:25 +00005252// This instruction adds an immediate value to the PC value to form a PC-relative address,
5253// and writes the result to the destination register.
5254bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005255EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005256{
5257#if 0
5258 // ARM pseudo code...
5259 if ConditionPassed() then
5260 EncodingSpecificOperations();
5261 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5262 if d == 15 then // Can only occur for ARM encodings
5263 ALUWritePC(result);
5264 else
5265 R[d] = result;
5266#endif
5267
5268 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005269
Greg Clayton7bc39082011-03-24 23:53:38 +00005270 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005271 {
5272 uint32_t Rd;
5273 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5274 bool add;
5275 switch (encoding)
5276 {
5277 case eEncodingT1:
5278 Rd = Bits32(opcode, 10, 8);
5279 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5280 break;
5281 case eEncodingT2:
5282 case eEncodingT3:
5283 Rd = Bits32(opcode, 11, 8);
5284 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5285 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5286 if (BadReg(Rd))
5287 return false;
5288 break;
5289 case eEncodingA1:
5290 case eEncodingA2:
5291 Rd = Bits32(opcode, 15, 12);
5292 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5293 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5294 break;
5295 default:
5296 return false;
5297 }
5298
5299 // Read the PC value.
5300 uint32_t pc = ReadCoreReg(PC_REG, &success);
5301 if (!success)
5302 return false;
5303
5304 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5305
5306 EmulateInstruction::Context context;
5307 context.type = EmulateInstruction::eContextImmediate;
5308 context.SetNoArgs ();
5309
5310 if (!WriteCoreReg(context, result, Rd))
5311 return false;
5312 }
5313 return true;
5314}
5315
Johnny Chene97c0d52011-02-18 19:32:20 +00005316// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5317// to the destination register. It can optionally update the condition flags based on the result.
5318bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005319EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005320{
5321#if 0
5322 // ARM pseudo code...
5323 if ConditionPassed() then
5324 EncodingSpecificOperations();
5325 result = R[n] AND imm32;
5326 if d == 15 then // Can only occur for ARM encoding
5327 ALUWritePC(result); // setflags is always FALSE here
5328 else
5329 R[d] = result;
5330 if setflags then
5331 APSR.N = result<31>;
5332 APSR.Z = IsZeroBit(result);
5333 APSR.C = carry;
5334 // APSR.V unchanged
5335#endif
5336
5337 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005338
Greg Clayton7bc39082011-03-24 23:53:38 +00005339 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005340 {
5341 uint32_t Rd, Rn;
5342 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5343 bool setflags;
5344 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5345 switch (encoding)
5346 {
5347 case eEncodingT1:
5348 Rd = Bits32(opcode, 11, 8);
5349 Rn = Bits32(opcode, 19, 16);
5350 setflags = BitIsSet(opcode, 20);
5351 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005352 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005353 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005354 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005355 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5356 return false;
5357 break;
5358 case eEncodingA1:
5359 Rd = Bits32(opcode, 15, 12);
5360 Rn = Bits32(opcode, 19, 16);
5361 setflags = BitIsSet(opcode, 20);
5362 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005363
Johnny Chene97c0d52011-02-18 19:32:20 +00005364 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005365 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005366 break;
5367 default:
5368 return false;
5369 }
5370
Johnny Chene97c0d52011-02-18 19:32:20 +00005371 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005372 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005373 if (!success)
5374 return false;
5375
5376 uint32_t result = val1 & imm32;
5377
5378 EmulateInstruction::Context context;
5379 context.type = EmulateInstruction::eContextImmediate;
5380 context.SetNoArgs ();
5381
5382 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5383 return false;
5384 }
5385 return true;
5386}
5387
5388// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5389// and writes the result to the destination register. It can optionally update the condition flags
5390// based on the result.
5391bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005392EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005393{
5394#if 0
5395 // ARM pseudo code...
5396 if ConditionPassed() then
5397 EncodingSpecificOperations();
5398 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5399 result = R[n] AND shifted;
5400 if d == 15 then // Can only occur for ARM encoding
5401 ALUWritePC(result); // setflags is always FALSE here
5402 else
5403 R[d] = result;
5404 if setflags then
5405 APSR.N = result<31>;
5406 APSR.Z = IsZeroBit(result);
5407 APSR.C = carry;
5408 // APSR.V unchanged
5409#endif
5410
5411 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005412
Greg Clayton7bc39082011-03-24 23:53:38 +00005413 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005414 {
5415 uint32_t Rd, Rn, Rm;
5416 ARM_ShifterType shift_t;
5417 uint32_t shift_n; // the shift applied to the value read from Rm
5418 bool setflags;
5419 uint32_t carry;
5420 switch (encoding)
5421 {
5422 case eEncodingT1:
5423 Rd = Rn = Bits32(opcode, 2, 0);
5424 Rm = Bits32(opcode, 5, 3);
5425 setflags = !InITBlock();
5426 shift_t = SRType_LSL;
5427 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005428 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005429 case eEncodingT2:
5430 Rd = Bits32(opcode, 11, 8);
5431 Rn = Bits32(opcode, 19, 16);
5432 Rm = Bits32(opcode, 3, 0);
5433 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005434 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005435 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005436 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005437 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005438 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5439 return false;
5440 break;
5441 case eEncodingA1:
5442 Rd = Bits32(opcode, 15, 12);
5443 Rn = Bits32(opcode, 19, 16);
5444 Rm = Bits32(opcode, 3, 0);
5445 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005446 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005447
Johnny Chene97c0d52011-02-18 19:32:20 +00005448 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005449 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005450 break;
5451 default:
5452 return false;
5453 }
5454
Johnny Chene97c0d52011-02-18 19:32:20 +00005455 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005456 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005457 if (!success)
5458 return false;
5459
5460 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005461 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005462 if (!success)
5463 return false;
5464
5465 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5466 uint32_t result = val1 & shifted;
5467
5468 EmulateInstruction::Context context;
5469 context.type = EmulateInstruction::eContextImmediate;
5470 context.SetNoArgs ();
5471
5472 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5473 return false;
5474 }
5475 return true;
5476}
5477
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005478// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5479// immediate value, and writes the result to the destination register. It can optionally update the
5480// condition flags based on the result.
5481bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005482EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005483{
5484#if 0
5485 // ARM pseudo code...
5486 if ConditionPassed() then
5487 EncodingSpecificOperations();
5488 result = R[n] AND NOT(imm32);
5489 if d == 15 then // Can only occur for ARM encoding
5490 ALUWritePC(result); // setflags is always FALSE here
5491 else
5492 R[d] = result;
5493 if setflags then
5494 APSR.N = result<31>;
5495 APSR.Z = IsZeroBit(result);
5496 APSR.C = carry;
5497 // APSR.V unchanged
5498#endif
5499
5500 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005501
Greg Clayton7bc39082011-03-24 23:53:38 +00005502 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005503 {
5504 uint32_t Rd, Rn;
5505 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5506 bool setflags;
5507 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5508 switch (encoding)
5509 {
5510 case eEncodingT1:
5511 Rd = Bits32(opcode, 11, 8);
5512 Rn = Bits32(opcode, 19, 16);
5513 setflags = BitIsSet(opcode, 20);
5514 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5515 if (BadReg(Rd) || BadReg(Rn))
5516 return false;
5517 break;
5518 case eEncodingA1:
5519 Rd = Bits32(opcode, 15, 12);
5520 Rn = Bits32(opcode, 19, 16);
5521 setflags = BitIsSet(opcode, 20);
5522 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005523
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005524 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005525 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005526 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005527 break;
5528 default:
5529 return false;
5530 }
5531
5532 // Read the first operand.
5533 uint32_t val1 = ReadCoreReg(Rn, &success);
5534 if (!success)
5535 return false;
5536
5537 uint32_t result = val1 & ~imm32;
5538
5539 EmulateInstruction::Context context;
5540 context.type = EmulateInstruction::eContextImmediate;
5541 context.SetNoArgs ();
5542
5543 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5544 return false;
5545 }
5546 return true;
5547}
5548
5549// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5550// optionally-shifted register value, and writes the result to the destination register.
5551// It can optionally update the condition flags based on the result.
5552bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005553EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005554{
5555#if 0
5556 // ARM pseudo code...
5557 if ConditionPassed() then
5558 EncodingSpecificOperations();
5559 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5560 result = R[n] AND NOT(shifted);
5561 if d == 15 then // Can only occur for ARM encoding
5562 ALUWritePC(result); // setflags is always FALSE here
5563 else
5564 R[d] = result;
5565 if setflags then
5566 APSR.N = result<31>;
5567 APSR.Z = IsZeroBit(result);
5568 APSR.C = carry;
5569 // APSR.V unchanged
5570#endif
5571
5572 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005573
Greg Clayton7bc39082011-03-24 23:53:38 +00005574 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005575 {
5576 uint32_t Rd, Rn, Rm;
5577 ARM_ShifterType shift_t;
5578 uint32_t shift_n; // the shift applied to the value read from Rm
5579 bool setflags;
5580 uint32_t carry;
5581 switch (encoding)
5582 {
5583 case eEncodingT1:
5584 Rd = Rn = Bits32(opcode, 2, 0);
5585 Rm = Bits32(opcode, 5, 3);
5586 setflags = !InITBlock();
5587 shift_t = SRType_LSL;
5588 shift_n = 0;
5589 break;
5590 case eEncodingT2:
5591 Rd = Bits32(opcode, 11, 8);
5592 Rn = Bits32(opcode, 19, 16);
5593 Rm = Bits32(opcode, 3, 0);
5594 setflags = BitIsSet(opcode, 20);
5595 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5596 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5597 return false;
5598 break;
5599 case eEncodingA1:
5600 Rd = Bits32(opcode, 15, 12);
5601 Rn = Bits32(opcode, 19, 16);
5602 Rm = Bits32(opcode, 3, 0);
5603 setflags = BitIsSet(opcode, 20);
5604 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005605
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005606 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005607 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005608 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005609 break;
5610 default:
5611 return false;
5612 }
5613
5614 // Read the first operand.
5615 uint32_t val1 = ReadCoreReg(Rn, &success);
5616 if (!success)
5617 return false;
5618
5619 // Read the second operand.
5620 uint32_t val2 = ReadCoreReg(Rm, &success);
5621 if (!success)
5622 return false;
5623
5624 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5625 uint32_t result = val1 & ~shifted;
5626
5627 EmulateInstruction::Context context;
5628 context.type = EmulateInstruction::eContextImmediate;
5629 context.SetNoArgs ();
5630
5631 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5632 return false;
5633 }
5634 return true;
5635}
5636
Caroline Tice4d729c52011-02-18 00:55:53 +00005637// 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 +00005638// 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 +00005639bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005640EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005641{
5642#if 0
5643 if ConditionPassed() then
5644 EncodingSpecificOperations();
5645 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5646 address = if index then offset_addr else R[n];
5647 data = MemU[address,4];
5648 if wback then R[n] = offset_addr;
5649 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005650 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5651 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005652 R[t] = data;
5653 else // Can only apply before ARMv7
5654 R[t] = ROR(data, 8*UInt(address<1:0>));
5655#endif
5656
5657 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005658
Greg Clayton7bc39082011-03-24 23:53:38 +00005659 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005660 {
5661 const uint32_t addr_byte_size = GetAddressByteSize();
5662
5663 uint32_t t;
5664 uint32_t n;
5665 uint32_t imm32;
5666 bool index;
5667 bool add;
5668 bool wback;
5669
5670 switch (encoding)
5671 {
5672 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005673 // if Rn == '1111' then SEE LDR (literal);
5674 // if P == '0' && W == '1' then SEE LDRT;
5675 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005676 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5677 t = Bits32 (opcode, 15, 12);
5678 n = Bits32 (opcode, 19, 16);
5679 imm32 = Bits32 (opcode, 11, 0);
5680
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005681 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5682 index = BitIsSet (opcode, 24);
5683 add = BitIsSet (opcode, 23);
5684 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005685
5686 // if wback && n == t then UNPREDICTABLE;
5687 if (wback && (n == t))
5688 return false;
5689
5690 break;
5691
5692 default:
5693 return false;
5694 }
5695
5696 addr_t address;
5697 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005698 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005699 if (!success)
5700 return false;
5701
5702 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5703 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005704 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005705 else
5706 offset_addr = base_address - imm32;
5707
5708 // address = if index then offset_addr else R[n];
5709 if (index)
5710 address = offset_addr;
5711 else
5712 address = base_address;
5713
5714 // data = MemU[address,4];
5715
5716 Register base_reg;
5717 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5718
5719 EmulateInstruction::Context context;
5720 context.type = eContextRegisterLoad;
5721 context.SetRegisterPlusOffset (base_reg, address - base_address);
5722
5723 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5724 if (!success)
5725 return false;
5726
5727 // if wback then R[n] = offset_addr;
5728 if (wback)
5729 {
5730 context.type = eContextAdjustBaseRegister;
5731 context.SetAddress (offset_addr);
5732 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5733 return false;
5734 }
5735
5736 // if t == 15 then
5737 if (t == 15)
5738 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005739 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005740 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5741 {
5742 // LoadWritePC (data);
5743 context.type = eContextRegisterLoad;
5744 context.SetRegisterPlusOffset (base_reg, address - base_address);
5745 LoadWritePC (context, data);
5746 }
5747 else
5748 return false;
5749 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005750 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005751 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5752 {
5753 // R[t] = data;
5754 context.type = eContextRegisterLoad;
5755 context.SetRegisterPlusOffset (base_reg, address - base_address);
5756 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5757 return false;
5758 }
5759 // else // Can only apply before ARMv7
5760 else
5761 {
5762 // R[t] = ROR(data, 8*UInt(address<1:0>));
5763 data = ROR (data, Bits32 (address, 1, 0));
5764 context.type = eContextRegisterLoad;
5765 context.SetImmediate (data);
5766 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5767 return false;
5768 }
5769
5770 }
5771 return true;
5772}
5773
Caroline Ticefe479112011-02-18 18:52:37 +00005774// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5775// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5776bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005777EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005778{
5779#if 0
5780 if ConditionPassed() then
5781 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5782 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5783 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5784 address = if index then offset_addr else R[n];
5785 data = MemU[address,4];
5786 if wback then R[n] = offset_addr;
5787 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005788 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5789 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005790 R[t] = data;
5791 else // Can only apply before ARMv7
5792 if CurrentInstrSet() == InstrSet_ARM then
5793 R[t] = ROR(data, 8*UInt(address<1:0>));
5794 else
5795 R[t] = bits(32) UNKNOWN;
5796#endif
5797
5798 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005799
Greg Clayton7bc39082011-03-24 23:53:38 +00005800 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005801 {
5802 const uint32_t addr_byte_size = GetAddressByteSize();
5803
5804 uint32_t t;
5805 uint32_t n;
5806 uint32_t m;
5807 bool index;
5808 bool add;
5809 bool wback;
5810 ARM_ShifterType shift_t;
5811 uint32_t shift_n;
5812
5813 switch (encoding)
5814 {
5815 case eEncodingT1:
5816 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5817 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5818 t = Bits32 (opcode, 2, 0);
5819 n = Bits32 (opcode, 5, 3);
5820 m = Bits32 (opcode, 8, 6);
5821
5822 // index = TRUE; add = TRUE; wback = FALSE;
5823 index = true;
5824 add = true;
5825 wback = false;
5826
5827 // (shift_t, shift_n) = (SRType_LSL, 0);
5828 shift_t = SRType_LSL;
5829 shift_n = 0;
5830
5831 break;
5832
5833 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005834 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005835 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5836 t = Bits32 (opcode, 15, 12);
5837 n = Bits32 (opcode, 19, 16);
5838 m = Bits32 (opcode, 3, 0);
5839
5840 // index = TRUE; add = TRUE; wback = FALSE;
5841 index = true;
5842 add = true;
5843 wback = false;
5844
5845 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5846 shift_t = SRType_LSL;
5847 shift_n = Bits32 (opcode, 5, 4);
5848
5849 // if BadReg(m) then UNPREDICTABLE;
5850 if (BadReg (m))
5851 return false;
5852
5853 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5854 if ((t == 15) && InITBlock() && !LastInITBlock())
5855 return false;
5856
5857 break;
5858
5859 case eEncodingA1:
5860 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005861 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005862 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5863 t = Bits32 (opcode, 15, 12);
5864 n = Bits32 (opcode, 19, 16);
5865 m = Bits32 (opcode, 3, 0);
5866
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005867 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005868 index = BitIsSet (opcode, 24);
5869 add = BitIsSet (opcode, 23);
5870 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5871
5872 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5873 uint32_t type = Bits32 (opcode, 6, 5);
5874 uint32_t imm5 = Bits32 (opcode, 11, 7);
5875 shift_n = DecodeImmShift (type, imm5, shift_t);
5876
5877 // if m == 15 then UNPREDICTABLE;
5878 if (m == 15)
5879 return false;
5880
5881 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5882 if (wback && ((n == 15) || (n == t)))
5883 return false;
5884 }
5885 break;
5886
5887
5888 default:
5889 return false;
5890 }
5891
5892 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5893 if (!success)
5894 return false;
5895
5896 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5897 if (!success)
5898 return false;
5899
5900 addr_t offset_addr;
5901 addr_t address;
5902
5903 // 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 +00005904 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005905
5906 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5907 if (add)
5908 offset_addr = Rn + offset;
5909 else
5910 offset_addr = Rn - offset;
5911
5912 // address = if index then offset_addr else R[n];
5913 if (index)
5914 address = offset_addr;
5915 else
5916 address = Rn;
5917
5918 // data = MemU[address,4];
5919 Register base_reg;
5920 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5921
5922 EmulateInstruction::Context context;
5923 context.type = eContextRegisterLoad;
5924 context.SetRegisterPlusOffset (base_reg, address - Rn);
5925
5926 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5927 if (!success)
5928 return false;
5929
5930 // if wback then R[n] = offset_addr;
5931 if (wback)
5932 {
5933 context.type = eContextAdjustBaseRegister;
5934 context.SetAddress (offset_addr);
5935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5936 return false;
5937 }
5938
5939 // if t == 15 then
5940 if (t == 15)
5941 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005942 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005943 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5944 {
5945 context.type = eContextRegisterLoad;
5946 context.SetRegisterPlusOffset (base_reg, address - Rn);
5947 LoadWritePC (context, data);
5948 }
5949 else
5950 return false;
5951 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005952 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005953 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5954 {
5955 // R[t] = data;
5956 context.type = eContextRegisterLoad;
5957 context.SetRegisterPlusOffset (base_reg, address - Rn);
5958 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5959 return false;
5960 }
5961 else // Can only apply before ARMv7
5962 {
5963 // if CurrentInstrSet() == InstrSet_ARM then
5964 if (CurrentInstrSet () == eModeARM)
5965 {
5966 // R[t] = ROR(data, 8*UInt(address<1:0>));
5967 data = ROR (data, Bits32 (address, 1, 0));
5968 context.type = eContextRegisterLoad;
5969 context.SetImmediate (data);
5970 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5971 return false;
5972 }
5973 else
5974 {
5975 // R[t] = bits(32) UNKNOWN;
5976 WriteBits32Unknown (t);
5977 }
5978 }
5979 }
5980 return true;
5981}
Caroline Tice21b604b2011-02-18 21:06:04 +00005982
5983// LDRB (immediate, Thumb)
5984bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005985EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00005986{
5987#if 0
5988 if ConditionPassed() then
5989 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5990 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5991 address = if index then offset_addr else R[n];
5992 R[t] = ZeroExtend(MemU[address,1], 32);
5993 if wback then R[n] = offset_addr;
5994#endif
5995
5996 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00005997
Greg Clayton7bc39082011-03-24 23:53:38 +00005998 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00005999 {
6000 uint32_t t;
6001 uint32_t n;
6002 uint32_t imm32;
6003 bool index;
6004 bool add;
6005 bool wback;
6006
6007 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6008 switch (encoding)
6009 {
6010 case eEncodingT1:
6011 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6012 t = Bits32 (opcode, 2, 0);
6013 n = Bits32 (opcode, 5, 3);
6014 imm32 = Bits32 (opcode, 10, 6);
6015
6016 // index = TRUE; add = TRUE; wback = FALSE;
6017 index = true;
6018 add = true;
6019 wback= false;
6020
6021 break;
6022
6023 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006024 // if Rt == '1111' then SEE PLD;
6025 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006026 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6027 t = Bits32 (opcode, 15, 12);
6028 n = Bits32 (opcode, 19, 16);
6029 imm32 = Bits32 (opcode, 11, 0);
6030
6031 // index = TRUE; add = TRUE; wback = FALSE;
6032 index = true;
6033 add = true;
6034 wback = false;
6035
6036 // if t == 13 then UNPREDICTABLE;
6037 if (t == 13)
6038 return false;
6039
6040 break;
6041
6042 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006043 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6044 // if Rn == '1111' then SEE LDRB (literal);
6045 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6046 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006047 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6048 return false;
6049
6050 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6051 t = Bits32 (opcode, 15, 12);
6052 n = Bits32 (opcode, 19, 16);
6053 imm32 = Bits32 (opcode, 7, 0);
6054
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006055 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006056 index = BitIsSet (opcode, 10);
6057 add = BitIsSet (opcode, 9);
6058 wback = BitIsSet (opcode, 8);
6059
6060 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6061 if (BadReg (t) || (wback && (n == t)))
6062 return false;
6063
6064 break;
6065
6066 default:
6067 return false;
6068 }
6069
6070 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6071 if (!success)
6072 return false;
6073
6074 addr_t address;
6075 addr_t offset_addr;
6076
6077 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6078 if (add)
6079 offset_addr = Rn + imm32;
6080 else
6081 offset_addr = Rn - imm32;
6082
6083 // address = if index then offset_addr else R[n];
6084 if (index)
6085 address = offset_addr;
6086 else
6087 address = Rn;
6088
6089 // R[t] = ZeroExtend(MemU[address,1], 32);
6090 Register base_reg;
6091 Register data_reg;
6092 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6093 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6094
6095 EmulateInstruction::Context context;
6096 context.type = eContextRegisterLoad;
6097 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6098
6099 uint64_t data = MemURead (context, address, 1, 0, &success);
6100 if (!success)
6101 return false;
6102
6103 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6104 return false;
6105
6106 // if wback then R[n] = offset_addr;
6107 if (wback)
6108 {
6109 context.type = eContextAdjustBaseRegister;
6110 context.SetAddress (offset_addr);
6111 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6112 return false;
6113 }
6114 }
6115 return true;
6116}
Caroline Ticef55261f2011-02-18 22:24:22 +00006117
6118// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6119// zero-extends it to form a 32-bit word and writes it to a register.
6120bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006121EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006122{
6123#if 0
6124 if ConditionPassed() then
6125 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6126 base = Align(PC,4);
6127 address = if add then (base + imm32) else (base - imm32);
6128 R[t] = ZeroExtend(MemU[address,1], 32);
6129#endif
6130
6131 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006132
Greg Clayton7bc39082011-03-24 23:53:38 +00006133 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006134 {
6135 uint32_t t;
6136 uint32_t imm32;
6137 bool add;
6138 switch (encoding)
6139 {
6140 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006141 // if Rt == '1111' then SEE PLD;
6142 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006143 t = Bits32 (opcode, 15, 12);
6144 imm32 = Bits32 (opcode, 11, 0);
6145 add = BitIsSet (opcode, 23);
6146
6147 // if t == 13 then UNPREDICTABLE;
6148 if (t == 13)
6149 return false;
6150
6151 break;
6152
6153 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006154 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006155 t = Bits32 (opcode, 15, 12);
6156 imm32 = Bits32 (opcode, 11, 0);
6157 add = BitIsSet (opcode, 23);
6158
6159 // if t == 15 then UNPREDICTABLE;
6160 if (t == 15)
6161 return false;
6162 break;
6163
6164 default:
6165 return false;
6166 }
6167
6168 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006169 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006170 if (!success)
6171 return false;
6172
6173 uint32_t base = AlignPC (pc_val);
6174
6175 addr_t address;
6176 // address = if add then (base + imm32) else (base - imm32);
6177 if (add)
6178 address = base + imm32;
6179 else
6180 address = base - imm32;
6181
6182 // R[t] = ZeroExtend(MemU[address,1], 32);
6183 EmulateInstruction::Context context;
6184 context.type = eContextRelativeBranchImmediate;
6185 context.SetImmediate (address - base);
6186
6187 uint64_t data = MemURead (context, address, 1, 0, &success);
6188 if (!success)
6189 return false;
6190
6191 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6192 return false;
6193 }
6194 return true;
6195}
Caroline Tice30fec122011-02-18 23:52:21 +00006196
6197// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6198// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6199// optionally be shifted.
6200bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006201EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006202{
6203#if 0
6204 if ConditionPassed() then
6205 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6206 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6207 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6208 address = if index then offset_addr else R[n];
6209 R[t] = ZeroExtend(MemU[address,1],32);
6210 if wback then R[n] = offset_addr;
6211#endif
6212
6213 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006214
Greg Clayton7bc39082011-03-24 23:53:38 +00006215 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006216 {
6217 uint32_t t;
6218 uint32_t n;
6219 uint32_t m;
6220 bool index;
6221 bool add;
6222 bool wback;
6223 ARM_ShifterType shift_t;
6224 uint32_t shift_n;
6225
6226 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6227 switch (encoding)
6228 {
6229 case eEncodingT1:
6230 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6231 t = Bits32 (opcode, 2, 0);
6232 n = Bits32 (opcode, 5, 3);
6233 m = Bits32 (opcode, 8, 6);
6234
6235 // index = TRUE; add = TRUE; wback = FALSE;
6236 index = true;
6237 add = true;
6238 wback = false;
6239
6240 // (shift_t, shift_n) = (SRType_LSL, 0);
6241 shift_t = SRType_LSL;
6242 shift_n = 0;
6243 break;
6244
6245 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006246 // if Rt == '1111' then SEE PLD;
6247 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006248 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6249 t = Bits32 (opcode, 15, 12);
6250 n = Bits32 (opcode, 19, 16);
6251 m = Bits32 (opcode, 3, 0);
6252
6253 // index = TRUE; add = TRUE; wback = FALSE;
6254 index = true;
6255 add = true;
6256 wback = false;
6257
6258 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6259 shift_t = SRType_LSL;
6260 shift_n = Bits32 (opcode, 5, 4);
6261
6262 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6263 if ((t == 13) || BadReg (m))
6264 return false;
6265 break;
6266
6267 case eEncodingA1:
6268 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006269 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006270 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6271 t = Bits32 (opcode, 15, 12);
6272 n = Bits32 (opcode, 19, 16);
6273 m = Bits32 (opcode, 3, 0);
6274
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006275 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006276 index = BitIsSet (opcode, 24);
6277 add = BitIsSet (opcode, 23);
6278 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6279
6280 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6281 uint32_t type = Bits32 (opcode, 6, 5);
6282 uint32_t imm5 = Bits32 (opcode, 11, 7);
6283 shift_n = DecodeImmShift (type, imm5, shift_t);
6284
6285 // if t == 15 || m == 15 then UNPREDICTABLE;
6286 if ((t == 15) || (m == 15))
6287 return false;
6288
6289 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6290 if (wback && ((n == 15) || (n == t)))
6291 return false;
6292 }
6293 break;
6294
6295 default:
6296 return false;
6297 }
6298
6299 addr_t offset_addr;
6300 addr_t address;
6301
6302 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6303 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6304 if (!success)
6305 return false;
6306
6307 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6308
6309 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6310 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6311 if (!success)
6312 return false;
6313
6314 if (add)
6315 offset_addr = Rn + offset;
6316 else
6317 offset_addr = Rn - offset;
6318
6319 // address = if index then offset_addr else R[n];
6320 if (index)
6321 address = offset_addr;
6322 else
6323 address = Rn;
6324
6325 // R[t] = ZeroExtend(MemU[address,1],32);
6326 Register base_reg;
6327 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6328
6329 EmulateInstruction::Context context;
6330 context.type = eContextRegisterLoad;
6331 context.SetRegisterPlusOffset (base_reg, address - Rn);
6332
6333 uint64_t data = MemURead (context, address, 1, 0, &success);
6334 if (!success)
6335 return false;
6336
6337 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6338 return false;
6339
6340 // if wback then R[n] = offset_addr;
6341 if (wback)
6342 {
6343 context.type = eContextAdjustBaseRegister;
6344 context.SetAddress (offset_addr);
6345 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6346 return false;
6347 }
6348 }
6349 return true;
6350}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006351
6352// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6353// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6354// post-indexed, or pre-indexed addressing.
6355bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006356EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006357{
6358#if 0
6359 if ConditionPassed() then
6360 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6361 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6362 address = if index then offset_addr else R[n];
6363 data = MemU[address,2];
6364 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006365 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006366 R[t] = ZeroExtend(data, 32);
6367 else // Can only apply before ARMv7
6368 R[t] = bits(32) UNKNOWN;
6369#endif
6370
6371
6372 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006373
Greg Clayton7bc39082011-03-24 23:53:38 +00006374 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006375 {
6376 uint32_t t;
6377 uint32_t n;
6378 uint32_t imm32;
6379 bool index;
6380 bool add;
6381 bool wback;
6382
6383 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6384 switch (encoding)
6385 {
6386 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006387 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006388 t = Bits32 (opcode, 2, 0);
6389 n = Bits32 (opcode, 5, 3);
6390 imm32 = Bits32 (opcode, 10, 6) << 1;
6391
6392 // index = TRUE; add = TRUE; wback = FALSE;
6393 index = true;
6394 add = true;
6395 wback = false;
6396
6397 break;
6398
6399 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006400 // if Rt == '1111' then SEE "Unallocated memory hints";
6401 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006402 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6403 t = Bits32 (opcode, 15, 12);
6404 n = Bits32 (opcode, 19, 16);
6405 imm32 = Bits32 (opcode, 11, 0);
6406
6407 // index = TRUE; add = TRUE; wback = FALSE;
6408 index = true;
6409 add = true;
6410 wback = false;
6411
6412 // if t == 13 then UNPREDICTABLE;
6413 if (t == 13)
6414 return false;
6415 break;
6416
6417 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006418 // if Rn == '1111' then SEE LDRH (literal);
6419 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6420 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6421 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006422 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6423 return false;
6424
6425 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6426 t = Bits32 (opcode, 15, 12);
6427 n = Bits32 (opcode, 19, 16);
6428 imm32 = Bits32 (opcode, 7, 0);
6429
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006430 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006431 index = BitIsSet (opcode, 10);
6432 add = BitIsSet (opcode, 9);
6433 wback = BitIsSet (opcode, 8);
6434
6435 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6436 if (BadReg (t) || (wback && (n == t)))
6437 return false;
6438 break;
6439
6440 default:
6441 return false;
6442 }
6443
6444 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6445 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6446 if (!success)
6447 return false;
6448
6449 addr_t offset_addr;
6450 addr_t address;
6451
6452 if (add)
6453 offset_addr = Rn + imm32;
6454 else
6455 offset_addr = Rn - imm32;
6456
6457 // address = if index then offset_addr else R[n];
6458 if (index)
6459 address = offset_addr;
6460 else
6461 address = Rn;
6462
6463 // data = MemU[address,2];
6464 Register base_reg;
6465 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6466
6467 EmulateInstruction::Context context;
6468 context.type = eContextRegisterLoad;
6469 context.SetRegisterPlusOffset (base_reg, address - Rn);
6470
6471 uint64_t data = MemURead (context, address, 2, 0, &success);
6472 if (!success)
6473 return false;
6474
6475 // if wback then R[n] = offset_addr;
6476 if (wback)
6477 {
6478 context.type = eContextAdjustBaseRegister;
6479 context.SetAddress (offset_addr);
6480 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6481 return false;
6482 }
6483
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006484 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006485 if (UnalignedSupport () || BitIsClear (address, 0))
6486 {
6487 // R[t] = ZeroExtend(data, 32);
6488 context.type = eContextRegisterLoad;
6489 context.SetRegisterPlusOffset (base_reg, address - Rn);
6490 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6491 return false;
6492 }
6493 else // Can only apply before ARMv7
6494 {
6495 // R[t] = bits(32) UNKNOWN;
6496 WriteBits32Unknown (t);
6497 }
6498 }
6499 return true;
6500}
Caroline Ticefe479112011-02-18 18:52:37 +00006501
Caroline Tice952b5382011-02-28 23:15:24 +00006502// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6503// zero-extends it to form a 32-bit word, and writes it to a register.
6504bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006505EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006506{
6507#if 0
6508 if ConditionPassed() then
6509 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6510 base = Align(PC,4);
6511 address = if add then (base + imm32) else (base - imm32);
6512 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006513 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006514 R[t] = ZeroExtend(data, 32);
6515 else // Can only apply before ARMv7
6516 R[t] = bits(32) UNKNOWN;
6517#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006518
Caroline Tice952b5382011-02-28 23:15:24 +00006519 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006520
Greg Clayton7bc39082011-03-24 23:53:38 +00006521 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006522 {
6523 uint32_t t;
6524 uint32_t imm32;
6525 bool add;
6526
6527 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6528 switch (encoding)
6529 {
6530 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006531 // if Rt == '1111' then SEE "Unallocated memory hints";
6532 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006533 t = Bits32 (opcode, 15, 12);
6534 imm32 = Bits32 (opcode, 11, 0);
6535 add = BitIsSet (opcode, 23);
6536
6537 // if t == 13 then UNPREDICTABLE;
6538 if (t == 13)
6539 return false;
6540
6541 break;
6542
6543 case eEncodingA1:
6544 {
6545 uint32_t imm4H = Bits32 (opcode, 11, 8);
6546 uint32_t imm4L = Bits32 (opcode, 3, 0);
6547
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006548 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006549 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006550 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006551 add = BitIsSet (opcode, 23);
6552
6553 // if t == 15 then UNPREDICTABLE;
6554 if (t == 15)
6555 return false;
6556 break;
6557 }
6558
6559 default:
6560 return false;
6561 }
6562
6563 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006564 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006565 if (!success)
6566 return false;
6567
6568 addr_t base = AlignPC (pc_value);
6569 addr_t address;
6570
6571 // address = if add then (base + imm32) else (base - imm32);
6572 if (add)
6573 address = base + imm32;
6574 else
6575 address = base - imm32;
6576
6577 // data = MemU[address,2];
6578 Register base_reg;
6579 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6580
6581 EmulateInstruction::Context context;
6582 context.type = eContextRegisterLoad;
6583 context.SetRegisterPlusOffset (base_reg, address - base);
6584
6585 uint64_t data = MemURead (context, address, 2, 0, &success);
6586 if (!success)
6587 return false;
6588
6589
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006590 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006591 if (UnalignedSupport () || BitIsClear (address, 0))
6592 {
6593 // R[t] = ZeroExtend(data, 32);
6594 context.type = eContextRegisterLoad;
6595 context.SetRegisterPlusOffset (base_reg, address - base);
6596 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6597 return false;
6598
6599 }
6600 else // Can only apply before ARMv7
6601 {
6602 // R[t] = bits(32) UNKNOWN;
6603 WriteBits32Unknown (t);
6604 }
6605 }
6606 return true;
6607}
6608
Caroline Tice0e6bc952011-03-01 18:00:42 +00006609// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6610// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6611// be shifted left by 0, 1, 2, or 3 bits.
6612bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006613EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006614{
6615#if 0
6616 if ConditionPassed() then
6617 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6618 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6619 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6620 address = if index then offset_addr else R[n];
6621 data = MemU[address,2];
6622 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006623 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006624 R[t] = ZeroExtend(data, 32);
6625 else // Can only apply before ARMv7
6626 R[t] = bits(32) UNKNOWN;
6627#endif
6628
6629 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006630
Greg Clayton7bc39082011-03-24 23:53:38 +00006631 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006632 {
6633 uint32_t t;
6634 uint32_t n;
6635 uint32_t m;
6636 bool index;
6637 bool add;
6638 bool wback;
6639 ARM_ShifterType shift_t;
6640 uint32_t shift_n;
6641
6642 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6643 switch (encoding)
6644 {
6645 case eEncodingT1:
6646 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6647 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6648 t = Bits32 (opcode, 2, 0);
6649 n = Bits32 (opcode, 5, 3);
6650 m = Bits32 (opcode, 8, 6);
6651
6652 // index = TRUE; add = TRUE; wback = FALSE;
6653 index = true;
6654 add = true;
6655 wback = false;
6656
6657 // (shift_t, shift_n) = (SRType_LSL, 0);
6658 shift_t = SRType_LSL;
6659 shift_n = 0;
6660
6661 break;
6662
6663 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006664 // if Rn == '1111' then SEE LDRH (literal);
6665 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006666 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6667 t = Bits32 (opcode, 15, 12);
6668 n = Bits32 (opcode, 19, 16);
6669 m = Bits32 (opcode, 3, 0);
6670
6671 // index = TRUE; add = TRUE; wback = FALSE;
6672 index = true;
6673 add = true;
6674 wback = false;
6675
6676 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6677 shift_t = SRType_LSL;
6678 shift_n = Bits32 (opcode, 5, 4);
6679
6680 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6681 if ((t == 13) || BadReg (m))
6682 return false;
6683 break;
6684
6685 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006686 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006687 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6688 t = Bits32 (opcode, 15, 12);
6689 n = Bits32 (opcode, 19, 16);
6690 m = Bits32 (opcode, 3, 0);
6691
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006692 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006693 index = BitIsSet (opcode, 24);
6694 add = BitIsSet (opcode, 23);
6695 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6696
6697 // (shift_t, shift_n) = (SRType_LSL, 0);
6698 shift_t = SRType_LSL;
6699 shift_n = 0;
6700
6701 // if t == 15 || m == 15 then UNPREDICTABLE;
6702 if ((t == 15) || (m == 15))
6703 return false;
6704
6705 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6706 if (wback && ((n == 15) || (n == t)))
6707 return false;
6708
6709 break;
6710
6711 default:
6712 return false;
6713 }
6714
6715 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6716
6717 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6718 if (!success)
6719 return false;
6720
6721 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6722
6723 addr_t offset_addr;
6724 addr_t address;
6725
6726 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6727 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6728 if (!success)
6729 return false;
6730
6731 if (add)
6732 offset_addr = Rn + offset;
6733 else
6734 offset_addr = Rn - offset;
6735
6736 // address = if index then offset_addr else R[n];
6737 if (index)
6738 address = offset_addr;
6739 else
6740 address = Rn;
6741
6742 // data = MemU[address,2];
6743 Register base_reg;
6744 Register offset_reg;
6745 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6746 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6747
6748 EmulateInstruction::Context context;
6749 context.type = eContextRegisterLoad;
6750 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6751 uint64_t data = MemURead (context, address, 2, 0, &success);
6752 if (!success)
6753 return false;
6754
6755 // if wback then R[n] = offset_addr;
6756 if (wback)
6757 {
6758 context.type = eContextAdjustBaseRegister;
6759 context.SetAddress (offset_addr);
6760 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6761 return false;
6762 }
6763
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006764 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006765 if (UnalignedSupport() || BitIsClear (address, 0))
6766 {
6767 // R[t] = ZeroExtend(data, 32);
6768 context.type = eContextRegisterLoad;
6769 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6770 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6771 return false;
6772 }
6773 else // Can only apply before ARMv7
6774 {
6775 // R[t] = bits(32) UNKNOWN;
6776 WriteBits32Unknown (t);
6777 }
6778 }
6779 return true;
6780}
6781
Caroline Ticea5e28af2011-03-01 21:53:03 +00006782// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6783// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6784// or pre-indexed addressing.
6785bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006786EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006787{
6788#if 0
6789 if ConditionPassed() then
6790 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6791 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6792 address = if index then offset_addr else R[n];
6793 R[t] = SignExtend(MemU[address,1], 32);
6794 if wback then R[n] = offset_addr;
6795#endif
6796
6797 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006798
Greg Clayton7bc39082011-03-24 23:53:38 +00006799 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006800 {
6801 uint32_t t;
6802 uint32_t n;
6803 uint32_t imm32;
6804 bool index;
6805 bool add;
6806 bool wback;
6807
6808 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6809 switch (encoding)
6810 {
6811 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006812 // if Rt == '1111' then SEE PLI;
6813 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006814 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6815 t = Bits32 (opcode, 15, 12);
6816 n = Bits32 (opcode, 19, 16);
6817 imm32 = Bits32 (opcode, 11, 0);
6818
6819 // index = TRUE; add = TRUE; wback = FALSE;
6820 index = true;
6821 add = true;
6822 wback = false;
6823
6824 // if t == 13 then UNPREDICTABLE;
6825 if (t == 13)
6826 return false;
6827
6828 break;
6829
6830 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006831 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6832 // if Rn == '1111' then SEE LDRSB (literal);
6833 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6834 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006835 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6836 return false;
6837
6838 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6839 t = Bits32 (opcode, 15, 12);
6840 n = Bits32 (opcode, 19, 16);
6841 imm32 = Bits32 (opcode, 7, 0);
6842
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006843 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006844 index = BitIsSet (opcode, 10);
6845 add = BitIsSet (opcode, 9);
6846 wback = BitIsSet (opcode, 8);
6847
6848 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006849 if (((t == 13) || ((t == 15)
6850 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6851 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006852 return false;
6853
6854 break;
6855
6856 case eEncodingA1:
6857 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006858 // if Rn == '1111' then SEE LDRSB (literal);
6859 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006860 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6861 t = Bits32 (opcode, 15, 12);
6862 n = Bits32 (opcode, 19, 16);
6863
6864 uint32_t imm4H = Bits32 (opcode, 11, 8);
6865 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006866 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006867
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006868 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006869 index = BitIsSet (opcode, 24);
6870 add = BitIsSet (opcode, 23);
6871 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6872
6873 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6874 if ((t == 15) || (wback && (n == t)))
6875 return false;
6876
6877 break;
6878 }
6879
6880 default:
6881 return false;
6882 }
6883
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006884 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006885 if (!success)
6886 return false;
6887
6888 addr_t offset_addr;
6889 addr_t address;
6890
6891 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6892 if (add)
6893 offset_addr = Rn + imm32;
6894 else
6895 offset_addr = Rn - imm32;
6896
6897 // address = if index then offset_addr else R[n];
6898 if (index)
6899 address = offset_addr;
6900 else
6901 address = Rn;
6902
6903 // R[t] = SignExtend(MemU[address,1], 32);
6904 Register base_reg;
6905 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6906
6907 EmulateInstruction::Context context;
6908 context.type = eContextRegisterLoad;
6909 context.SetRegisterPlusOffset (base_reg, address - Rn);
6910
6911 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6912 if (!success)
6913 return false;
6914
6915 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6916 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6917 return false;
6918
6919 // if wback then R[n] = offset_addr;
6920 if (wback)
6921 {
6922 context.type = eContextAdjustBaseRegister;
6923 context.SetAddress (offset_addr);
6924 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6925 return false;
6926 }
6927 }
6928
6929 return true;
6930}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006931
Caroline Tice5f593912011-03-01 22:25:17 +00006932// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6933// sign-extends it to form a 32-bit word, and writes tit to a register.
6934bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006935EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006936{
6937#if 0
6938 if ConditionPassed() then
6939 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6940 base = Align(PC,4);
6941 address = if add then (base + imm32) else (base - imm32);
6942 R[t] = SignExtend(MemU[address,1], 32);
6943#endif
6944
6945 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006946
Greg Clayton7bc39082011-03-24 23:53:38 +00006947 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006948 {
6949 uint32_t t;
6950 uint32_t imm32;
6951 bool add;
6952
6953 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6954 switch (encoding)
6955 {
6956 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006957 // if Rt == '1111' then SEE PLI;
6958 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006959 t = Bits32 (opcode, 15, 12);
6960 imm32 = Bits32 (opcode, 11, 0);
6961 add = BitIsSet (opcode, 23);
6962
6963 // if t == 13 then UNPREDICTABLE;
6964 if (t == 13)
6965 return false;
6966
6967 break;
6968
6969 case eEncodingA1:
6970 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006971 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006972 t = Bits32 (opcode, 15, 12);
6973 uint32_t imm4H = Bits32 (opcode, 11, 8);
6974 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006975 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006976 add = BitIsSet (opcode, 23);
6977
6978 // if t == 15 then UNPREDICTABLE;
6979 if (t == 15)
6980 return false;
6981
6982 break;
6983 }
6984
6985 default:
6986 return false;
6987 }
6988
6989 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006990 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006991 if (!success)
6992 return false;
6993 uint64_t base = AlignPC (pc_value);
6994
6995 // address = if add then (base + imm32) else (base - imm32);
6996 addr_t address;
6997 if (add)
6998 address = base + imm32;
6999 else
7000 address = base - imm32;
7001
7002 // R[t] = SignExtend(MemU[address,1], 32);
7003 Register base_reg;
7004 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7005
7006 EmulateInstruction::Context context;
7007 context.type = eContextRegisterLoad;
7008 context.SetRegisterPlusOffset (base_reg, address - base);
7009
7010 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7011 if (!success)
7012 return false;
7013
7014 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7015 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7016 return false;
7017 }
7018 return true;
7019}
7020
Caroline Tice672f3112011-03-01 23:55:59 +00007021// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7022// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7023// shifted left by 0, 1, 2, or 3 bits.
7024bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007025EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007026{
7027#if 0
7028 if ConditionPassed() then
7029 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7030 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7031 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7032 address = if index then offset_addr else R[n];
7033 R[t] = SignExtend(MemU[address,1], 32);
7034 if wback then R[n] = offset_addr;
7035#endif
7036
7037 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007038
Greg Clayton7bc39082011-03-24 23:53:38 +00007039 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007040 {
7041 uint32_t t;
7042 uint32_t n;
7043 uint32_t m;
7044 bool index;
7045 bool add;
7046 bool wback;
7047 ARM_ShifterType shift_t;
7048 uint32_t shift_n;
7049
7050 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7051 switch (encoding)
7052 {
7053 case eEncodingT1:
7054 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7055 t = Bits32 (opcode, 2, 0);
7056 n = Bits32 (opcode, 5, 3);
7057 m = Bits32 (opcode, 8, 6);
7058
7059 // index = TRUE; add = TRUE; wback = FALSE;
7060 index = true;
7061 add = true;
7062 wback = false;
7063
7064 // (shift_t, shift_n) = (SRType_LSL, 0);
7065 shift_t = SRType_LSL;
7066 shift_n = 0;
7067
7068 break;
7069
7070 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007071 // if Rt == '1111' then SEE PLI;
7072 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007073 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7074 t = Bits32 (opcode, 15, 12);
7075 n = Bits32 (opcode, 19, 16);
7076 m = Bits32 (opcode, 3, 0);
7077
7078 // index = TRUE; add = TRUE; wback = FALSE;
7079 index = true;
7080 add = true;
7081 wback = false;
7082
7083 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7084 shift_t = SRType_LSL;
7085 shift_n = Bits32 (opcode, 5, 4);
7086
7087 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7088 if ((t == 13) || BadReg (m))
7089 return false;
7090 break;
7091
7092 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007093 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007094 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7095 t = Bits32 (opcode, 15, 12);
7096 n = Bits32 (opcode, 19, 16);
7097 m = Bits32 (opcode, 3, 0);
7098
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007099 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007100 index = BitIsSet (opcode, 24);
7101 add = BitIsSet (opcode, 23);
7102 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7103
7104 // (shift_t, shift_n) = (SRType_LSL, 0);
7105 shift_t = SRType_LSL;
7106 shift_n = 0;
7107
7108 // if t == 15 || m == 15 then UNPREDICTABLE;
7109 if ((t == 15) || (m == 15))
7110 return false;
7111
7112 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7113 if (wback && ((n == 15) || (n == t)))
7114 return false;
7115 break;
7116
7117 default:
7118 return false;
7119 }
7120
7121 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7122 if (!success)
7123 return false;
7124
7125 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7126 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7127
7128 addr_t offset_addr;
7129 addr_t address;
7130
7131 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7132 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7133 if (!success)
7134 return false;
7135
7136 if (add)
7137 offset_addr = Rn + offset;
7138 else
7139 offset_addr = Rn - offset;
7140
7141 // address = if index then offset_addr else R[n];
7142 if (index)
7143 address = offset_addr;
7144 else
7145 address = Rn;
7146
7147 // R[t] = SignExtend(MemU[address,1], 32);
7148 Register base_reg;
7149 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7150 Register offset_reg;
7151 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7152
7153 EmulateInstruction::Context context;
7154 context.type = eContextRegisterLoad;
7155 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7156
7157 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7158 if (!success)
7159 return false;
7160
7161 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7162 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7163 return false;
7164
7165 // if wback then R[n] = offset_addr;
7166 if (wback)
7167 {
7168 context.type = eContextAdjustBaseRegister;
7169 context.SetAddress (offset_addr);
7170 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7171 return false;
7172 }
7173 }
7174 return true;
7175}
7176
Caroline Tice78fb5632011-03-02 00:39:42 +00007177// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7178// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7179// pre-indexed addressing.
7180bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007181EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007182{
7183#if 0
7184 if ConditionPassed() then
7185 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7186 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7187 address = if index then offset_addr else R[n];
7188 data = MemU[address,2];
7189 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007190 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007191 R[t] = SignExtend(data, 32);
7192 else // Can only apply before ARMv7
7193 R[t] = bits(32) UNKNOWN;
7194#endif
7195
7196 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007197
Greg Clayton7bc39082011-03-24 23:53:38 +00007198 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007199 {
7200 uint32_t t;
7201 uint32_t n;
7202 uint32_t imm32;
7203 bool index;
7204 bool add;
7205 bool wback;
7206
7207 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7208 switch (encoding)
7209 {
7210 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007211 // if Rn == '1111' then SEE LDRSH (literal);
7212 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007213 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7214 t = Bits32 (opcode, 15, 12);
7215 n = Bits32 (opcode, 19, 16);
7216 imm32 = Bits32 (opcode, 11, 0);
7217
7218 // index = TRUE; add = TRUE; wback = FALSE;
7219 index = true;
7220 add = true;
7221 wback = false;
7222
7223 // if t == 13 then UNPREDICTABLE;
7224 if (t == 13)
7225 return false;
7226
7227 break;
7228
7229 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007230 // if Rn == '1111' then SEE LDRSH (literal);
7231 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7232 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7233 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007234 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7235 return false;
7236
7237 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7238 t = Bits32 (opcode, 15, 12);
7239 n = Bits32 (opcode, 19, 16);
7240 imm32 = Bits32 (opcode, 7, 0);
7241
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007242 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007243 index = BitIsSet (opcode, 10);
7244 add = BitIsSet (opcode, 9);
7245 wback = BitIsSet (opcode, 8);
7246
7247 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7248 if (BadReg (t) || (wback && (n == t)))
7249 return false;
7250
7251 break;
7252
7253 case eEncodingA1:
7254 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007255 // if Rn == '1111' then SEE LDRSH (literal);
7256 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007257 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7258 t = Bits32 (opcode, 15, 12);
7259 n = Bits32 (opcode, 19, 16);
7260 uint32_t imm4H = Bits32 (opcode, 11,8);
7261 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007262 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007263
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007264 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007265 index = BitIsSet (opcode, 24);
7266 add = BitIsSet (opcode, 23);
7267 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7268
7269 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7270 if ((t == 15) || (wback && (n == t)))
7271 return false;
7272
7273 break;
7274 }
7275
7276 default:
7277 return false;
7278 }
7279
7280 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7281 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7282 if (!success)
7283 return false;
7284
7285 addr_t offset_addr;
7286 if (add)
7287 offset_addr = Rn + imm32;
7288 else
7289 offset_addr = Rn - imm32;
7290
7291 // address = if index then offset_addr else R[n];
7292 addr_t address;
7293 if (index)
7294 address = offset_addr;
7295 else
7296 address = Rn;
7297
7298 // data = MemU[address,2];
7299 Register base_reg;
7300 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7301
7302 EmulateInstruction::Context context;
7303 context.type = eContextRegisterLoad;
7304 context.SetRegisterPlusOffset (base_reg, address - Rn);
7305
7306 uint64_t data = MemURead (context, address, 2, 0, &success);
7307 if (!success)
7308 return false;
7309
7310 // if wback then R[n] = offset_addr;
7311 if (wback)
7312 {
7313 context.type = eContextAdjustBaseRegister;
7314 context.SetAddress (offset_addr);
7315 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7316 return false;
7317 }
7318
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007319 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007320 if (UnalignedSupport() || BitIsClear (address, 0))
7321 {
7322 // R[t] = SignExtend(data, 32);
7323 int64_t signed_data = llvm::SignExtend64<16>(data);
7324 context.type = eContextRegisterLoad;
7325 context.SetRegisterPlusOffset (base_reg, address - Rn);
7326 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7327 return false;
7328 }
7329 else // Can only apply before ARMv7
7330 {
7331 // R[t] = bits(32) UNKNOWN;
7332 WriteBits32Unknown (t);
7333 }
7334 }
7335 return true;
7336}
7337
Caroline Ticed2fac092011-03-02 19:45:34 +00007338// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7339// sign-extends it to from a 32-bit word, and writes it to a register.
7340bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007341EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007342{
7343#if 0
7344 if ConditionPassed() then
7345 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7346 base = Align(PC,4);
7347 address = if add then (base + imm32) else (base - imm32);
7348 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007349 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007350 R[t] = SignExtend(data, 32);
7351 else // Can only apply before ARMv7
7352 R[t] = bits(32) UNKNOWN;
7353#endif
7354
7355 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007356
Greg Clayton7bc39082011-03-24 23:53:38 +00007357 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007358 {
7359 uint32_t t;
7360 uint32_t imm32;
7361 bool add;
7362
7363 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7364 switch (encoding)
7365 {
7366 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007367 // if Rt == '1111' then SEE "Unallocated memory hints";
7368 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007369 t = Bits32 (opcode, 15, 12);
7370 imm32 = Bits32 (opcode, 11, 0);
7371 add = BitIsSet (opcode, 23);
7372
7373 // if t == 13 then UNPREDICTABLE;
7374 if (t == 13)
7375 return false;
7376
7377 break;
7378
7379 case eEncodingA1:
7380 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007381 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007382 t = Bits32 (opcode, 15, 12);
7383 uint32_t imm4H = Bits32 (opcode, 11, 8);
7384 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007385 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007386 add = BitIsSet (opcode, 23);
7387
7388 // if t == 15 then UNPREDICTABLE;
7389 if (t == 15)
7390 return false;
7391
7392 break;
7393 }
7394 default:
7395 return false;
7396 }
7397
7398 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007399 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007400 if (!success)
7401 return false;
7402
7403 uint64_t base = AlignPC (pc_value);
7404
7405 addr_t address;
7406 // address = if add then (base + imm32) else (base - imm32);
7407 if (add)
7408 address = base + imm32;
7409 else
7410 address = base - imm32;
7411
7412 // data = MemU[address,2];
7413 Register base_reg;
7414 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7415
7416 EmulateInstruction::Context context;
7417 context.type = eContextRegisterLoad;
7418 context.SetRegisterPlusOffset (base_reg, imm32);
7419
7420 uint64_t data = MemURead (context, address, 2, 0, &success);
7421 if (!success)
7422 return false;
7423
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007424 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007425 if (UnalignedSupport() || BitIsClear (address, 0))
7426 {
7427 // R[t] = SignExtend(data, 32);
7428 int64_t signed_data = llvm::SignExtend64<16>(data);
7429 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7430 return false;
7431 }
7432 else // Can only apply before ARMv7
7433 {
7434 // R[t] = bits(32) UNKNOWN;
7435 WriteBits32Unknown (t);
7436 }
7437 }
7438 return true;
7439}
7440
Caroline Tice291a3e92011-03-02 21:13:44 +00007441// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7442// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7443// shifted left by 0, 1, 2, or 3 bits.
7444bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007445EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007446{
7447#if 0
7448 if ConditionPassed() then
7449 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7450 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7451 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7452 address = if index then offset_addr else R[n];
7453 data = MemU[address,2];
7454 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007455 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007456 R[t] = SignExtend(data, 32);
7457 else // Can only apply before ARMv7
7458 R[t] = bits(32) UNKNOWN;
7459#endif
7460
7461 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007462
Greg Clayton7bc39082011-03-24 23:53:38 +00007463 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007464 {
7465 uint32_t t;
7466 uint32_t n;
7467 uint32_t m;
7468 bool index;
7469 bool add;
7470 bool wback;
7471 ARM_ShifterType shift_t;
7472 uint32_t shift_n;
7473
7474 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7475 switch (encoding)
7476 {
7477 case eEncodingT1:
7478 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7479 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7480 t = Bits32 (opcode, 2, 0);
7481 n = Bits32 (opcode, 5, 3);
7482 m = Bits32 (opcode, 8, 6);
7483
7484 // index = TRUE; add = TRUE; wback = FALSE;
7485 index = true;
7486 add = true;
7487 wback = false;
7488
7489 // (shift_t, shift_n) = (SRType_LSL, 0);
7490 shift_t = SRType_LSL;
7491 shift_n = 0;
7492
7493 break;
7494
7495 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007496 // if Rn == '1111' then SEE LDRSH (literal);
7497 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007498 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7499 t = Bits32 (opcode, 15, 12);
7500 n = Bits32 (opcode, 19, 16);
7501 m = Bits32 (opcode, 3, 0);
7502
7503 // index = TRUE; add = TRUE; wback = FALSE;
7504 index = true;
7505 add = true;
7506 wback = false;
7507
7508 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7509 shift_t = SRType_LSL;
7510 shift_n = Bits32 (opcode, 5, 4);
7511
7512 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7513 if ((t == 13) || BadReg (m))
7514 return false;
7515
7516 break;
7517
7518 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007519 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007520 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7521 t = Bits32 (opcode, 15, 12);
7522 n = Bits32 (opcode, 19, 16);
7523 m = Bits32 (opcode, 3, 0);
7524
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007525 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007526 index = BitIsSet (opcode, 24);
7527 add = BitIsSet (opcode, 23);
7528 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7529
7530 // (shift_t, shift_n) = (SRType_LSL, 0);
7531 shift_t = SRType_LSL;
7532 shift_n = 0;
7533
7534 // if t == 15 || m == 15 then UNPREDICTABLE;
7535 if ((t == 15) || (m == 15))
7536 return false;
7537
7538 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7539 if (wback && ((n == 15) || (n == t)))
7540 return false;
7541
7542 break;
7543
7544 default:
7545 break;
7546 }
7547
7548 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7549 if (!success)
7550 return false;
7551
7552 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7553 if (!success)
7554 return false;
7555
7556 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7557 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7558
7559 addr_t offset_addr;
7560 addr_t address;
7561
7562 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7563 if (add)
7564 offset_addr = Rn + offset;
7565 else
7566 offset_addr = Rn - offset;
7567
7568 // address = if index then offset_addr else R[n];
7569 if (index)
7570 address = offset_addr;
7571 else
7572 address = Rn;
7573
7574 // data = MemU[address,2];
7575 Register base_reg;
7576 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7577
7578 Register offset_reg;
7579 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7580
7581 EmulateInstruction::Context context;
7582 context.type = eContextRegisterLoad;
7583 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7584
7585 uint64_t data = MemURead (context, address, 2, 0, &success);
7586 if (!success)
7587 return false;
7588
7589 // if wback then R[n] = offset_addr;
7590 if (wback)
7591 {
7592 context.type = eContextAdjustBaseRegister;
7593 context.SetAddress (offset_addr);
7594 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7595 return false;
7596 }
7597
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007598 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007599 if (UnalignedSupport() || BitIsClear (address, 0))
7600 {
7601 // R[t] = SignExtend(data, 32);
7602 context.type = eContextRegisterLoad;
7603 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7604
7605 int64_t signed_data = llvm::SignExtend64<16>(data);
7606 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7607 return false;
7608 }
7609 else // Can only apply before ARMv7
7610 {
7611 // R[t] = bits(32) UNKNOWN;
7612 WriteBits32Unknown (t);
7613 }
7614 }
7615 return true;
7616}
Caroline Tice6bf65162011-03-03 17:42:58 +00007617
7618// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7619// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7620bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007621EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007622{
7623#if 0
7624 if ConditionPassed() then
7625 EncodingSpecificOperations();
7626 rotated = ROR(R[m], rotation);
7627 R[d] = SignExtend(rotated<7:0>, 32);
7628#endif
7629
7630 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007631
Greg Clayton7bc39082011-03-24 23:53:38 +00007632 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007633 {
7634 uint32_t d;
7635 uint32_t m;
7636 uint32_t rotation;
7637
7638 // EncodingSpecificOperations();
7639 switch (encoding)
7640 {
7641 case eEncodingT1:
7642 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7643 d = Bits32 (opcode, 2, 0);
7644 m = Bits32 (opcode, 5, 3);
7645 rotation = 0;
7646
7647 break;
7648
7649 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007650 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007651 d = Bits32 (opcode, 11, 8);
7652 m = Bits32 (opcode, 3, 0);
7653 rotation = Bits32 (opcode, 5, 4) << 3;
7654
7655 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7656 if (BadReg (d) || BadReg (m))
7657 return false;
7658
7659 break;
7660
7661 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007662 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007663 d = Bits32 (opcode, 15, 12);
7664 m = Bits32 (opcode, 3, 0);
7665 rotation = Bits32 (opcode, 11, 10) << 3;
7666
7667 // if d == 15 || m == 15 then UNPREDICTABLE;
7668 if ((d == 15) || (m == 15))
7669 return false;
7670
7671 break;
7672
7673 default:
7674 return false;
7675 }
7676
Caroline Tice868198b2011-03-03 18:04:49 +00007677 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7678 if (!success)
7679 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007680
7681 // rotated = ROR(R[m], rotation);
7682 uint64_t rotated = ROR (Rm, rotation);
7683
7684 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007685 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007686
7687 Register source_reg;
7688 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7689
7690 EmulateInstruction::Context context;
7691 context.type = eContextRegisterLoad;
7692 context.SetRegister (source_reg);
7693
Caroline Tice8ce96d92011-03-03 18:27:17 +00007694 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007695 return false;
7696 }
7697 return true;
7698}
Caroline Tice291a3e92011-03-02 21:13:44 +00007699
Caroline Tice868198b2011-03-03 18:04:49 +00007700// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7701// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7702bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007703EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007704{
7705#if 0
7706 if ConditionPassed() then
7707 EncodingSpecificOperations();
7708 rotated = ROR(R[m], rotation);
7709 R[d] = SignExtend(rotated<15:0>, 32);
7710#endif
7711
7712 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007713
Greg Clayton7bc39082011-03-24 23:53:38 +00007714 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007715 {
7716 uint32_t d;
7717 uint32_t m;
7718 uint32_t rotation;
7719
7720 // EncodingSpecificOperations();
7721 switch (encoding)
7722 {
7723 case eEncodingT1:
7724 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7725 d = Bits32 (opcode, 2, 0);
7726 m = Bits32 (opcode, 5, 3);
7727 rotation = 0;
7728
7729 break;
7730
7731 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007732 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007733 d = Bits32 (opcode, 11, 8);
7734 m = Bits32 (opcode, 3, 0);
7735 rotation = Bits32 (opcode, 5, 4) << 3;
7736
7737 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7738 if (BadReg (d) || BadReg (m))
7739 return false;
7740
7741 break;
7742
7743 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007744 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007745 d = Bits32 (opcode, 15, 12);
7746 m = Bits32 (opcode, 3, 0);
7747 rotation = Bits32 (opcode, 11, 10) << 3;
7748
7749 // if d == 15 || m == 15 then UNPREDICTABLE;
7750 if ((d == 15) || (m == 15))
7751 return false;
7752
7753 break;
7754
7755 default:
7756 return false;
7757 }
7758
7759 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7760 if (!success)
7761 return false;
7762
7763 // rotated = ROR(R[m], rotation);
7764 uint64_t rotated = ROR (Rm, rotation);
7765
7766 // R[d] = SignExtend(rotated<15:0>, 32);
7767 Register source_reg;
7768 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7769
7770 EmulateInstruction::Context context;
7771 context.type = eContextRegisterLoad;
7772 context.SetRegister (source_reg);
7773
Caroline Tice8ce96d92011-03-03 18:27:17 +00007774 int64_t data = llvm::SignExtend64<16> (rotated);
7775 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007776 return false;
7777 }
7778
7779 return true;
7780}
7781
Caroline Tice8ce96d92011-03-03 18:27:17 +00007782// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7783// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7784bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007785EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007786{
7787#if 0
7788 if ConditionPassed() then
7789 EncodingSpecificOperations();
7790 rotated = ROR(R[m], rotation);
7791 R[d] = ZeroExtend(rotated<7:0>, 32);
7792#endif
7793
7794 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007795
Greg Clayton7bc39082011-03-24 23:53:38 +00007796 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007797 {
7798 uint32_t d;
7799 uint32_t m;
7800 uint32_t rotation;
7801
7802 // EncodingSpecificOperations();
7803 switch (encoding)
7804 {
7805 case eEncodingT1:
7806 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7807 d = Bits32 (opcode, 2, 0);
7808 m = Bits32 (opcode, 5, 3);
7809 rotation = 0;
7810
7811 break;
7812
7813 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007814 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007815 d = Bits32 (opcode, 11, 8);
7816 m = Bits32 (opcode, 3, 0);
7817 rotation = Bits32 (opcode, 5, 4) << 3;
7818
7819 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7820 if (BadReg (d) || BadReg (m))
7821 return false;
7822
7823 break;
7824
7825 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007826 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007827 d = Bits32 (opcode, 15, 12);
7828 m = Bits32 (opcode, 3, 0);
7829 rotation = Bits32 (opcode, 11, 10) << 3;
7830
7831 // if d == 15 || m == 15 then UNPREDICTABLE;
7832 if ((d == 15) || (m == 15))
7833 return false;
7834
7835 break;
7836
7837 default:
7838 return false;
7839 }
7840
7841 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7842 if (!success)
7843 return false;
7844
7845 // rotated = ROR(R[m], rotation);
7846 uint64_t rotated = ROR (Rm, rotation);
7847
7848 // R[d] = ZeroExtend(rotated<7:0>, 32);
7849 Register source_reg;
7850 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7851
7852 EmulateInstruction::Context context;
7853 context.type = eContextRegisterLoad;
7854 context.SetRegister (source_reg);
7855
7856 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7857 return false;
7858 }
7859 return true;
7860}
7861
Caroline Tice11555f22011-03-03 18:48:58 +00007862// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7863// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7864bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007865EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007866{
7867#if 0
7868 if ConditionPassed() then
7869 EncodingSpecificOperations();
7870 rotated = ROR(R[m], rotation);
7871 R[d] = ZeroExtend(rotated<15:0>, 32);
7872#endif
7873
7874 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007875
Greg Clayton7bc39082011-03-24 23:53:38 +00007876 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007877 {
7878 uint32_t d;
7879 uint32_t m;
7880 uint32_t rotation;
7881
7882 switch (encoding)
7883 {
7884 case eEncodingT1:
7885 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7886 d = Bits32 (opcode, 2, 0);
7887 m = Bits32 (opcode, 5, 3);
7888 rotation = 0;
7889
7890 break;
7891
7892 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007893 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007894 d = Bits32 (opcode, 11, 8);
7895 m = Bits32 (opcode, 3, 0);
7896 rotation = Bits32 (opcode, 5, 4) << 3;
7897
7898 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7899 if (BadReg (d) || BadReg (m))
7900 return false;
7901
7902 break;
7903
7904 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007905 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007906 d = Bits32 (opcode, 15, 12);
7907 m = Bits32 (opcode, 3, 0);
7908 rotation = Bits32 (opcode, 11, 10) << 3;
7909
7910 // if d == 15 || m == 15 then UNPREDICTABLE;
7911 if ((d == 15) || (m == 15))
7912 return false;
7913
7914 break;
7915
7916 default:
7917 return false;
7918 }
7919
7920 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7921 if (!success)
7922 return false;
7923
7924 // rotated = ROR(R[m], rotation);
7925 uint64_t rotated = ROR (Rm, rotation);
7926
7927 // R[d] = ZeroExtend(rotated<15:0>, 32);
7928 Register source_reg;
7929 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7930
7931 EmulateInstruction::Context context;
7932 context.type = eContextRegisterLoad;
7933 context.SetRegister (source_reg);
7934
7935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7936 return false;
7937 }
7938 return true;
7939}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007940
7941// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7942// word respectively.
7943bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007944EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007945{
7946#if 0
7947 if ConditionPassed() then
7948 EncodingSpecificOperations();
7949 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7950 UNPREDICTABLE;
7951 else
7952 address = if increment then R[n] else R[n]-8;
7953 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007954 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007955 BranchWritePC(MemA[address,4]);
7956 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7957#endif
7958
7959 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007960
Greg Clayton7bc39082011-03-24 23:53:38 +00007961 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007962 {
7963 uint32_t n;
7964 bool wback;
7965 bool increment;
7966 bool wordhigher;
7967
7968 // EncodingSpecificOperations();
7969 switch (encoding)
7970 {
7971 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007972 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007973 n = Bits32 (opcode, 19, 16);
7974 wback = BitIsSet (opcode, 21);
7975 increment = false;
7976 wordhigher = false;
7977
7978 // if n == 15 then UNPREDICTABLE;
7979 if (n == 15)
7980 return false;
7981
7982 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7983 if (InITBlock() && !LastInITBlock())
7984 return false;
7985
7986 break;
7987
7988 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007989 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007990 n = Bits32 (opcode, 19, 16);
7991 wback = BitIsSet (opcode, 21);
7992 increment = true;
7993 wordhigher = false;
7994
7995 // if n == 15 then UNPREDICTABLE;
7996 if (n == 15)
7997 return false;
7998
7999 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8000 if (InITBlock() && !LastInITBlock())
8001 return false;
8002
8003 break;
8004
8005 case eEncodingA1:
8006 // n = UInt(Rn);
8007 n = Bits32 (opcode, 19, 16);
8008
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008009 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008010 wback = BitIsSet (opcode, 21);
8011 increment = BitIsSet (opcode, 23);
8012 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8013
8014 // if n == 15 then UNPREDICTABLE;
8015 if (n == 15)
8016 return false;
8017
8018 break;
8019
8020 default:
8021 return false;
8022 }
8023
8024 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8025 if (!CurrentModeIsPrivileged ())
8026 // UNPREDICTABLE;
8027 return false;
8028 else
8029 {
8030 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8031 if (!success)
8032 return false;
8033
8034 addr_t address;
8035 // address = if increment then R[n] else R[n]-8;
8036 if (increment)
8037 address = Rn;
8038 else
8039 address = Rn - 8;
8040
8041 // if wordhigher then address = address+4;
8042 if (wordhigher)
8043 address = address + 4;
8044
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008045 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008046 Register base_reg;
8047 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8048
8049 EmulateInstruction::Context context;
8050 context.type = eContextReturnFromException;
8051 context.SetRegisterPlusOffset (base_reg, address - Rn);
8052
8053 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8054 if (!success)
8055 return false;
8056
8057 CPSRWriteByInstr (data, 15, true);
8058
8059 // BranchWritePC(MemA[address,4]);
8060 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8061 if (!success)
8062 return false;
8063
8064 BranchWritePC (context, data2);
8065
8066 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8067 if (wback)
8068 {
8069 context.type = eContextAdjustBaseRegister;
8070 if (increment)
8071 {
8072 context.SetOffset (8);
8073 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8074 return false;
8075 }
8076 else
8077 {
8078 context.SetOffset (-8);
8079 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8080 return false;
8081 }
8082 } // if wback
8083 }
8084 } // if ConditionPassed()
8085 return true;
8086}
Caroline Tice11555f22011-03-03 18:48:58 +00008087
Johnny Chen2115b412011-02-21 23:42:44 +00008088// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8089// and writes the result to the destination register. It can optionally update the condition flags based on
8090// the result.
8091bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008092EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008093{
8094#if 0
8095 // ARM pseudo code...
8096 if ConditionPassed() then
8097 EncodingSpecificOperations();
8098 result = R[n] EOR imm32;
8099 if d == 15 then // Can only occur for ARM encoding
8100 ALUWritePC(result); // setflags is always FALSE here
8101 else
8102 R[d] = result;
8103 if setflags then
8104 APSR.N = result<31>;
8105 APSR.Z = IsZeroBit(result);
8106 APSR.C = carry;
8107 // APSR.V unchanged
8108#endif
8109
8110 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008111
Greg Clayton7bc39082011-03-24 23:53:38 +00008112 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008113 {
8114 uint32_t Rd, Rn;
8115 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8116 bool setflags;
8117 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8118 switch (encoding)
8119 {
8120 case eEncodingT1:
8121 Rd = Bits32(opcode, 11, 8);
8122 Rn = Bits32(opcode, 19, 16);
8123 setflags = BitIsSet(opcode, 20);
8124 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8125 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8126 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008127 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008128 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8129 return false;
8130 break;
8131 case eEncodingA1:
8132 Rd = Bits32(opcode, 15, 12);
8133 Rn = Bits32(opcode, 19, 16);
8134 setflags = BitIsSet(opcode, 20);
8135 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008136
Johnny Chen2115b412011-02-21 23:42:44 +00008137 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008138 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008139 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008140 break;
8141 default:
8142 return false;
8143 }
8144
8145 // Read the first operand.
8146 uint32_t val1 = ReadCoreReg(Rn, &success);
8147 if (!success)
8148 return false;
8149
8150 uint32_t result = val1 ^ imm32;
8151
8152 EmulateInstruction::Context context;
8153 context.type = EmulateInstruction::eContextImmediate;
8154 context.SetNoArgs ();
8155
8156 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8157 return false;
8158 }
8159 return true;
8160}
8161
8162// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8163// optionally-shifted register value, and writes the result to the destination register.
8164// It can optionally update the condition flags based on the result.
8165bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008166EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008167{
8168#if 0
8169 // ARM pseudo code...
8170 if ConditionPassed() then
8171 EncodingSpecificOperations();
8172 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8173 result = R[n] EOR shifted;
8174 if d == 15 then // Can only occur for ARM encoding
8175 ALUWritePC(result); // setflags is always FALSE here
8176 else
8177 R[d] = result;
8178 if setflags then
8179 APSR.N = result<31>;
8180 APSR.Z = IsZeroBit(result);
8181 APSR.C = carry;
8182 // APSR.V unchanged
8183#endif
8184
8185 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008186
Greg Clayton7bc39082011-03-24 23:53:38 +00008187 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008188 {
8189 uint32_t Rd, Rn, Rm;
8190 ARM_ShifterType shift_t;
8191 uint32_t shift_n; // the shift applied to the value read from Rm
8192 bool setflags;
8193 uint32_t carry;
8194 switch (encoding)
8195 {
8196 case eEncodingT1:
8197 Rd = Rn = Bits32(opcode, 2, 0);
8198 Rm = Bits32(opcode, 5, 3);
8199 setflags = !InITBlock();
8200 shift_t = SRType_LSL;
8201 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008202 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008203 case eEncodingT2:
8204 Rd = Bits32(opcode, 11, 8);
8205 Rn = Bits32(opcode, 19, 16);
8206 Rm = Bits32(opcode, 3, 0);
8207 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008208 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8209 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008210 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008211 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008212 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8213 return false;
8214 break;
8215 case eEncodingA1:
8216 Rd = Bits32(opcode, 15, 12);
8217 Rn = Bits32(opcode, 19, 16);
8218 Rm = Bits32(opcode, 3, 0);
8219 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008220 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008221
Johnny Chen2115b412011-02-21 23:42:44 +00008222 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008223 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008224 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008225 break;
8226 default:
8227 return false;
8228 }
8229
8230 // Read the first operand.
8231 uint32_t val1 = ReadCoreReg(Rn, &success);
8232 if (!success)
8233 return false;
8234
8235 // Read the second operand.
8236 uint32_t val2 = ReadCoreReg(Rm, &success);
8237 if (!success)
8238 return false;
8239
8240 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8241 uint32_t result = val1 ^ shifted;
8242
8243 EmulateInstruction::Context context;
8244 context.type = EmulateInstruction::eContextImmediate;
8245 context.SetNoArgs ();
8246
8247 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8248 return false;
8249 }
8250 return true;
8251}
8252
Johnny Chen7c5234d2011-02-18 23:41:11 +00008253// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8254// writes the result to the destination register. It can optionally update the condition flags based
8255// on the result.
8256bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008257EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008258{
8259#if 0
8260 // ARM pseudo code...
8261 if ConditionPassed() then
8262 EncodingSpecificOperations();
8263 result = R[n] OR imm32;
8264 if d == 15 then // Can only occur for ARM encoding
8265 ALUWritePC(result); // setflags is always FALSE here
8266 else
8267 R[d] = result;
8268 if setflags then
8269 APSR.N = result<31>;
8270 APSR.Z = IsZeroBit(result);
8271 APSR.C = carry;
8272 // APSR.V unchanged
8273#endif
8274
8275 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008276
Greg Clayton7bc39082011-03-24 23:53:38 +00008277 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008278 {
8279 uint32_t Rd, Rn;
8280 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8281 bool setflags;
8282 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8283 switch (encoding)
8284 {
8285 case eEncodingT1:
8286 Rd = Bits32(opcode, 11, 8);
8287 Rn = Bits32(opcode, 19, 16);
8288 setflags = BitIsSet(opcode, 20);
8289 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008290 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008291 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008292 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008293 if (BadReg(Rd) || Rn == 13)
8294 return false;
8295 break;
8296 case eEncodingA1:
8297 Rd = Bits32(opcode, 15, 12);
8298 Rn = Bits32(opcode, 19, 16);
8299 setflags = BitIsSet(opcode, 20);
8300 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008301
Johnny Chen7c5234d2011-02-18 23:41:11 +00008302 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008303 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008304 break;
8305 default:
8306 return false;
8307 }
8308
8309 // Read the first operand.
8310 uint32_t val1 = ReadCoreReg(Rn, &success);
8311 if (!success)
8312 return false;
8313
8314 uint32_t result = val1 | imm32;
8315
8316 EmulateInstruction::Context context;
8317 context.type = EmulateInstruction::eContextImmediate;
8318 context.SetNoArgs ();
8319
8320 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8321 return false;
8322 }
8323 return true;
8324}
8325
8326// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8327// value, and writes the result to the destination register. It can optionally update the condition flags based
8328// on the result.
8329bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008330EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008331{
8332#if 0
8333 // ARM pseudo code...
8334 if ConditionPassed() then
8335 EncodingSpecificOperations();
8336 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8337 result = R[n] OR shifted;
8338 if d == 15 then // Can only occur for ARM encoding
8339 ALUWritePC(result); // setflags is always FALSE here
8340 else
8341 R[d] = result;
8342 if setflags then
8343 APSR.N = result<31>;
8344 APSR.Z = IsZeroBit(result);
8345 APSR.C = carry;
8346 // APSR.V unchanged
8347#endif
8348
8349 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008350
Greg Clayton7bc39082011-03-24 23:53:38 +00008351 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008352 {
8353 uint32_t Rd, Rn, Rm;
8354 ARM_ShifterType shift_t;
8355 uint32_t shift_n; // the shift applied to the value read from Rm
8356 bool setflags;
8357 uint32_t carry;
8358 switch (encoding)
8359 {
8360 case eEncodingT1:
8361 Rd = Rn = Bits32(opcode, 2, 0);
8362 Rm = Bits32(opcode, 5, 3);
8363 setflags = !InITBlock();
8364 shift_t = SRType_LSL;
8365 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008366 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008367 case eEncodingT2:
8368 Rd = Bits32(opcode, 11, 8);
8369 Rn = Bits32(opcode, 19, 16);
8370 Rm = Bits32(opcode, 3, 0);
8371 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008372 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8373 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008374 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008375 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008376 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8377 return false;
8378 break;
8379 case eEncodingA1:
8380 Rd = Bits32(opcode, 15, 12);
8381 Rn = Bits32(opcode, 19, 16);
8382 Rm = Bits32(opcode, 3, 0);
8383 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008384 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008385
Johnny Chen7c5234d2011-02-18 23:41:11 +00008386 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008387 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008388 break;
8389 default:
8390 return false;
8391 }
8392
8393 // Read the first operand.
8394 uint32_t val1 = ReadCoreReg(Rn, &success);
8395 if (!success)
8396 return false;
8397
8398 // Read the second operand.
8399 uint32_t val2 = ReadCoreReg(Rm, &success);
8400 if (!success)
8401 return false;
8402
8403 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008404 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008405
8406 EmulateInstruction::Context context;
8407 context.type = EmulateInstruction::eContextImmediate;
8408 context.SetNoArgs ();
8409
8410 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8411 return false;
8412 }
8413 return true;
8414}
8415
Johnny Chened32e7c2011-02-22 23:42:58 +00008416// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8417// the destination register. It can optionally update the condition flags based on the result.
8418bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008419EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008420{
8421#if 0
8422 // ARM pseudo code...
8423 if ConditionPassed() then
8424 EncodingSpecificOperations();
8425 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8426 if d == 15 then // Can only occur for ARM encoding
8427 ALUWritePC(result); // setflags is always FALSE here
8428 else
8429 R[d] = result;
8430 if setflags then
8431 APSR.N = result<31>;
8432 APSR.Z = IsZeroBit(result);
8433 APSR.C = carry;
8434 APSR.V = overflow;
8435#endif
8436
8437 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008438
8439 uint32_t Rd; // the destination register
8440 uint32_t Rn; // the first operand
8441 bool setflags;
8442 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8443 switch (encoding) {
8444 case eEncodingT1:
8445 Rd = Bits32(opcode, 2, 0);
8446 Rn = Bits32(opcode, 5, 3);
8447 setflags = !InITBlock();
8448 imm32 = 0;
8449 break;
8450 case eEncodingT2:
8451 Rd = Bits32(opcode, 11, 8);
8452 Rn = Bits32(opcode, 19, 16);
8453 setflags = BitIsSet(opcode, 20);
8454 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8455 if (BadReg(Rd) || BadReg(Rn))
8456 return false;
8457 break;
8458 case eEncodingA1:
8459 Rd = Bits32(opcode, 15, 12);
8460 Rn = Bits32(opcode, 19, 16);
8461 setflags = BitIsSet(opcode, 20);
8462 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008463
Johnny Chened32e7c2011-02-22 23:42:58 +00008464 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008465 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008466 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008467 break;
8468 default:
8469 return false;
8470 }
8471 // Read the register value from the operand register Rn.
8472 uint32_t reg_val = ReadCoreReg(Rn, &success);
8473 if (!success)
8474 return false;
8475
8476 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8477
8478 EmulateInstruction::Context context;
8479 context.type = EmulateInstruction::eContextImmediate;
8480 context.SetNoArgs ();
8481
8482 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8483 return false;
8484
8485 return true;
8486}
8487
8488// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8489// result to the destination register. It can optionally update the condition flags based on the result.
8490bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008491EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008492{
8493#if 0
8494 // ARM pseudo code...
8495 if ConditionPassed() then
8496 EncodingSpecificOperations();
8497 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8498 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8499 if d == 15 then // Can only occur for ARM encoding
8500 ALUWritePC(result); // setflags is always FALSE here
8501 else
8502 R[d] = result;
8503 if setflags then
8504 APSR.N = result<31>;
8505 APSR.Z = IsZeroBit(result);
8506 APSR.C = carry;
8507 APSR.V = overflow;
8508#endif
8509
8510 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008511
8512 uint32_t Rd; // the destination register
8513 uint32_t Rn; // the first operand
8514 uint32_t Rm; // the second operand
8515 bool setflags;
8516 ARM_ShifterType shift_t;
8517 uint32_t shift_n; // the shift applied to the value read from Rm
8518 switch (encoding) {
8519 case eEncodingT1:
8520 Rd = Bits32(opcode, 11, 8);
8521 Rn = Bits32(opcode, 19, 16);
8522 Rm = Bits32(opcode, 3, 0);
8523 setflags = BitIsSet(opcode, 20);
8524 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8525 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8526 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8527 return false;
8528 break;
8529 case eEncodingA1:
8530 Rd = Bits32(opcode, 15, 12);
8531 Rn = Bits32(opcode, 19, 16);
8532 Rm = Bits32(opcode, 3, 0);
8533 setflags = BitIsSet(opcode, 20);
8534 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008535
Johnny Chened32e7c2011-02-22 23:42:58 +00008536 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008537 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008538 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008539 break;
8540 default:
8541 return false;
8542 }
8543 // Read the register value from register Rn.
8544 uint32_t val1 = ReadCoreReg(Rn, &success);
8545 if (!success)
8546 return false;
8547
8548 // Read the register value from register Rm.
8549 uint32_t val2 = ReadCoreReg(Rm, &success);
8550 if (!success)
8551 return false;
8552
8553 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8554 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8555
8556 EmulateInstruction::Context context;
8557 context.type = EmulateInstruction::eContextImmediate;
8558 context.SetNoArgs();
8559 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8560 return false;
8561
8562 return true;
8563}
8564
Johnny Chen90e607b2011-02-23 00:07:09 +00008565// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8566// an immediate value, and writes the result to the destination register. It can optionally update the condition
8567// flags based on the result.
8568bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008569EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008570{
8571#if 0
8572 // ARM pseudo code...
8573 if ConditionPassed() then
8574 EncodingSpecificOperations();
8575 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8576 if d == 15 then
8577 ALUWritePC(result); // setflags is always FALSE here
8578 else
8579 R[d] = result;
8580 if setflags then
8581 APSR.N = result<31>;
8582 APSR.Z = IsZeroBit(result);
8583 APSR.C = carry;
8584 APSR.V = overflow;
8585#endif
8586
8587 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008588
8589 uint32_t Rd; // the destination register
8590 uint32_t Rn; // the first operand
8591 bool setflags;
8592 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8593 switch (encoding) {
8594 case eEncodingA1:
8595 Rd = Bits32(opcode, 15, 12);
8596 Rn = Bits32(opcode, 19, 16);
8597 setflags = BitIsSet(opcode, 20);
8598 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008599
Johnny Chen90e607b2011-02-23 00:07:09 +00008600 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008601 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008602 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008603 break;
8604 default:
8605 return false;
8606 }
8607 // Read the register value from the operand register Rn.
8608 uint32_t reg_val = ReadCoreReg(Rn, &success);
8609 if (!success)
8610 return false;
8611
8612 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8613
8614 EmulateInstruction::Context context;
8615 context.type = EmulateInstruction::eContextImmediate;
8616 context.SetNoArgs ();
8617
8618 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8619 return false;
8620
8621 return true;
8622}
8623
8624// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8625// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8626// condition flags based on the result.
8627bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008628EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008629{
8630#if 0
8631 // ARM pseudo code...
8632 if ConditionPassed() then
8633 EncodingSpecificOperations();
8634 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8635 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8636 if d == 15 then
8637 ALUWritePC(result); // setflags is always FALSE here
8638 else
8639 R[d] = result;
8640 if setflags then
8641 APSR.N = result<31>;
8642 APSR.Z = IsZeroBit(result);
8643 APSR.C = carry;
8644 APSR.V = overflow;
8645#endif
8646
8647 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008648
8649 uint32_t Rd; // the destination register
8650 uint32_t Rn; // the first operand
8651 uint32_t Rm; // the second operand
8652 bool setflags;
8653 ARM_ShifterType shift_t;
8654 uint32_t shift_n; // the shift applied to the value read from Rm
8655 switch (encoding) {
8656 case eEncodingA1:
8657 Rd = Bits32(opcode, 15, 12);
8658 Rn = Bits32(opcode, 19, 16);
8659 Rm = Bits32(opcode, 3, 0);
8660 setflags = BitIsSet(opcode, 20);
8661 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008662
Johnny Chen90e607b2011-02-23 00:07:09 +00008663 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008664 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008665 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008666 break;
8667 default:
8668 return false;
8669 }
8670 // Read the register value from register Rn.
8671 uint32_t val1 = ReadCoreReg(Rn, &success);
8672 if (!success)
8673 return false;
8674
8675 // Read the register value from register Rm.
8676 uint32_t val2 = ReadCoreReg(Rm, &success);
8677 if (!success)
8678 return false;
8679
8680 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8681 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8682
8683 EmulateInstruction::Context context;
8684 context.type = EmulateInstruction::eContextImmediate;
8685 context.SetNoArgs();
8686 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8687 return false;
8688
8689 return true;
8690}
8691
Johnny Chen9b381772011-02-23 01:01:21 +00008692// Subtract with Carry (immediate) subtracts an immediate value and the value of
8693// NOT (Carry flag) from a register value, and writes the result to the destination register.
8694// It can optionally update the condition flags based on the result.
8695bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008696EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008697{
8698#if 0
8699 // ARM pseudo code...
8700 if ConditionPassed() then
8701 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008702 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008703 if d == 15 then // Can only occur for ARM encoding
8704 ALUWritePC(result); // setflags is always FALSE here
8705 else
8706 R[d] = result;
8707 if setflags then
8708 APSR.N = result<31>;
8709 APSR.Z = IsZeroBit(result);
8710 APSR.C = carry;
8711 APSR.V = overflow;
8712#endif
8713
8714 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008715
8716 uint32_t Rd; // the destination register
8717 uint32_t Rn; // the first operand
8718 bool setflags;
8719 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8720 switch (encoding) {
8721 case eEncodingT1:
8722 Rd = Bits32(opcode, 11, 8);
8723 Rn = Bits32(opcode, 19, 16);
8724 setflags = BitIsSet(opcode, 20);
8725 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8726 if (BadReg(Rd) || BadReg(Rn))
8727 return false;
8728 break;
8729 case eEncodingA1:
8730 Rd = Bits32(opcode, 15, 12);
8731 Rn = Bits32(opcode, 19, 16);
8732 setflags = BitIsSet(opcode, 20);
8733 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008734
Johnny Chen9b381772011-02-23 01:01:21 +00008735 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008736 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008737 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008738 break;
8739 default:
8740 return false;
8741 }
8742 // Read the register value from the operand register Rn.
8743 uint32_t reg_val = ReadCoreReg(Rn, &success);
8744 if (!success)
8745 return false;
8746
8747 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8748
8749 EmulateInstruction::Context context;
8750 context.type = EmulateInstruction::eContextImmediate;
8751 context.SetNoArgs ();
8752
8753 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8754 return false;
8755
8756 return true;
8757}
8758
8759// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8760// NOT (Carry flag) from a register value, and writes the result to the destination register.
8761// It can optionally update the condition flags based on the result.
8762bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008763EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008764{
8765#if 0
8766 // ARM pseudo code...
8767 if ConditionPassed() then
8768 EncodingSpecificOperations();
8769 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8770 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8771 if d == 15 then // Can only occur for ARM encoding
8772 ALUWritePC(result); // setflags is always FALSE here
8773 else
8774 R[d] = result;
8775 if setflags then
8776 APSR.N = result<31>;
8777 APSR.Z = IsZeroBit(result);
8778 APSR.C = carry;
8779 APSR.V = overflow;
8780#endif
8781
8782 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008783
8784 uint32_t Rd; // the destination register
8785 uint32_t Rn; // the first operand
8786 uint32_t Rm; // the second operand
8787 bool setflags;
8788 ARM_ShifterType shift_t;
8789 uint32_t shift_n; // the shift applied to the value read from Rm
8790 switch (encoding) {
8791 case eEncodingT1:
8792 Rd = Rn = Bits32(opcode, 2, 0);
8793 Rm = Bits32(opcode, 5, 3);
8794 setflags = !InITBlock();
8795 shift_t = SRType_LSL;
8796 shift_n = 0;
8797 break;
8798 case eEncodingT2:
8799 Rd = Bits32(opcode, 11, 8);
8800 Rn = Bits32(opcode, 19, 16);
8801 Rm = Bits32(opcode, 3, 0);
8802 setflags = BitIsSet(opcode, 20);
8803 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8804 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8805 return false;
8806 break;
8807 case eEncodingA1:
8808 Rd = Bits32(opcode, 15, 12);
8809 Rn = Bits32(opcode, 19, 16);
8810 Rm = Bits32(opcode, 3, 0);
8811 setflags = BitIsSet(opcode, 20);
8812 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008813
Johnny Chen9b381772011-02-23 01:01:21 +00008814 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008815 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008816 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008817 break;
8818 default:
8819 return false;
8820 }
8821 // Read the register value from register Rn.
8822 uint32_t val1 = ReadCoreReg(Rn, &success);
8823 if (!success)
8824 return false;
8825
8826 // Read the register value from register Rm.
8827 uint32_t val2 = ReadCoreReg(Rm, &success);
8828 if (!success)
8829 return false;
8830
8831 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8832 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8833
8834 EmulateInstruction::Context context;
8835 context.type = EmulateInstruction::eContextImmediate;
8836 context.SetNoArgs();
8837 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8838 return false;
8839
8840 return true;
8841}
8842
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008843// This instruction subtracts an immediate value from a register value, and writes the result
8844// to the destination register. It can optionally update the condition flags based on the result.
8845bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008846EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008847{
8848#if 0
8849 // ARM pseudo code...
8850 if ConditionPassed() then
8851 EncodingSpecificOperations();
8852 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8853 R[d] = result;
8854 if setflags then
8855 APSR.N = result<31>;
8856 APSR.Z = IsZeroBit(result);
8857 APSR.C = carry;
8858 APSR.V = overflow;
8859#endif
8860
8861 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008862
8863 uint32_t Rd; // the destination register
8864 uint32_t Rn; // the first operand
8865 bool setflags;
8866 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8867 switch (encoding) {
8868 case eEncodingT1:
8869 Rd = Bits32(opcode, 2, 0);
8870 Rn = Bits32(opcode, 5, 3);
8871 setflags = !InITBlock();
8872 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8873 break;
8874 case eEncodingT2:
8875 Rd = Rn = Bits32(opcode, 10, 8);
8876 setflags = !InITBlock();
8877 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8878 break;
8879 case eEncodingT3:
8880 Rd = Bits32(opcode, 11, 8);
8881 Rn = Bits32(opcode, 19, 16);
8882 setflags = BitIsSet(opcode, 20);
8883 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8884
8885 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8886 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008887 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008888
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008889 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008890 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008891 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008892
8893 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8894 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8895 return false;
8896 break;
8897 case eEncodingT4:
8898 Rd = Bits32(opcode, 11, 8);
8899 Rn = Bits32(opcode, 19, 16);
8900 setflags = BitIsSet(opcode, 20);
8901 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8902
8903 // if Rn == '1111' then SEE ADR;
8904 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008905 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008906
8907 // if Rn == '1101' then SEE SUB (SP minus immediate);
8908 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008909 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008910
8911 if (BadReg(Rd))
8912 return false;
8913 break;
8914 default:
8915 return false;
8916 }
8917 // Read the register value from the operand register Rn.
8918 uint32_t reg_val = ReadCoreReg(Rn, &success);
8919 if (!success)
8920 return false;
8921
8922 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8923
8924 EmulateInstruction::Context context;
8925 context.type = EmulateInstruction::eContextImmediate;
8926 context.SetNoArgs ();
8927
8928 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8929 return false;
8930
8931 return true;
8932}
8933
8934// This instruction subtracts an immediate value from a register value, and writes the result
8935// to the destination register. It can optionally update the condition flags based on the result.
8936bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008937EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008938{
8939#if 0
8940 // ARM pseudo code...
8941 if ConditionPassed() then
8942 EncodingSpecificOperations();
8943 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8944 if d == 15 then
8945 ALUWritePC(result); // setflags is always FALSE here
8946 else
8947 R[d] = result;
8948 if setflags then
8949 APSR.N = result<31>;
8950 APSR.Z = IsZeroBit(result);
8951 APSR.C = carry;
8952 APSR.V = overflow;
8953#endif
8954
8955 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008956
8957 uint32_t Rd; // the destination register
8958 uint32_t Rn; // the first operand
8959 bool setflags;
8960 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8961 switch (encoding) {
8962 case eEncodingA1:
8963 Rd = Bits32(opcode, 15, 12);
8964 Rn = Bits32(opcode, 19, 16);
8965 setflags = BitIsSet(opcode, 20);
8966 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8967
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008968 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008969 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008970 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008971
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008972 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008973 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008974 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008975
8976 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008977 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008978 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008979 break;
8980 default:
8981 return false;
8982 }
8983 // Read the register value from the operand register Rn.
8984 uint32_t reg_val = ReadCoreReg(Rn, &success);
8985 if (!success)
8986 return false;
8987
8988 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8989
8990 EmulateInstruction::Context context;
8991 context.type = EmulateInstruction::eContextImmediate;
8992 context.SetNoArgs ();
8993
8994 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8995 return false;
8996
8997 return true;
8998}
8999
Johnny Chen2115b412011-02-21 23:42:44 +00009000// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9001// immediate value. It updates the condition flags based on the result, and discards the result.
9002bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009003EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009004{
9005#if 0
9006 // ARM pseudo code...
9007 if ConditionPassed() then
9008 EncodingSpecificOperations();
9009 result = R[n] EOR imm32;
9010 APSR.N = result<31>;
9011 APSR.Z = IsZeroBit(result);
9012 APSR.C = carry;
9013 // APSR.V unchanged
9014#endif
9015
9016 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009017
Greg Clayton7bc39082011-03-24 23:53:38 +00009018 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009019 {
9020 uint32_t Rn;
9021 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9022 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9023 switch (encoding)
9024 {
9025 case eEncodingT1:
9026 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009027 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009028 if (BadReg(Rn))
9029 return false;
9030 break;
9031 case eEncodingA1:
9032 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009033 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009034 break;
9035 default:
9036 return false;
9037 }
9038
9039 // Read the first operand.
9040 uint32_t val1 = ReadCoreReg(Rn, &success);
9041 if (!success)
9042 return false;
9043
9044 uint32_t result = val1 ^ imm32;
9045
9046 EmulateInstruction::Context context;
9047 context.type = EmulateInstruction::eContextImmediate;
9048 context.SetNoArgs ();
9049
9050 if (!WriteFlags(context, result, carry))
9051 return false;
9052 }
9053 return true;
9054}
9055
9056// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9057// optionally-shifted register value. It updates the condition flags based on the result, and discards
9058// the result.
9059bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009060EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009061{
9062#if 0
9063 // ARM pseudo code...
9064 if ConditionPassed() then
9065 EncodingSpecificOperations();
9066 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9067 result = R[n] EOR shifted;
9068 APSR.N = result<31>;
9069 APSR.Z = IsZeroBit(result);
9070 APSR.C = carry;
9071 // APSR.V unchanged
9072#endif
9073
9074 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009075
Greg Clayton7bc39082011-03-24 23:53:38 +00009076 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009077 {
9078 uint32_t Rn, Rm;
9079 ARM_ShifterType shift_t;
9080 uint32_t shift_n; // the shift applied to the value read from Rm
9081 uint32_t carry;
9082 switch (encoding)
9083 {
9084 case eEncodingT1:
9085 Rn = Bits32(opcode, 19, 16);
9086 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009087 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009088 if (BadReg(Rn) || BadReg(Rm))
9089 return false;
9090 break;
9091 case eEncodingA1:
9092 Rn = Bits32(opcode, 19, 16);
9093 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009094 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009095 break;
9096 default:
9097 return false;
9098 }
9099
9100 // Read the first operand.
9101 uint32_t val1 = ReadCoreReg(Rn, &success);
9102 if (!success)
9103 return false;
9104
9105 // Read the second operand.
9106 uint32_t val2 = ReadCoreReg(Rm, &success);
9107 if (!success)
9108 return false;
9109
9110 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9111 uint32_t result = val1 ^ shifted;
9112
9113 EmulateInstruction::Context context;
9114 context.type = EmulateInstruction::eContextImmediate;
9115 context.SetNoArgs ();
9116
9117 if (!WriteFlags(context, result, carry))
9118 return false;
9119 }
9120 return true;
9121}
9122
Johnny Chende3cce32011-02-21 21:24:49 +00009123// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9124// It updates the condition flags based on the result, and discards the result.
9125bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009126EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009127{
9128#if 0
9129 // ARM pseudo code...
9130 if ConditionPassed() then
9131 EncodingSpecificOperations();
9132 result = R[n] AND imm32;
9133 APSR.N = result<31>;
9134 APSR.Z = IsZeroBit(result);
9135 APSR.C = carry;
9136 // APSR.V unchanged
9137#endif
9138
9139 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009140
Greg Clayton7bc39082011-03-24 23:53:38 +00009141 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009142 {
9143 uint32_t Rn;
9144 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9145 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9146 switch (encoding)
9147 {
9148 case eEncodingT1:
9149 Rn = Bits32(opcode, 19, 16);
9150 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9151 if (BadReg(Rn))
9152 return false;
9153 break;
9154 case eEncodingA1:
9155 Rn = Bits32(opcode, 19, 16);
9156 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9157 break;
9158 default:
9159 return false;
9160 }
9161
9162 // Read the first operand.
9163 uint32_t val1 = ReadCoreReg(Rn, &success);
9164 if (!success)
9165 return false;
9166
9167 uint32_t result = val1 & imm32;
9168
9169 EmulateInstruction::Context context;
9170 context.type = EmulateInstruction::eContextImmediate;
9171 context.SetNoArgs ();
9172
9173 if (!WriteFlags(context, result, carry))
9174 return false;
9175 }
9176 return true;
9177}
9178
9179// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9180// It updates the condition flags based on the result, and discards the result.
9181bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009182EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009183{
9184#if 0
9185 // ARM pseudo code...
9186 if ConditionPassed() then
9187 EncodingSpecificOperations();
9188 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9189 result = R[n] AND shifted;
9190 APSR.N = result<31>;
9191 APSR.Z = IsZeroBit(result);
9192 APSR.C = carry;
9193 // APSR.V unchanged
9194#endif
9195
9196 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009197
Greg Clayton7bc39082011-03-24 23:53:38 +00009198 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009199 {
9200 uint32_t Rn, Rm;
9201 ARM_ShifterType shift_t;
9202 uint32_t shift_n; // the shift applied to the value read from Rm
9203 uint32_t carry;
9204 switch (encoding)
9205 {
9206 case eEncodingT1:
9207 Rn = Bits32(opcode, 2, 0);
9208 Rm = Bits32(opcode, 5, 3);
9209 shift_t = SRType_LSL;
9210 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009211 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009212 case eEncodingT2:
9213 Rn = Bits32(opcode, 19, 16);
9214 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009215 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009216 if (BadReg(Rn) || BadReg(Rm))
9217 return false;
9218 break;
9219 case eEncodingA1:
9220 Rn = Bits32(opcode, 19, 16);
9221 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009222 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009223 break;
9224 default:
9225 return false;
9226 }
9227
9228 // Read the first operand.
9229 uint32_t val1 = ReadCoreReg(Rn, &success);
9230 if (!success)
9231 return false;
9232
9233 // Read the second operand.
9234 uint32_t val2 = ReadCoreReg(Rm, &success);
9235 if (!success)
9236 return false;
9237
9238 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9239 uint32_t result = val1 & shifted;
9240
9241 EmulateInstruction::Context context;
9242 context.type = EmulateInstruction::eContextImmediate;
9243 context.SetNoArgs ();
9244
9245 if (!WriteFlags(context, result, carry))
9246 return false;
9247 }
9248 return true;
9249}
Caroline Ticed05b4902011-03-29 21:24:06 +00009250
9251// A8.6.216 SUB (SP minus register)
9252bool
9253EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9254{
9255#if 0
9256 if ConditionPassed() then
9257 EncodingSpecificOperations();
9258 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9259 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), 1’);
9260 if d == 15 then // Can only occur for ARM encoding
9261 ALUWritePC(result); // setflags is always FALSE here
9262 else
9263 R[d] = result;
9264 if setflags then
9265 APSR.N = result<31>;
9266 APSR.Z = IsZeroBit(result);
9267 APSR.C = carry;
9268 APSR.V = overflow;
9269#endif
9270
9271 bool success = false;
9272
9273 if (ConditionPassed(opcode))
9274 {
9275 uint32_t d;
9276 uint32_t m;
9277 bool setflags;
9278 ARM_ShifterType shift_t;
9279 uint32_t shift_n;
9280
9281 switch (encoding)
9282 {
9283 case eEncodingT1:
9284 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9285 d = Bits32 (opcode, 11, 8);
9286 m = Bits32 (opcode, 3, 0);
9287 setflags = BitIsSet (opcode, 20);
9288
9289 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9290 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9291
9292 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9293 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9294 return false;
9295
9296 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9297 if ((d == 15) || BadReg (m))
9298 return false;
9299 break;
9300
9301 case eEncodingA1:
Caroline Ticed05b4902011-03-29 21:24:06 +00009302 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9303 d = Bits32 (opcode, 15, 12);
9304 m = Bits32 (opcode, 3, 0);
9305 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009306
9307 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9308 if (d == 15 && setflags)
9309 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009310
9311 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9312 shift_n = DecodeImmShiftARM (opcode, shift_t);
9313 break;
9314
9315 default:
9316 return false;
9317 }
9318
9319 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9320 uint32_t Rm = ReadCoreReg (m, &success);
9321 if (!success)
9322 return false;
9323
9324 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9325
9326 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’);
9327 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9328 if (!success)
9329 return false;
9330
9331 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9332
9333 EmulateInstruction::Context context;
9334 context.type = eContextSubtraction;
9335 Register sp_reg;
Greg Clayton888a7332011-04-26 04:39:08 +00009336 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Caroline Ticed05b4902011-03-29 21:24:06 +00009337 Register dwarf_reg;
9338 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
9339 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9340
Caroline Ticeef440002011-03-30 05:40:56 +00009341 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009342 return false;
9343 }
9344 return true;
9345}
9346
9347
9348// A8.6.7 ADD (register-shifted register)
9349bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009350EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009351{
9352#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009353 if ConditionPassed() then
9354 EncodingSpecificOperations();
9355 shift_n = UInt(R[s]<7:0>);
9356 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9357 (result, carry, overflow) = AddWithCarry(R[n], shifted, 0’);
9358 R[d] = result;
9359 if setflags then
9360 APSR.N = result<31>;
9361 APSR.Z = IsZeroBit(result);
9362 APSR.C = carry;
9363 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009364#endif
9365
Caroline Ticec08ed382011-03-29 23:03:16 +00009366 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009367
9368 if (ConditionPassed(opcode))
9369 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009370 uint32_t d;
9371 uint32_t n;
9372 uint32_t m;
9373 uint32_t s;
9374 bool setflags;
9375 ARM_ShifterType shift_t;
9376
Caroline Ticed05b4902011-03-29 21:24:06 +00009377 switch (encoding)
9378 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009379 case eEncodingA1:
9380 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9381 d = Bits32 (opcode, 15, 12);
9382 n = Bits32 (opcode, 19, 16);
9383 m = Bits32 (opcode, 3, 0);
9384 s = Bits32 (opcode, 11, 8);
9385
9386 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type);
9387 setflags = BitIsSet (opcode, 20);
9388 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9389
9390 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9391 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9392 return false;
9393 break;
9394
9395 default:
9396 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009397 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009398
9399 // shift_n = UInt(R[s]<7:0>);
9400 uint32_t Rs = ReadCoreReg (s, &success);
9401 if (!success)
9402 return false;
9403
9404 uint32_t shift_n = Bits32 (Rs, 7, 0);
9405
9406 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9407 uint32_t Rm = ReadCoreReg (m, &success);
9408 if (!success)
9409 return false;
9410
9411 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9412
9413 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’);
9414 uint32_t Rn = ReadCoreReg (n, &success);
9415 if (!success)
9416 return false;
9417
9418 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9419
9420 // R[d] = result;
9421 EmulateInstruction::Context context;
9422 context.type = eContextAddition;
9423 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009424 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
Caroline Ticec08ed382011-03-29 23:03:16 +00009425 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009426 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009427
9428 context.SetRegisterRegisterOperands (reg_n, reg_m);
9429
9430 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9431 return false;
9432
9433 // if setflags then
9434 // APSR.N = result<31>;
9435 // APSR.Z = IsZeroBit(result);
9436 // APSR.C = carry;
9437 // APSR.V = overflow;
9438 if (setflags)
9439 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009440 }
9441 return true;
9442}
9443
9444// A8.6.213 SUB (register)
9445bool
9446EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9447{
9448#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009449 if ConditionPassed() then
9450 EncodingSpecificOperations();
9451 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9452 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), 1’);
9453 if d == 15 then // Can only occur for ARM encoding
9454 ALUWritePC(result); // setflags is always FALSE here
9455 else
9456 R[d] = result;
9457 if setflags then
9458 APSR.N = result<31>;
9459 APSR.Z = IsZeroBit(result);
9460 APSR.C = carry;
9461 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009462#endif
9463
Caroline Tice4cccd532011-03-29 23:44:20 +00009464 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009465
9466 if (ConditionPassed(opcode))
9467 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009468 uint32_t d;
9469 uint32_t n;
9470 uint32_t m;
9471 bool setflags;
9472 ARM_ShifterType shift_t;
9473 uint32_t shift_n;
9474
Caroline Ticed05b4902011-03-29 21:24:06 +00009475 switch (encoding)
9476 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009477 case eEncodingT1:
9478 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9479 d = Bits32 (opcode, 2, 0);
9480 n = Bits32 (opcode, 5, 3);
9481 m = Bits32 (opcode, 8, 6);
9482 setflags = !InITBlock();
9483
9484 // (shift_t, shift_n) = (SRType_LSL, 0);
9485 shift_t = SRType_LSL;
9486 shift_n = 0;
9487
9488 break;
9489
9490 case eEncodingT2:
9491 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register);
9492 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9493 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9494 d = Bits32 (opcode, 11, 8);
9495 n = Bits32 (opcode, 19, 16);
9496 m = Bits32 (opcode, 3, 0);
9497 setflags = BitIsSet (opcode, 20);
9498
9499 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9500 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9501
9502 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9503 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9504 return false;
9505
9506 break;
9507
9508 case eEncodingA1:
Caroline Tice4cccd532011-03-29 23:44:20 +00009509 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9510 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9511 d = Bits32 (opcode, 15, 12);
9512 n = Bits32 (opcode, 19, 16);
9513 m = Bits32 (opcode, 3, 0);
9514 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009515
9516 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9517 if ((d == 15) && setflags)
9518 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009519
9520 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9521 shift_n = DecodeImmShiftARM (opcode, shift_t);
9522
9523 break;
9524
9525 default:
9526 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009527 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009528
9529 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9530 uint32_t Rm = ReadCoreReg (m, &success);
9531 if (!success)
9532 return false;
9533
9534 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9535
9536 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’);
9537 uint32_t Rn = ReadCoreReg (n, &success);
9538 if (!success)
9539 return false;
9540
9541 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9542
9543 // if d == 15 then // Can only occur for ARM encoding
9544 // ALUWritePC(result); // setflags is always FALSE here
9545 // else
9546 // R[d] = result;
9547 // if setflags then
9548 // APSR.N = result<31>;
9549 // APSR.Z = IsZeroBit(result);
9550 // APSR.C = carry;
9551 // APSR.V = overflow;
9552
9553 EmulateInstruction::Context context;
9554 context.type = eContextSubtraction;
9555 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009556 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Tice4cccd532011-03-29 23:44:20 +00009557 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009558 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009559 context.SetRegisterRegisterOperands (reg_n, reg_m);
9560
Caroline Ticeef440002011-03-30 05:40:56 +00009561 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009562 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009563 }
9564 return true;
9565}
Caroline Tice4cccd532011-03-29 23:44:20 +00009566
Caroline Ticed05b4902011-03-29 21:24:06 +00009567// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009568// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9569// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009570bool
9571EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9572{
9573#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009574 if ConditionPassed() then
9575 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9576 address = R[n] + imm32;
9577 if ExclusiveMonitorsPass(address,4) then
9578 MemA[address,4] = R[t];
9579 R[d] = 0;
9580 else
9581 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009582#endif
9583
Caroline Tice5168b6c2011-03-30 05:15:46 +00009584 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009585
9586 if (ConditionPassed(opcode))
9587 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009588 uint32_t d;
9589 uint32_t t;
9590 uint32_t n;
9591 uint32_t imm32;
9592 const uint32_t addr_byte_size = GetAddressByteSize();
9593
Caroline Ticed05b4902011-03-29 21:24:06 +00009594 switch (encoding)
9595 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009596 case eEncodingT1:
9597 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9598 d = Bits32 (opcode, 11, 8);
9599 t = Bits32 (opcode, 15, 12);
9600 n = Bits32 (opcode, 19, 16);
9601 imm32 = Bits32 (opcode, 7, 0) << 2;
9602
9603 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9604 if (BadReg (d) || BadReg (t) || (n == 15))
9605 return false;
9606
9607 // if d == n || d == t then UNPREDICTABLE;
9608 if ((d == n) || (d == t))
9609 return false;
9610
9611 break;
9612
9613 case eEncodingA1:
9614 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9615 d = Bits32 (opcode, 15, 12);
9616 t = Bits32 (opcode, 3, 0);
9617 n = Bits32 (opcode, 19, 16);
9618 imm32 = 0;
9619
9620 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9621 if ((d == 15) || (t == 15) || (n == 15))
9622 return false;
9623
9624 // if d == n || d == t then UNPREDICTABLE;
9625 if ((d == n) || (d == t))
9626 return false;
9627
9628 break;
9629
9630 default:
9631 return false;
9632 }
9633
9634 // address = R[n] + imm32;
9635 uint32_t Rn = ReadCoreReg (n, &success);
9636 if (!success)
9637 return false;
9638
9639 addr_t address = Rn + imm32;
9640
9641 Register base_reg;
9642 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9643 Register data_reg;
9644 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
9645 EmulateInstruction::Context context;
9646 context.type = eContextRegisterStore;
9647 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9648
9649 // if ExclusiveMonitorsPass(address,4) then
9650 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9651 // always return true.
9652 if (true)
9653 {
9654 // MemA[address,4] = R[t];
9655 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9656 if (!success)
9657 return false;
9658
9659 if (!MemAWrite (context, address, Rt, addr_byte_size))
9660 return false;
9661
9662 // R[d] = 0;
9663 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9664 return false;
9665 }
9666 else
9667 {
9668 // R[d] = 1;
9669 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9670 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009671 }
9672 }
9673 return true;
9674}
9675
9676// A8.6.197 STRB (immediate, ARM)
9677bool
9678EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9679{
9680#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009681 if ConditionPassed() then
9682 EncodingSpecificOperations();
9683 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9684 address = if index then offset_addr else R[n];
9685 MemU[address,1] = R[t]<7:0>;
9686 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009687#endif
9688
Caroline Ticeef440002011-03-30 05:40:56 +00009689 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009690
9691 if (ConditionPassed(opcode))
9692 {
Caroline Ticeef440002011-03-30 05:40:56 +00009693 uint32_t t;
9694 uint32_t n;
9695 uint32_t imm32;
9696 bool index;
9697 bool add;
9698 bool wback;
9699
Caroline Ticed05b4902011-03-29 21:24:06 +00009700 switch (encoding)
9701 {
Caroline Ticeef440002011-03-30 05:40:56 +00009702 case eEncodingA1:
9703 // if P == ‘0’ && W == ‘1’ then SEE STRBT;
9704 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9705 t = Bits32 (opcode, 15, 12);
9706 n = Bits32 (opcode, 19, 16);
9707 imm32 = Bits32 (opcode, 11, 0);
9708
9709 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9710 index = BitIsSet (opcode, 24);
9711 add = BitIsSet (opcode, 23);
9712 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9713
9714 // if t == 15 then UNPREDICTABLE;
9715 if (t == 15)
9716 return false;
9717
9718 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9719 if (wback && ((n == 15) || (n == t)))
9720 return false;
9721
9722 break;
9723
9724 default:
9725 return false;
9726 }
9727
9728 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9729 uint32_t Rn = ReadCoreReg (n, &success);
9730 if (!success)
9731 return false;
9732
9733 addr_t offset_addr;
9734 if (add)
9735 offset_addr = Rn + imm32;
9736 else
9737 offset_addr = Rn - imm32;
9738
9739 // address = if index then offset_addr else R[n];
9740 addr_t address;
9741 if (index)
9742 address = offset_addr;
9743 else
9744 address = Rn;
9745
9746 // MemU[address,1] = R[t]<7:0>;
9747 uint32_t Rt = ReadCoreReg (t, &success);
9748 if (!success)
9749 return false;
9750
9751 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009752 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticeef440002011-03-30 05:40:56 +00009753 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009754 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticeef440002011-03-30 05:40:56 +00009755 EmulateInstruction::Context context;
9756 context.type = eContextRegisterStore;
9757 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9758
9759 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9760 return false;
9761
9762 // if wback then R[n] = offset_addr;
9763 if (wback)
9764 {
Caroline Tice523c5542011-04-13 00:42:12 +00009765 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009766 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009767 }
9768 }
9769 return true;
9770}
9771
9772// A8.6.194 STR (immediate, ARM)
9773bool
9774EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9775{
9776#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009777 if ConditionPassed() then
9778 EncodingSpecificOperations();
9779 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9780 address = if index then offset_addr else R[n];
9781 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9782 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009783#endif
9784
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009785 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009786
9787 if (ConditionPassed(opcode))
9788 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009789 uint32_t t;
9790 uint32_t n;
9791 uint32_t imm32;
9792 bool index;
9793 bool add;
9794 bool wback;
9795
9796 const uint32_t addr_byte_size = GetAddressByteSize();
9797
Caroline Ticed05b4902011-03-29 21:24:06 +00009798 switch (encoding)
9799 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009800 case eEncodingA1:
9801 // if P == ‘0’ && W == ‘1’ then SEE STRT;
9802 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH;
9803 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9804 t = Bits32 (opcode, 15, 12);
9805 n = Bits32 (opcode, 19, 16);
9806 imm32 = Bits32 (opcode, 11, 0);
9807
9808 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9809 index = BitIsSet (opcode, 24);
9810 add = BitIsSet (opcode, 23);
9811 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9812
9813 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9814 if (wback && ((n == 15) || (n == t)))
9815 return false;
9816
9817 break;
9818
9819 default:
9820 return false;
9821 }
9822
9823 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9824 uint32_t Rn = ReadCoreReg (n, &success);
9825 if (!success)
9826 return false;
9827
9828 addr_t offset_addr;
9829 if (add)
9830 offset_addr = Rn + imm32;
9831 else
9832 offset_addr = Rn - imm32;
9833
9834 // address = if index then offset_addr else R[n];
9835 addr_t address;
9836 if (index)
9837 address = offset_addr;
9838 else
9839 address = Rn;
9840
9841 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009842 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009843 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009844 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009845 EmulateInstruction::Context context;
9846 context.type = eContextRegisterStore;
9847 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9848
9849 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9850 uint32_t Rt = ReadCoreReg (t, &success);
9851 if (!success)
9852 return false;
9853
9854 if (t == 15)
9855 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009856 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009857 if (!success)
9858 return false;
9859
9860 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9861 return false;
9862 }
9863 else
9864 {
9865 if (!MemUWrite (context, address, Rt, addr_byte_size))
9866 return false;
9867 }
9868
9869 // if wback then R[n] = offset_addr;
9870 if (wback)
9871 {
9872 context.type = eContextAdjustBaseRegister;
9873 context.SetImmediate (offset_addr);
9874
9875 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9876 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009877 }
9878 }
9879 return true;
9880}
9881
Caroline Ticed05b4902011-03-29 21:24:06 +00009882// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009883// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9884// 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 +00009885bool
9886EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9887{
9888#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009889 if ConditionPassed() then
9890 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9891 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9892 address = if index then offset_addr else R[n];
9893 R[t] = MemA[address,4];
9894 R[t2] = MemA[address+4,4];
9895 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009896#endif
9897
Caroline Tice1697dd72011-03-30 17:11:45 +00009898 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009899
9900 if (ConditionPassed(opcode))
9901 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009902 uint32_t t;
9903 uint32_t t2;
9904 uint32_t n;
9905 uint32_t imm32;
9906 bool index;
9907 bool add;
9908 bool wback;
9909
Caroline Ticed05b4902011-03-29 21:24:06 +00009910 switch (encoding)
9911 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009912 case eEncodingT1:
9913 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
9914 //if Rn == ‘1111’ then SEE LDRD (literal);
9915 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9916 t = Bits32 (opcode, 15, 12);
9917 t2 = Bits32 (opcode, 11, 8);
9918 n = Bits32 (opcode, 19, 16);
9919 imm32 = Bits32 (opcode, 7, 0) << 2;
9920
9921 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
9922 index = BitIsSet (opcode, 24);
9923 add = BitIsSet (opcode, 23);
9924 wback = BitIsSet (opcode, 21);
9925
9926 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9927 if (wback && ((n == t) || (n == t2)))
9928 return false;
9929
9930 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9931 if (BadReg (t) || BadReg (t2) || (t == t2))
9932 return false;
9933
9934 break;
9935
9936 case eEncodingA1:
9937 //if Rn == ‘1111’ then SEE LDRD (literal);
9938 //if Rt<0> == ‘1’ then UNPREDICTABLE;
9939 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9940 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009941 if (BitIsSet (t, 0))
9942 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009943 t2 = t + 1;
9944 n = Bits32 (opcode, 19, 16);
9945 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9946
9947 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9948 index = BitIsSet (opcode, 24);
9949 add = BitIsSet (opcode, 23);
9950 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9951
9952 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
9953 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9954 return false;
9955
9956 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9957 if (wback && ((n == t) || (n == t2)))
9958 return false;
9959
9960 //if t2 == 15 then UNPREDICTABLE;
9961 if (t2 == 15)
9962 return false;
9963
9964 break;
9965
9966 default:
9967 return false;
9968 }
9969
9970 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9971 uint32_t Rn = ReadCoreReg (n, &success);
9972 if (!success)
9973 return false;
9974
9975 addr_t offset_addr;
9976 if (add)
9977 offset_addr = Rn + imm32;
9978 else
9979 offset_addr = Rn - imm32;
9980
9981 //address = if index then offset_addr else R[n];
9982 addr_t address;
9983 if (index)
9984 address = offset_addr;
9985 else
9986 address = Rn;
9987
9988 //R[t] = MemA[address,4];
9989 Register base_reg;
9990 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9991
9992 EmulateInstruction::Context context;
9993 context.type = eContextRegisterLoad;
9994 context.SetRegisterPlusOffset (base_reg, address - Rn);
9995
9996 const uint32_t addr_byte_size = GetAddressByteSize();
9997 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
9998 if (!success)
9999 return false;
10000
10001 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10002 return false;
10003
10004 //R[t2] = MemA[address+4,4];
10005
10006 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10007 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10008 if (!success)
10009 return false;
10010
10011 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10012 return false;
10013
10014 //if wback then R[n] = offset_addr;
10015 if (wback)
10016 {
10017 context.type = eContextAdjustBaseRegister;
10018 context.SetAddress (offset_addr);
10019
10020 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10021 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010022 }
10023 }
10024 return true;
10025}
10026
Caroline Ticed05b4902011-03-29 21:24:06 +000010027// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010028// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10029// 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 +000010030bool
10031EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10032{
10033#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010034 if ConditionPassed() then
10035 EncodingSpecificOperations();
10036 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10037 address = if index then offset_addr else R[n];
10038 R[t] = MemA[address,4];
10039 R[t2] = MemA[address+4,4];
10040 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010041#endif
10042
Caroline Ticeeab301f2011-03-30 17:54:52 +000010043 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010044
10045 if (ConditionPassed(opcode))
10046 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010047 uint32_t t;
10048 uint32_t t2;
10049 uint32_t n;
10050 uint32_t m;
10051 bool index;
10052 bool add;
10053 bool wback;
10054
Caroline Ticed05b4902011-03-29 21:24:06 +000010055 switch (encoding)
10056 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010057 case eEncodingA1:
10058 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10059 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10060 t = Bits32 (opcode, 15, 12);
10061 if (BitIsSet (t, 0))
10062 return false;
10063 t2 = t + 1;
10064 n = Bits32 (opcode, 19, 16);
10065 m = Bits32 (opcode, 3, 0);
10066
10067 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10068 index = BitIsSet (opcode, 24);
10069 add = BitIsSet (opcode, 23);
10070 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10071
10072 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10073 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10074 return false;
10075
10076 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10077 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10078 return false;
10079
10080 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10081 if (wback && ((n == 15) || (n == t) || (n == t2)))
10082 return false;
10083
10084 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10085 if ((ArchVersion() < 6) && wback && (m == n))
10086 return false;
10087 break;
10088
10089 default:
10090 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010091 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010092
Caroline Ticeeab301f2011-03-30 17:54:52 +000010093 uint32_t Rn = ReadCoreReg (n, &success);
10094 if (!success)
10095 return false;
10096 Register base_reg;
10097 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed05b4902011-03-29 21:24:06 +000010098
Caroline Ticeeab301f2011-03-30 17:54:52 +000010099 uint32_t Rm = ReadCoreReg (m, &success);
10100 if (!success)
10101 return false;
10102 Register offset_reg;
10103 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticed05b4902011-03-29 21:24:06 +000010104
Caroline Ticeeab301f2011-03-30 17:54:52 +000010105 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10106 addr_t offset_addr;
10107 if (add)
10108 offset_addr = Rn + Rm;
10109 else
10110 offset_addr = Rn - Rm;
10111
10112 // address = if index then offset_addr else R[n];
10113 addr_t address;
10114 if (index)
10115 address = offset_addr;
10116 else
10117 address = Rn;
10118
10119 EmulateInstruction::Context context;
10120 context.type = eContextRegisterLoad;
10121 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10122
10123 // R[t] = MemA[address,4];
10124 const uint32_t addr_byte_size = GetAddressByteSize();
10125 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10126 if (!success)
10127 return false;
10128
10129 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10130 return false;
10131
10132 // R[t2] = MemA[address+4,4];
10133
10134 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10135 if (!success)
10136 return false;
10137
10138 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10139 return false;
10140
10141 // if wback then R[n] = offset_addr;
10142 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010143 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010144 context.type = eContextAdjustBaseRegister;
10145 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010146
Caroline Ticeeab301f2011-03-30 17:54:52 +000010147 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10148 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010149 }
10150 }
10151 return true;
10152}
Caroline Ticed05b4902011-03-29 21:24:06 +000010153
10154// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010155// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10156// 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 +000010157bool
10158EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10159{
10160#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010161 if ConditionPassed() then
10162 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10163 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10164 address = if index then offset_addr else R[n];
10165 MemA[address,4] = R[t];
10166 MemA[address+4,4] = R[t2];
10167 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010168#endif
10169
Caroline Tice74467fe2011-03-30 19:02:56 +000010170 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010171
Caroline Tice74467fe2011-03-30 19:02:56 +000010172 if (ConditionPassed(opcode))
10173 {
10174 uint32_t t;
10175 uint32_t t2;
10176 uint32_t n;
10177 uint32_t imm32;
10178 bool index;
10179 bool add;
10180 bool wback;
10181
10182 switch (encoding)
10183 {
10184 case eEncodingT1:
10185 // if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10186 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10187 t = Bits32 (opcode, 15, 12);
10188 t2 = Bits32 (opcode, 11, 8);
10189 n = Bits32 (opcode, 19, 16);
10190 imm32 = Bits32 (opcode, 7, 0) << 2;
10191
10192 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
10193 index = BitIsSet (opcode, 24);
10194 add = BitIsSet (opcode, 23);
10195 wback = BitIsSet (opcode, 21);
10196
10197 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10198 if (wback && ((n == t) || (n == t2)))
10199 return false;
10200
10201 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10202 if ((n == 15) || BadReg (t) || BadReg (t2))
10203 return false;
10204
10205 break;
10206
10207 case eEncodingA1:
10208 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10209 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10210 t = Bits32 (opcode, 15, 12);
10211 if (BitIsSet (t, 0))
10212 return false;
10213
10214 t2 = t + 1;
10215 n = Bits32 (opcode, 19, 16);
10216 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10217
10218 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10219 index = BitIsSet (opcode, 24);
10220 add = BitIsSet (opcode, 23);
10221 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10222
10223 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10224 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10225 return false;
10226
10227 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10228 if (wback && ((n == 15) || (n == t) || (n == t2)))
10229 return false;
10230
10231 // if t2 == 15 then UNPREDICTABLE;
10232 if (t2 == 15)
10233 return false;
10234
10235 break;
10236
10237 default:
10238 return false;
10239 }
10240
10241 Register base_reg;
10242 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10243
10244 uint32_t Rn = ReadCoreReg (n, &success);
10245 if (!success)
10246 return false;
10247
10248 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10249 addr_t offset_addr;
10250 if (add)
10251 offset_addr = Rn + imm32;
10252 else
10253 offset_addr = Rn - imm32;
10254
10255 //address = if index then offset_addr else R[n];
10256 addr_t address;
10257 if (index)
10258 address = offset_addr;
10259 else
10260 address = Rn;
10261
10262 //MemA[address,4] = R[t];
10263 Register data_reg;
10264 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10265
10266 uint32_t data = ReadCoreReg (t, &success);
10267 if (!success)
10268 return false;
10269
10270 EmulateInstruction::Context context;
10271 context.type = eContextRegisterStore;
10272 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10273
10274 const uint32_t addr_byte_size = GetAddressByteSize();
10275
10276 if (!MemAWrite (context, address, data, addr_byte_size))
10277 return false;
10278
10279 //MemA[address+4,4] = R[t2];
10280 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t2);
10281 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10282
10283 data = ReadCoreReg (t2, &success);
10284 if (!success)
10285 return false;
10286
10287 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10288 return false;
10289
10290 //if wback then R[n] = offset_addr;
10291 if (wback)
10292 {
10293 context.type = eContextAdjustBaseRegister;
10294 context.SetAddress (offset_addr);
10295
10296 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10297 return false;
10298 }
10299 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010300 return true;
10301}
10302
10303
10304// A8.6.201 STRD (register)
10305bool
10306EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10307{
10308#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010309 if ConditionPassed() then
10310 EncodingSpecificOperations();
10311 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10312 address = if index then offset_addr else R[n];
10313 MemA[address,4] = R[t];
10314 MemA[address+4,4] = R[t2];
10315 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010316#endif
10317
Caroline Tice74467fe2011-03-30 19:02:56 +000010318 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010319
Caroline Tice74467fe2011-03-30 19:02:56 +000010320 if (ConditionPassed(opcode))
10321 {
10322 uint32_t t;
10323 uint32_t t2;
10324 uint32_t n;
10325 uint32_t m;
10326 bool index;
10327 bool add;
10328 bool wback;
10329
10330 switch (encoding)
10331 {
10332 case eEncodingA1:
10333 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10334 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10335 t = Bits32 (opcode, 15, 12);
10336 if (BitIsSet (t, 0))
10337 return false;
10338
10339 t2 = t+1;
10340 n = Bits32 (opcode, 19, 16);
10341 m = Bits32 (opcode, 3, 0);
10342
10343 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10344 index = BitIsSet (opcode, 24);
10345 add = BitIsSet (opcode, 23);
10346 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10347
10348 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10349 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10350 return false;
10351
10352 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10353 if ((t2 == 15) || (m == 15))
10354 return false;
10355
10356 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10357 if (wback && ((n == 15) || (n == t) || (n == t2)))
10358 return false;
10359
10360 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010361 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010362 return false;
10363
10364 break;
10365
10366 default:
10367 return false;
10368 }
10369
10370 Register base_reg;
10371 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10372 Register offset_reg;
10373 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
10374 Register data_reg;
10375 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
10376
10377 uint32_t Rn = ReadCoreReg (n, &success);
10378 if (!success)
10379 return false;
10380
10381 uint32_t Rm = ReadCoreReg (m, &success);
10382 if (!success)
10383 return false;
10384
10385 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10386 addr_t offset_addr;
10387 if (add)
10388 offset_addr = Rn + Rm;
10389 else
10390 offset_addr = Rn - Rm;
10391
10392 // address = if index then offset_addr else R[n];
10393 addr_t address;
10394 if (index)
10395 address = offset_addr;
10396 else
10397 address = Rn;
10398 // MemA[address,4] = R[t];
10399 uint32_t Rt = ReadCoreReg (t, &success);
10400 if (!success)
10401 return false;
10402
10403 EmulateInstruction::Context context;
10404 context.type = eContextRegisterStore;
10405 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10406
10407 const uint32_t addr_byte_size = GetAddressByteSize();
10408
10409 if (!MemAWrite (context, address, Rt, addr_byte_size))
10410 return false;
10411
10412 // MemA[address+4,4] = R[t2];
10413 uint32_t Rt2 = ReadCoreReg (t2, &success);
10414 if (!success)
10415 return false;
10416
10417 data_reg.num = dwarf_r0 + t2;
10418
10419 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10420
10421 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10422 return false;
10423
10424 // if wback then R[n] = offset_addr;
10425 if (wback)
10426 {
10427 context.type = eContextAdjustBaseRegister;
10428 context.SetAddress (offset_addr);
10429
10430 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10431 return false;
10432
10433 }
10434 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010435 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010436}
10437
Caroline Tice4f605582011-03-31 00:02:51 +000010438// A8.6.319 VLDM
10439// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10440// an ARM core register.
10441bool
10442EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10443{
10444#if 0
10445 if ConditionPassed() then
10446 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10447 address = if add then R[n] else R[n]-imm32;
10448 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10449 for r = 0 to regs-1
10450 if single_regs then
10451 S[d+r] = MemA[address,4]; address = address+4;
10452 else
10453 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10454 // Combine the word-aligned words in the correct order for current endianness.
10455 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10456#endif
10457
10458 bool success = false;
10459
10460 if (ConditionPassed(opcode))
10461 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010462 bool single_regs;
10463 bool add;
10464 bool wback;
10465 uint32_t d;
10466 uint32_t n;
10467 uint32_t imm32;
10468 uint32_t regs;
10469
Caroline Tice4f605582011-03-31 00:02:51 +000010470 switch (encoding)
10471 {
10472 case eEncodingT1:
10473 case eEncodingA1:
10474 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10475 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10476 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10477 // if P == U && W == ‘1’ then UNDEFINED;
10478 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10479 return false;
10480
10481 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10482 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10483 single_regs = false;
10484 add = BitIsSet (opcode, 23);
10485 wback = BitIsSet (opcode, 21);
10486
10487 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10488 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10489 n = Bits32 (opcode, 19, 16);
10490 imm32 = Bits32 (opcode, 7, 0) << 2;
10491
10492 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FLDMX”.
10493 regs = Bits32 (opcode, 7, 0) / 2;
10494
10495 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10496 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10497 return false;
10498
10499 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10500 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10501 return false;
10502
10503 break;
10504
10505 case eEncodingT2:
10506 case eEncodingA2:
10507 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10508 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10509 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10510 // if P == U && W == ‘1’ then UNDEFINED;
10511 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10512 return false;
10513
10514 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10515 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10516 single_regs = true;
10517 add = BitIsSet (opcode, 23);
10518 wback = BitIsSet (opcode, 21);
10519 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10520 n = Bits32 (opcode, 19, 16);
10521
10522 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10523 imm32 = Bits32 (opcode, 7, 0) << 2;
10524 regs = Bits32 (opcode, 7, 0);
10525
10526 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10527 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10528 return false;
10529
10530 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10531 if ((regs == 0) || ((d + regs) > 32))
10532 return false;
10533 break;
10534
10535 default:
10536 return false;
10537 }
10538
10539 Register base_reg;
10540 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10541
10542 uint32_t Rn = ReadCoreReg (n, &success);
10543 if (!success)
10544 return false;
10545
10546 // address = if add then R[n] else R[n]-imm32;
10547 addr_t address;
10548 if (add)
10549 address = Rn;
10550 else
10551 address = Rn - imm32;
10552
10553 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10554 EmulateInstruction::Context context;
10555
10556 if (wback)
10557 {
10558 uint32_t value;
10559 if (add)
10560 value = Rn + imm32;
10561 else
10562 value = Rn - imm32;
10563
10564 context.type = eContextAdjustBaseRegister;
10565 context.SetImmediateSigned (value - Rn);
10566 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10567 return false;
10568
10569 }
10570
10571 const uint32_t addr_byte_size = GetAddressByteSize();
10572 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10573
10574 context.type = eContextRegisterLoad;
10575
10576 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010577 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010578 {
10579 if (single_regs)
10580 {
10581 // S[d+r] = MemA[address,4]; address = address+4;
10582 context.SetRegisterPlusOffset (base_reg, address - Rn);
10583
10584 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10585 if (!success)
10586 return false;
10587
10588 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10589 return false;
10590
10591 address = address + 4;
10592 }
10593 else
10594 {
10595 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10596 context.SetRegisterPlusOffset (base_reg, address - Rn);
10597 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10598 if (!success)
10599 return false;
10600
10601 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10602 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10603 if (!success)
10604 return false;
10605
10606 address = address + 8;
10607 // // Combine the word-aligned words in the correct order for current endianness.
10608 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10609 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010610 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010611 {
10612 data = word1;
10613 data = (data << 32) | word2;
10614 }
10615 else
10616 {
10617 data = word2;
10618 data = (data << 32) | word1;
10619 }
10620
10621 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10622 return false;
10623 }
10624 }
10625 }
10626 return true;
10627}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010628
10629// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010630// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10631// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010632bool
10633EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10634{
10635#if 0
10636 if ConditionPassed() then
10637 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10638 address = if add then R[n] else R[n]-imm32;
10639 if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10640 for r = 0 to regs-1
10641 if single_regs then
10642 MemA[address,4] = S[d+r]; address = address+4;
10643 else
10644 // Store as two word-aligned words in the correct order for current endianness.
10645 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10646 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10647 address = address+8;
10648#endif
10649
10650 bool success = false;
10651
10652 if (ConditionPassed (opcode))
10653 {
10654 bool single_regs;
10655 bool add;
10656 bool wback;
10657 uint32_t d;
10658 uint32_t n;
10659 uint32_t imm32;
10660 uint32_t regs;
10661
10662 switch (encoding)
10663 {
10664 case eEncodingT1:
10665 case eEncodingA1:
10666 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10667 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10668 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10669 // if P == U && W == ‘1’ then UNDEFINED;
10670 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10671 return false;
10672
10673 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10674 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10675 single_regs = false;
10676 add = BitIsSet (opcode, 23);
10677 wback = BitIsSet (opcode, 21);
10678
10679 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10680 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10681 n = Bits32 (opcode, 19, 16);
10682 imm32 = Bits32 (opcode, 7, 0) << 2;
10683
10684 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FSTMX”.
10685 regs = Bits32 (opcode, 7, 0) / 2;
10686
10687 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10688 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10689 return false;
10690
10691 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10692 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10693 return false;
10694
10695 break;
10696
10697 case eEncodingT2:
10698 case eEncodingA2:
10699 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10700 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10701 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10702 // if P == U && W == ‘1’ then UNDEFINED;
10703 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10704 return false;
10705
10706 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10707 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10708 single_regs = true;
10709 add = BitIsSet (opcode, 23);
10710 wback = BitIsSet (opcode, 21);
10711 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10712 n = Bits32 (opcode, 19, 16);
10713
10714 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10715 imm32 = Bits32 (opcode, 7, 0) << 2;
10716 regs = Bits32 (opcode, 7, 0);
10717
10718 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10719 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10720 return false;
10721
10722 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10723 if ((regs == 0) || ((d + regs) > 32))
10724 return false;
10725
10726 break;
10727
10728 default:
10729 return false;
10730 }
10731
10732 Register base_reg;
10733 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10734
10735 uint32_t Rn = ReadCoreReg (n, &success);
10736 if (!success)
10737 return false;
10738
10739 // address = if add then R[n] else R[n]-imm32;
10740 addr_t address;
10741 if (add)
10742 address = Rn;
10743 else
10744 address = Rn - imm32;
10745
10746 EmulateInstruction::Context context;
10747 // if wback then R[n] = if add then R[n}+imm32 else R[n]-imm32;
10748 if (wback)
10749 {
10750 uint32_t value;
10751 if (add)
10752 value = Rn + imm32;
10753 else
10754 value = Rn - imm32;
10755
10756 context.type = eContextAdjustBaseRegister;
10757 context.SetRegisterPlusOffset (base_reg, value - Rn);
10758
10759 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10760 return false;
10761 }
10762
10763 const uint32_t addr_byte_size = GetAddressByteSize();
10764 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10765
10766 context.type = eContextRegisterStore;
10767 // for r = 0 to regs-1
10768 for (int r = 0; r < regs; ++r)
10769 {
10770 Register data_reg;
10771 data_reg.SetRegister (eRegisterKindDWARF, 0);
10772 if (single_regs)
10773 {
10774 // MemA[address,4] = S[d+r]; address = address+4;
10775 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10776 if (!success)
10777 return false;
10778
10779 data_reg.num = start_reg + d + r;
10780 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10781 if (!MemAWrite (context, address, data, addr_byte_size))
10782 return false;
10783
10784 address = address + 4;
10785 }
10786 else
10787 {
10788 // // Store as two word-aligned words in the correct order for current endianness.
10789 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10790 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10791 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10792 if (!success)
10793 return false;
10794
10795 data_reg.num = start_reg + d + r;
10796
Greg Clayton888a7332011-04-26 04:39:08 +000010797 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010798 {
10799 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10800 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10801 return false;
10802
10803 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10804 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10805 return false;
10806 }
10807 else
10808 {
10809 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10810 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10811 return false;
10812
10813 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10814 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10815 return false;
10816 }
10817 // address = address+8;
10818 address = address + 8;
10819 }
10820 }
10821 }
10822 return true;
10823}
10824
Caroline Tice917ad352011-03-31 05:05:30 +000010825// A8.6.320
10826// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10827// an optional offset.
10828bool
10829EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10830{
10831#if 0
10832 if ConditionPassed() then
10833 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10834 base = if n == 15 then Align(PC,4) else R[n];
10835 address = if add then (base + imm32) else (base - imm32);
10836 if single_reg then
10837 S[d] = MemA[address,4];
10838 else
10839 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10840 // Combine the word-aligned words in the correct order for current endianness.
10841 D[d] = if BigEndian() then word1:word2 else word2:word1;
10842#endif
10843
10844 bool success = false;
10845
10846 if (ConditionPassed (opcode))
10847 {
10848 bool single_reg;
10849 bool add;
10850 uint32_t imm32;
10851 uint32_t d;
10852 uint32_t n;
10853
10854 switch (encoding)
10855 {
10856 case eEncodingT1:
10857 case eEncodingA1:
10858 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10859 single_reg = false;
10860 add = BitIsSet (opcode, 23);
10861 imm32 = Bits32 (opcode, 7, 0) << 2;
10862
10863 // d = UInt(D:Vd); n = UInt(Rn);
10864 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10865 n = Bits32 (opcode, 19, 16);
10866
10867 break;
10868
10869 case eEncodingT2:
10870 case eEncodingA2:
10871 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10872 single_reg = true;
10873 add = BitIsSet (opcode, 23);
10874 imm32 = Bits32 (opcode, 7, 0) << 2;
10875
10876 // d = UInt(Vd:D); n = UInt(Rn);
10877 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10878 n = Bits32 (opcode, 19, 16);
10879
10880 break;
10881
10882 default:
10883 return false;
10884 }
10885 Register base_reg;
10886 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10887
10888 uint32_t Rn = ReadCoreReg (n, &success);
10889 if (!success)
10890 return false;
10891
10892 // base = if n == 15 then Align(PC,4) else R[n];
10893 uint32_t base;
10894 if (n == 15)
10895 base = AlignPC (Rn);
10896 else
10897 base = Rn;
10898
10899 // address = if add then (base + imm32) else (base - imm32);
10900 addr_t address;
10901 if (add)
10902 address = base + imm32;
10903 else
10904 address = base - imm32;
10905
10906 const uint32_t addr_byte_size = GetAddressByteSize();
10907 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
10908
10909 EmulateInstruction::Context context;
10910 context.type = eContextRegisterLoad;
10911 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010912
Caroline Tice917ad352011-03-31 05:05:30 +000010913 if (single_reg)
10914 {
10915 // S[d] = MemA[address,4];
10916 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10917 if (!success)
10918 return false;
10919
10920 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
10921 return false;
10922 }
10923 else
10924 {
10925 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
10926 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10927 if (!success)
10928 return false;
10929
10930 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
10931 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10932 if (!success)
10933 return false;
10934 // // Combine the word-aligned words in the correct order for current endianness.
10935 // D[d] = if BigEndian() then word1:word2 else word2:word1;
10936 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000010937 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000010938 {
10939 data64 = word1;
10940 data64 = (data64 << 32) | word2;
10941 }
10942 else
10943 {
10944 data64 = word2;
10945 data64 = (data64 << 32) | word1;
10946 }
10947
10948 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
10949 return false;
10950 }
10951 }
10952 return true;
10953}
Caroline Tice424652f2011-03-31 05:38:36 +000010954
10955// A8.6.400 VSTR
10956// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
10957// optional offset.
10958bool
10959EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
10960{
10961#if 0
10962 if ConditionPassed() then
10963 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10964 address = if add then (R[n] + imm32) else (R[n] - imm32);
10965 if single_reg then
10966 MemA[address,4] = S[d];
10967 else
10968 // Store as two word-aligned words in the correct order for current endianness.
10969 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
10970 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
10971#endif
10972
10973 bool success = false;
10974
10975 if (ConditionPassed (opcode))
10976 {
10977 bool single_reg;
10978 bool add;
10979 uint32_t imm32;
10980 uint32_t d;
10981 uint32_t n;
10982
10983 switch (encoding)
10984 {
10985 case eEncodingT1:
10986 case eEncodingA1:
10987 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10988 single_reg = false;
10989 add = BitIsSet (opcode, 23);
10990 imm32 = Bits32 (opcode, 7, 0) << 2;
10991
10992 // d = UInt(D:Vd); n = UInt(Rn);
10993 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10994 n = Bits32 (opcode, 19, 16);
10995
10996 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
10997 if ((n == 15) && (CurrentInstrSet() != eModeARM))
10998 return false;
10999
11000 break;
11001
11002 case eEncodingT2:
11003 case eEncodingA2:
11004 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
11005 single_reg = true;
11006 add = BitIsSet (opcode, 23);
11007 imm32 = Bits32 (opcode, 7, 0) << 2;
11008
11009 // d = UInt(Vd:D); n = UInt(Rn);
11010 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11011 n = Bits32 (opcode, 19, 16);
11012
11013 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11014 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11015 return false;
11016
11017 break;
11018
11019 default:
11020 return false;
11021 }
11022
11023 Register base_reg;
11024 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11025
11026 uint32_t Rn = ReadCoreReg (n, &success);
11027 if (!success)
11028 return false;
11029
11030 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11031 addr_t address;
11032 if (add)
11033 address = Rn + imm32;
11034 else
11035 address = Rn - imm32;
11036
11037 const uint32_t addr_byte_size = GetAddressByteSize();
11038 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11039
11040 Register data_reg;
11041 data_reg.SetRegister (eRegisterKindDWARF, start_reg + d);
11042 EmulateInstruction::Context context;
11043 context.type = eContextRegisterStore;
11044 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11045
11046 if (single_reg)
11047 {
11048 // MemA[address,4] = S[d];
11049 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11050 if (!success)
11051 return false;
11052
11053 if (!MemAWrite (context, address, data, addr_byte_size))
11054 return false;
11055 }
11056 else
11057 {
11058 // // Store as two word-aligned words in the correct order for current endianness.
11059 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11060 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11061 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11062 if (!success)
11063 return false;
11064
Greg Clayton888a7332011-04-26 04:39:08 +000011065 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011066 {
11067 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11068 return false;
11069
11070 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11071 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11072 return false;
11073 }
11074 else
11075 {
11076 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11077 return false;
11078
11079 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11080 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11081 return false;
11082 }
11083 }
11084 }
11085 return true;
11086}
Caroline Tice9121b352011-03-31 16:41:19 +000011087
11088// A8.6.307 VLDI1 (multiple single elements)
11089// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11090// element of each register is loaded.
11091bool
11092EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11093{
11094#if 0
11095 if ConditionPassed() then
11096 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11097 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11098 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11099 for r = 0 to regs-1
11100 for e = 0 to elements-1
11101 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11102 address = address + ebytes;
11103#endif
11104
11105 bool success = false;
11106
11107 if (ConditionPassed (opcode))
11108 {
11109 uint32_t regs;
11110 uint32_t alignment;
11111 uint32_t ebytes;
11112 uint32_t esize;
11113 uint32_t elements;
11114 uint32_t d;
11115 uint32_t n;
11116 uint32_t m;
11117 bool wback;
11118 bool register_index;
11119
11120 switch (encoding)
11121 {
11122 case eEncodingT1:
11123 case eEncodingA1:
11124 {
11125 // case type of
11126 // when ‘0111’
11127 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11128 // when ‘1010’
11129 // regs = 2; if align == ‘11’ then UNDEFINED;
11130 // when ‘0110’
11131 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11132 // when ‘0010’
11133 // regs = 4;
11134 // otherwise
11135 // SEE “Related encodings”;
11136 uint32_t type = Bits32 (opcode, 11, 8);
11137 uint32_t align = Bits32 (opcode, 5, 4);
11138 if (type == 7) // '0111'
11139 {
11140 regs = 1;
11141 if (BitIsSet (align, 1))
11142 return false;
11143 }
11144 else if (type == 10) // '1010'
11145 {
11146 regs = 2;
11147 if (align == 3)
11148 return false;
11149
11150 }
11151 else if (type == 6) // '0110'
11152 {
11153 regs = 3;
11154 if (BitIsSet (align, 1))
11155 return false;
11156 }
11157 else if (type == 2) // '0010'
11158 {
11159 regs = 4;
11160 }
11161 else
11162 return false;
11163
11164 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11165 if (align == 0)
11166 alignment = 1;
11167 else
11168 alignment = 4 << align;
11169
11170 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11171 ebytes = 1 << Bits32 (opcode, 7, 6);
11172 esize = 8 * ebytes;
11173 elements = 8 / ebytes;
11174
11175 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11176 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11177 n = Bits32 (opcode, 19, 15);
11178 m = Bits32 (opcode, 3, 0);
11179
11180 // wback = (m != 15); register_index = (m != 15 && m != 13);
11181 wback = (m != 15);
11182 register_index = ((m != 15) && (m != 13));
11183
11184 // if d+regs > 32 then UNPREDICTABLE;
11185 if ((d + regs) > 32)
11186 return false;
11187 }
11188 break;
11189
11190 default:
11191 return false;
11192 }
11193
11194 Register base_reg;
11195 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11196
11197 uint32_t Rn = ReadCoreReg (n, &success);
11198 if (!success)
11199 return false;
11200
11201 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11202 addr_t address = Rn;
11203 if ((address % alignment) != 0)
11204 return false;
11205
11206 EmulateInstruction::Context context;
11207 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11208 if (wback)
11209 {
11210 uint32_t Rm = ReadCoreReg (m, &success);
11211 if (!success)
11212 return false;
11213
11214 uint32_t offset;
11215 if (register_index)
11216 offset = Rm;
11217 else
11218 offset = 8 * regs;
11219
11220 uint32_t value = Rn + offset;
11221 context.type = eContextAdjustBaseRegister;
11222 context.SetRegisterPlusOffset (base_reg, offset);
11223
11224 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11225 return false;
11226
11227 }
11228
11229 // for r = 0 to regs-1
11230 for (int r = 0; r < regs; ++r)
11231 {
11232 // for e = 0 to elements-1
11233 uint64_t assembled_data = 0;
11234 for (int e = 0; e < elements; ++e)
11235 {
11236 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11237 context.type = eContextRegisterLoad;
11238 context.SetRegisterPlusOffset (base_reg, address - Rn);
11239 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11240 if (!success)
11241 return false;
11242
11243 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11244
11245 // address = address + ebytes;
11246 address = address + ebytes;
11247 }
11248 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11249 return false;
11250 }
11251 }
11252 return true;
11253}
11254
Caroline Ticeb6281b12011-03-31 17:58:23 +000011255// A8.6.308 VLD1 (single element to one lane)
11256//
11257bool
11258EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11259{
11260#if 0
11261 if ConditionPassed() then
11262 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11263 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11264 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11265 Elem[D[d],index,esize] = MemU[address,ebytes];
11266#endif
11267
11268 bool success = false;
11269
11270 if (ConditionPassed (opcode))
11271 {
11272 uint32_t ebytes;
11273 uint32_t esize;
11274 uint32_t index;
11275 uint32_t alignment;
11276 uint32_t d;
11277 uint32_t n;
11278 uint32_t m;
11279 bool wback;
11280 bool register_index;
11281
11282 switch (encoding)
11283 {
11284 case eEncodingT1:
11285 case eEncodingA1:
11286 {
11287 uint32_t size = Bits32 (opcode, 11, 10);
11288 uint32_t index_align = Bits32 (opcode, 7, 4);
11289 // if size == ‘11’ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011290 if (size == 3)
11291 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011292 // case size of
11293 if (size == 0) // when '00'
11294 {
11295 // if index_align<0> != ‘0’ then UNDEFINED;
11296 if (BitIsClear (index_align, 0))
11297 return false;
11298
11299 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11300 ebytes = 1;
11301 esize = 8;
11302 index = Bits32 (index_align, 3, 1);
11303 alignment = 1;
11304 }
11305 else if (size == 1) // when ‘01’
11306 {
11307 // if index_align<1> != ‘0’ then UNDEFINED;
11308 if (BitIsClear (index_align, 1))
11309 return false;
11310
11311 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11312 ebytes = 2;
11313 esize = 16;
11314 index = Bits32 (index_align, 3, 2);
11315
11316 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11317 if (BitIsClear (index_align, 0))
11318 alignment = 1;
11319 else
11320 alignment = 2;
11321 }
11322 else if (size == 2) // when ‘10’
11323 {
11324 // if index_align<2> != ‘0’ then UNDEFINED;
11325 if (BitIsClear (index_align, 2))
11326 return false;
11327
11328 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11329 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11330 return false;
11331
11332 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11333 ebytes = 4;
11334 esize = 32;
11335 index = Bit32 (index_align, 3);
11336
11337 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11338 if (Bits32 (index_align, 1, 0) == 0)
11339 alignment = 1;
11340 else
11341 alignment = 4;
11342 }
11343 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11344 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11345 n = Bits32 (opcode, 19, 16);
11346 m = Bits32 (opcode, 3, 0);
11347
11348 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11349 wback = (m != 15);
11350 register_index = ((m != 15) && (m != 13));
11351
11352 if (n == 15)
11353 return false;
11354
11355 }
11356 break;
11357
11358 default:
11359 return false;
11360 }
11361
11362 Register base_reg;
11363 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11364
11365 uint32_t Rn = ReadCoreReg (n, &success);
11366 if (!success)
11367 return false;
11368
11369 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11370 addr_t address = Rn;
11371 if ((address % alignment) != 0)
11372 return false;
11373
11374 EmulateInstruction::Context context;
11375 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11376 if (wback)
11377 {
11378 uint32_t Rm = ReadCoreReg (m, &success);
11379 if (!success)
11380 return false;
11381
11382 uint32_t offset;
11383 if (register_index)
11384 offset = Rm;
11385 else
11386 offset = ebytes;
11387
11388 uint32_t value = Rn + offset;
11389
11390 context.type = eContextAdjustBaseRegister;
11391 context.SetRegisterPlusOffset (base_reg, offset);
11392
11393 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11394 return false;
11395 }
11396
11397 // Elem[D[d],index,esize] = MemU[address,ebytes];
11398 uint32_t element = MemURead (context, address, esize, 0, &success);
11399 if (!success)
11400 return false;
11401
11402 element = element << (index * esize);
11403
11404 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11405 if (!success)
11406 return false;
11407
11408 uint64_t all_ones = -1;
11409 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11410 // at element & to the right of element.
11411 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011412 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 +000011413 // now mask should be 0's where element goes & 1's
11414 // everywhere else.
11415
11416 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11417 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11418
11419 context.type = eContextRegisterLoad;
11420 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11421 return false;
11422 }
11423 return true;
11424}
11425
Caroline Tice1e542e32011-03-31 18:44:04 +000011426// A8.6.391 VST1 (multiple single elements)
11427// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11428// interleaving. Every element of each register is stored.
11429bool
11430EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11431{
11432#if 0
11433 if ConditionPassed() then
11434 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11435 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11436 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11437 for r = 0 to regs-1
11438 for e = 0 to elements-1
11439 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11440 address = address + ebytes;
11441#endif
11442
11443 bool success = false;
11444
11445 if (ConditionPassed (opcode))
11446 {
11447 uint32_t regs;
11448 uint32_t alignment;
11449 uint32_t ebytes;
11450 uint32_t esize;
11451 uint32_t elements;
11452 uint32_t d;
11453 uint32_t n;
11454 uint32_t m;
11455 bool wback;
11456 bool register_index;
11457
11458 switch (encoding)
11459 {
11460 case eEncodingT1:
11461 case eEncodingA1:
11462 {
11463 uint32_t type = Bits32 (opcode, 11, 8);
11464 uint32_t align = Bits32 (opcode, 5, 4);
11465
11466 // case type of
11467 if (type == 7) // when ‘0111’
11468 {
11469 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11470 regs = 1;
11471 if (BitIsSet (align, 1))
11472 return false;
11473 }
11474 else if (type == 10) // when ‘1010’
11475 {
11476 // regs = 2; if align == ‘11’ then UNDEFINED;
11477 regs = 2;
11478 if (align == 3)
11479 return false;
11480 }
11481 else if (type == 6) // when ‘0110’
11482 {
11483 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11484 regs = 3;
11485 if (BitIsSet (align, 1))
11486 return false;
11487 }
11488 else if (type == 2) // when ‘0010’
11489 // regs = 4;
11490 regs = 4;
11491 else // otherwise
11492 // SEE “Related encodings”;
11493 return false;
11494
11495 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11496 if (align == 0)
11497 alignment = 0;
11498 else
11499 alignment = 4 << align;
11500
11501 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11502 ebytes = 1 << Bits32 (opcode,7, 6);
11503 esize = 8 * ebytes;
11504 elements = 8 / ebytes;
11505
11506 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11507 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11508 n = Bits32 (opcode, 19, 16);
11509 m = Bits32 (opcode, 3, 0);
11510
11511 // wback = (m != 15); register_index = (m != 15 && m != 13);
11512 wback = (m != 15);
11513 register_index = ((m != 15) && (m != 13));
11514
11515 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11516 if ((d + regs) > 32)
11517 return false;
11518
11519 if (n == 15)
11520 return false;
11521
11522 }
11523 break;
11524
11525 default:
11526 return false;
11527 }
11528
11529 Register base_reg;
11530 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11531
11532 uint32_t Rn = ReadCoreReg (n, &success);
11533 if (!success)
11534 return false;
11535
11536 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11537 addr_t address = Rn;
11538 if ((address % alignment) != 0)
11539 return false;
11540
11541 EmulateInstruction::Context context;
11542 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11543 if (wback)
11544 {
11545 uint32_t Rm = ReadCoreReg (m, &success);
11546 if (!success)
11547 return false;
11548
11549 uint32_t offset;
11550 if (register_index)
11551 offset = Rm;
11552 else
11553 offset = 8 * regs;
11554
11555 context.type = eContextAdjustBaseRegister;
11556 context.SetRegisterPlusOffset (base_reg, offset);
11557
11558 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11559 return false;
11560 }
11561
11562 context.type = eContextRegisterStore;
11563 Register data_reg;
11564 data_reg.SetRegister (eRegisterKindDWARF, 0);
11565 // for r = 0 to regs-1
11566 for (int r = 0; r < regs; ++r)
11567 {
11568 data_reg.num = dwarf_d0 + d + r;
11569 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11570 if (!success)
11571 return false;
11572
11573 // for e = 0 to elements-1
11574 for (int e = 0; e < elements; ++e)
11575 {
11576 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011577 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011578
11579 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11580 if (!MemUWrite (context, address, word, ebytes))
11581 return false;
11582
11583 // address = address + ebytes;
11584 address = address + ebytes;
11585 }
11586 }
11587 }
11588 return true;
11589}
11590
Caroline Tice7b880942011-03-31 19:17:12 +000011591// A8.6.392 VST1 (single element from one lane)
11592// This instruction stores one element to memory from one element of a register.
11593bool
11594EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11595{
11596#if 0
11597 if ConditionPassed() then
11598 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11599 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11600 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11601 MemU[address,ebytes] = Elem[D[d],index,esize];
11602#endif
11603
11604 bool success = false;
11605
11606 if (ConditionPassed (opcode))
11607 {
11608 uint32_t ebytes;
11609 uint32_t esize;
11610 uint32_t index;
11611 uint32_t alignment;
11612 uint32_t d;
11613 uint32_t n;
11614 uint32_t m;
11615 bool wback;
11616 bool register_index;
11617
11618 switch (encoding)
11619 {
11620 case eEncodingT1:
11621 case eEncodingA1:
11622 {
11623 uint32_t size = Bits32 (opcode, 11, 10);
11624 uint32_t index_align = Bits32 (opcode, 7, 4);
11625
11626 // if size == ‘11’ then UNDEFINED;
11627 if (size == 3)
11628 return false;
11629
11630 // case size of
11631 if (size == 0) // when ‘00’
11632 {
11633 // if index_align<0> != ‘0’ then UNDEFINED;
11634 if (BitIsClear (index_align, 0))
11635 return false;
11636 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11637 ebytes = 1;
11638 esize = 8;
11639 index = Bits32 (index_align, 3, 1);
11640 alignment = 1;
11641 }
11642 else if (size == 1) // when ‘01’
11643 {
11644 // if index_align<1> != ‘0’ then UNDEFINED;
11645 if (BitIsClear (index_align, 1))
11646 return false;
11647
11648 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11649 ebytes = 2;
11650 esize = 16;
11651 index = Bits32 (index_align, 3, 2);
11652
11653 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11654 if (BitIsClear (index_align, 0))
11655 alignment = 1;
11656 else
11657 alignment = 2;
11658 }
11659 else if (size == 2) // when ‘10’
11660 {
11661 // if index_align<2> != ‘0’ then UNDEFINED;
11662 if (BitIsClear (index_align, 2))
11663 return false;
11664
11665 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11666 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11667 return false;
11668
11669 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11670 ebytes = 4;
11671 esize = 32;
11672 index = Bit32 (index_align, 3);
11673
11674 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11675 if (Bits32 (index_align, 1, 0) == 0)
11676 alignment = 1;
11677 else
11678 alignment = 4;
11679 }
11680 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11681 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11682 n = Bits32 (opcode, 19, 16);
11683 m = Bits32 (opcode, 3, 0);
11684
11685 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11686 wback = (m != 15);
11687 register_index = ((m != 15) && (m != 13));
11688
11689 if (n == 15)
11690 return false;
11691 }
11692 break;
11693
11694 default:
11695 return false;
11696 }
11697
11698 Register base_reg;
11699 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
11700
11701 uint32_t Rn = ReadCoreReg (n, &success);
11702 if (!success)
11703 return false;
11704
11705 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11706 addr_t address = Rn;
11707 if ((address % alignment) != 0)
11708 return false;
11709
11710 EmulateInstruction::Context context;
11711 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11712 if (wback)
11713 {
11714 uint32_t Rm = ReadCoreReg (m, &success);
11715 if (!success)
11716 return false;
11717
11718 uint32_t offset;
11719 if (register_index)
11720 offset = Rm;
11721 else
11722 offset = ebytes;
11723
11724 context.type = eContextAdjustBaseRegister;
11725 context.SetRegisterPlusOffset (base_reg, offset);
11726
11727 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11728 return false;
11729 }
11730
11731 // MemU[address,ebytes] = Elem[D[d],index,esize];
11732 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11733 if (!success)
11734 return false;
11735
11736 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11737
11738 Register data_reg;
11739 data_reg.SetRegister (eRegisterKindDWARF, dwarf_d0 + d);
11740 context.type = eContextRegisterStore;
11741 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11742
11743 if (!MemUWrite (context, address, word, ebytes))
11744 return false;
11745 }
11746 return true;
11747}
11748
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011749// A8.6.309 VLD1 (single element to all lanes)
11750// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011751bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011752EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011753{
11754#if 0
11755 if ConditionPassed() then
11756 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11757 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11758 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11759 replicated_element = Replicate(MemU[address,ebytes], elements);
11760 for r = 0 to regs-1
11761 D[d+r] = replicated_element;
11762#endif
11763
11764 bool success = false;
11765
11766 if (ConditionPassed (opcode))
11767 {
11768 uint32_t ebytes;
11769 uint32_t elements;
11770 uint32_t regs;
11771 uint32_t alignment;
11772 uint32_t d;
11773 uint32_t n;
11774 uint32_t m;
11775 bool wback;
11776 bool register_index;
11777
11778 switch (encoding)
11779 {
11780 case eEncodingT1:
11781 case eEncodingA1:
11782 {
11783 //if size == ‘11’ || (size == ‘00’ && a == ‘1’) then UNDEFINED;
11784 uint32_t size = Bits32 (opcode, 7, 6);
11785 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11786 return false;
11787
11788 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == ‘0’ then 1 else 2;
11789 ebytes = 1 << size;
11790 elements = 8 / ebytes;
11791 if (BitIsClear (opcode, 5))
11792 regs = 1;
11793 else
11794 regs = 2;
11795
11796 //alignment = if a == ‘0’ then 1 else ebytes;
11797 if (BitIsClear (opcode, 4))
11798 alignment = 1;
11799 else
11800 alignment = ebytes;
11801
11802 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11803 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11804 n = Bits32 (opcode, 19, 16);
11805 m = Bits32 (opcode, 3, 0);
11806
11807 //wback = (m != 15); register_index = (m != 15 && m != 13);
11808 wback = (m != 15);
11809 register_index = ((m != 15) && (m != 13));
11810
11811 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11812 if ((d + regs) > 32)
11813 return false;
11814
11815 if (n == 15)
11816 return false;
11817 }
11818 break;
11819
11820 default:
11821 break;
11822 }
11823
11824 Register base_reg;
11825 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
11826
11827 uint32_t Rn = ReadCoreReg (n, &success);
11828 if (!success)
11829 return false;
11830
11831 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11832 addr_t address = Rn;
11833 if ((address % alignment) != 0)
11834 return false;
11835
11836 EmulateInstruction::Context context;
11837 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11838 if (wback)
11839 {
11840 uint32_t Rm = ReadCoreReg (m, &success);
11841 if (!success)
11842 return false;
11843
11844 uint32_t offset;
11845 if (register_index)
11846 offset = Rm;
11847 else
11848 offset = ebytes;
11849
11850 context.type = eContextAdjustBaseRegister;
11851 context.SetRegisterPlusOffset (base_reg, offset);
11852
11853 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11854 return false;
11855 }
11856
11857 // replicated_element = Replicate(MemU[address,ebytes], elements);
11858
11859 context.type = eContextRegisterLoad;
11860 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11861 if (!success)
11862 return false;
11863
11864 uint64_t replicated_element;
11865 uint32_t esize = ebytes * 8;
11866 for (int e = 0; e < elements; ++e)
11867 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11868
11869 // for r = 0 to regs-1
11870 for (int r = 0; r < regs; ++r)
11871 {
11872 // D[d+r] = replicated_element;
11873 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11874 return false;
11875 }
11876 }
11877 return true;
11878}
11879
Caroline Tice1f954f52011-04-11 15:51:10 +000011880// B6.2.13 SUBS PC, LR and related instructions
11881//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
11882// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
11883bool
11884EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
11885{
11886#if 0
11887 if ConditionPassed() then
11888 EncodingSpecificOperations();
11889 if CurrentInstrSet() == InstrSet_ThumbEE then
11890 UNPREDICTABLE;
11891 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11892 case opcode of
11893 when 0000 result = R[n] AND operand2; // AND
11894 when 0001 result = R[n] EOR operand2; // EOR
11895 when 0010 (result, -, -) = AddWithCarry(R[n], NOT(operand2), 1’); // SUB
11896 when 0011 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, 1’); // RSB
11897 when 0100 (result, -, -) = AddWithCarry(R[n], operand2, 0’); // ADD
11898 when 0101 (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
11899 when 0110 (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
11900 when 0111 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
11901 when 1100 result = R[n] OR operand2; // ORR
11902 when 1101 result = operand2; // MOV
11903 when 1110 result = R[n] AND NOT(operand2); // BIC
11904 when 1111 result = NOT(operand2); // MVN
11905 CPSRWriteByInstr(SPSR[], 1111’, TRUE);
11906 BranchWritePC(result);
11907#endif
11908
11909 bool success = false;
11910
11911 if (ConditionPassed (opcode))
11912 {
11913 uint32_t n;
11914 uint32_t m;
11915 uint32_t imm32;
11916 bool register_form;
11917 ARM_ShifterType shift_t;
11918 uint32_t shift_n;
11919 uint32_t code;
11920
11921 switch (encoding)
11922 {
11923 case eEncodingT1:
11924 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
11925 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = ‘0010’; // = SUB
11926 n = 14;
11927 imm32 = Bits32 (opcode, 7, 0);
11928 register_form = false;
11929 code = 2;
11930
11931 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
11932 if (InITBlock() && !LastInITBlock())
11933 return false;
11934
11935 break;
11936
11937 case eEncodingA1:
11938 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
11939 n = Bits32 (opcode, 19, 16);
11940 imm32 = ARMExpandImm (opcode);
11941 register_form = false;
11942 code = Bits32 (opcode, 24, 21);
11943
11944 break;
11945
11946 case eEncodingA2:
11947 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
11948 n = Bits32 (opcode, 19, 16);
11949 m = Bits32 (opcode, 3, 0);
11950 register_form = true;
11951
11952 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
11953 shift_n = DecodeImmShiftARM (opcode, shift_t);
11954
11955 break;
11956
11957 default:
11958 return false;
11959 }
11960
11961 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11962 uint32_t operand2;
11963 if (register_form)
11964 {
11965 uint32_t Rm = ReadCoreReg (m, &success);
11966 if (!success)
11967 return false;
11968
11969 operand2 = Shift (Rm, shift_t, shift_n, APSR_C);
11970
11971 }
11972 else
11973 {
11974 operand2 = imm32;
11975 }
11976
11977 uint32_t Rn = ReadCoreReg (n, &success);
11978 if (!success)
11979 return false;
11980
11981 AddWithCarryResult result;
11982
11983 // case opcode of
11984 switch (code)
11985 {
11986 case 0: // when ‘0000’
11987 // result = R[n] AND operand2; // AND
11988 result.result = Rn & operand2;
11989 break;
11990
11991 case 1: // when ‘0001’
11992 // result = R[n] EOR operand2; // EOR
11993 result.result = Rn ^ operand2;
11994 break;
11995
11996 case 2: // when ‘0010’
11997 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), ‘1’); // SUB
11998 result = AddWithCarry (Rn, ~(operand2), 1);
11999 break;
12000
12001 case 3: // when ‘0011’
12002 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, ‘1’); // RSB
12003 result = AddWithCarry (~(Rn), operand2, 1);
12004 break;
12005
12006 case 4: // when ‘0100’
12007 // (result, -, -) = AddWithCarry(R[n], operand2, ‘0’); // ADD
12008 result = AddWithCarry (Rn, operand2, 0);
12009 break;
12010
12011 case 5: // when ‘0101’
12012 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12013 result = AddWithCarry (Rn, operand2, APSR_C);
12014 break;
12015
12016 case 6: // when ‘0110’
12017 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12018 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12019 break;
12020
12021 case 7: // when ‘0111’
12022 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12023 result = AddWithCarry (~(Rn), operand2, APSR_C);
12024 break;
12025
12026 case 10: // when ‘1100’
12027 // result = R[n] OR operand2; // ORR
12028 result.result = Rn | operand2;
12029 break;
12030
12031 case 11: // when ‘1101’
12032 // result = operand2; // MOV
12033 result.result = operand2;
12034 break;
12035
12036 case 12: // when ‘1110’
12037 // result = R[n] AND NOT(operand2); // BIC
12038 result.result = Rn & ~(operand2);
12039 break;
12040
12041 case 15: // when ‘1111’
12042 // result = NOT(operand2); // MVN
12043 result.result = ~(operand2);
12044 break;
12045
12046 default:
12047 return false;
12048 }
12049 // CPSRWriteByInstr(SPSR[], ‘1111’, TRUE);
12050
12051 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12052 // the best.
12053 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12054 if (!success)
12055 return false;
12056
12057 CPSRWriteByInstr (spsr, 15, true);
12058
12059 // BranchWritePC(result);
12060 EmulateInstruction::Context context;
12061 context.type = eContextAdjustPC;
12062 context.SetImmediate (result.result);
12063
12064 BranchWritePC (context, result.result);
12065 }
12066 return true;
12067}
12068
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012069EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012070EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012071{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012072 static ARMOpcode
12073 g_arm_opcodes[] =
12074 {
12075 //----------------------------------------------------------------------
12076 // Prologue instructions
12077 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012078
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012079 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012080 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12081 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012082
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012083 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012084 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12085 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012086 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012087 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12088 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12089 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012090
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012091 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012092 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12093 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012094
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012095 // push one register
12096 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012097 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012098
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012099 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012100 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12101 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012102
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012103 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012104 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012105 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012106
Caroline Tice4f605582011-03-31 00:02:51 +000012107 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12108 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12109 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12110 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012111
12112 //----------------------------------------------------------------------
12113 // Supervisor Call (previously Software Interrupt)
12114 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012115 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012116
12117 //----------------------------------------------------------------------
12118 // Branch instructions
12119 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012120 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012121 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012122 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12123 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12124 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012125 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012126 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012127 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012128 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012129
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012130 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012131 // Data-processing instructions
12132 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012133 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012134 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012135 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012136 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012137 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012138 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012139 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012140 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012141 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012142 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012143 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012144 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12145 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012146 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012147 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012148 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012149 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012150 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012151 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012152 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012153 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012154 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012155 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012156 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012157 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012158 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012159 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012160 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012161 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012162 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012163 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012164 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012165 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012166 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012167 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012168 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012169 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012170 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012171 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012172 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012173 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012174 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012175 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012176 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012177 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012178 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012179 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012180 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012181 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012182 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012183 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012184 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012185 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012186 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012187 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012188
Caroline Tice89c6d582011-03-29 19:53:44 +000012189 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012190 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12191 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012192 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012193 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012194 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012195 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012196 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012197 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012198 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012199 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012200 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012201 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012202 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012203 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012204 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012205 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012206 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012207 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012208 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012209 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012210 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012211 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012212 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012213 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012214 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012215 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012216 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012217 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012218 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012219 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012220 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012221 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012222 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012223 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012224 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012225 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012226
12227 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012228 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12229 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012230
12231 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012232 // Load instructions
12233 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012234 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12235 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12236 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12237 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12238 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12239 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12240 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12241 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12242 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12243 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12244 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12245 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12246 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12247 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12248 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12249 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12250 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12251 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012252 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12253 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12254 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12255 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012256 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12257 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012258 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012259
12260 //----------------------------------------------------------------------
12261 // Store instructions
12262 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012263 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12264 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12265 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12266 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12267 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12268 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12269 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12270 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12271 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012272 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012273 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012274 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12275 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12276 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12277 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12278 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012279 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012280
Caroline Tice6bf65162011-03-03 17:42:58 +000012281 //----------------------------------------------------------------------
12282 // Other instructions
12283 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012284 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12285 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12286 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12287 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12288 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012289
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012290 };
12291 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12292
12293 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12294 {
Greg Clayton888a7332011-04-26 04:39:08 +000012295 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12296 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012297 return &g_arm_opcodes[i];
12298 }
12299 return NULL;
12300}
Greg Clayton64c84432011-01-21 22:02:52 +000012301
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012302
12303EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012304EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012305{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012306
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012307 static ARMOpcode
12308 g_thumb_opcodes[] =
12309 {
12310 //----------------------------------------------------------------------
12311 // Prologue instructions
12312 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012313
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012314 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012315 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12316 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12317 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012318
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012319 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012320 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012321 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012322 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012323 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012324 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012325
Johnny Chen864a8e82011-02-18 00:07:39 +000012326 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012327 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012328
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012329 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012330 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12331 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12332 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12333 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12334 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012335
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012336 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012337 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12338 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012339
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012340 //----------------------------------------------------------------------
12341 // Epilogue instructions
12342 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012343
Caroline Tice4f605582011-03-31 00:02:51 +000012344 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12345 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12346 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12347 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12348 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12349 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12350 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012351
12352 //----------------------------------------------------------------------
12353 // Supervisor Call (previously Software Interrupt)
12354 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012355 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012356
12357 //----------------------------------------------------------------------
12358 // If Then makes up to four following instructions conditional.
12359 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012360 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012361
12362 //----------------------------------------------------------------------
12363 // Branch instructions
12364 //----------------------------------------------------------------------
12365 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012366 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12367 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12368 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12369 { 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 +000012370 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012371 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012372 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012373 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12374 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012375 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012376 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012377 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012378 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012379 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012380 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012381 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012382 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012383 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012384 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012385
12386 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012387 // Data-processing instructions
12388 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012389 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012390 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012391 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012392 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12393 { 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 +000012394 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012395 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012396 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012397 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012398 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012399 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12400 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12401 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012402 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012403 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012404 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012405 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12406 { 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 +000012407 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012408 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012409 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012410 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12411 { 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 +000012412 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012413 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012414 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012415 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12416 { 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 +000012417 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012418 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012419 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012420 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12421 { 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 +000012422 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012423 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12424 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012425 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012426 { 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 +000012427 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012428 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012429 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012430 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12431 { 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 +000012432 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012433 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12434 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12435 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12436 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012437 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012438 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12439 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12440 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12441 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012442 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012443 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12444 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012445 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012446 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12447 { 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 +000012448 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012449 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012450 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012451 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012452 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012453 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012454 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012455 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12456 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012457
Johnny Chen7c5234d2011-02-18 23:41:11 +000012458
Johnny Chen338bf542011-02-10 19:29:03 +000012459 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012460 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012461 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012462 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012463 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012464 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012465 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012466 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12467 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12468 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012469 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012470 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012471 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012472 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12473 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012474 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012475 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012476 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012477 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12478 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012479 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012480 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12481 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012482 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012483 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012484 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012485 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012486 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012487 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12488 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012489 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012490 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12491 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012492 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012493 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12494 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012495 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012496 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12497 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012498 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012499 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12500 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012501 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012502 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12503 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012504 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012505 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012506 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012507 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012508 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012509 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12510 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012511 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012512 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012513 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012514 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012515
12516 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012517 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012518
12519 //----------------------------------------------------------------------
12520 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12521 // otherwise the wrong instructions will be selected.
12522 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012523
Caroline Tice080bf612011-04-05 18:46:00 +000012524 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12525 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12526
Johnny Chen26863dc2011-02-09 23:43:29 +000012527 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012528 // Load instructions
12529 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012530 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12531 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12532 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12533 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12534 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12535 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12536 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012537 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012538 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12539 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12540 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12541 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12542 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012543 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012544 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12545 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12546 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12547 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12548 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12549 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12550 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12551 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12552 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12553 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12554 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12555 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12556 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12557 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12558 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12559 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12560 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12561 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12562 { 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 +000012563 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012564 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12565 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12566 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12567 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012568 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12569 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012570 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012571
12572 //----------------------------------------------------------------------
12573 // Store instructions
12574 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012575 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12576 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12577 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12578 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12579 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12580 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12581 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12582 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12583 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12584 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12585 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12586 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12587 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12588 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12589 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12590 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012591 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12592 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12593 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12594 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12595 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012596 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012597
12598 //----------------------------------------------------------------------
12599 // Other instructions
12600 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012601 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12602 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12603 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12604 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12605 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12606 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12607 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12608 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012609 };
12610
12611 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12612 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12613 {
Greg Clayton888a7332011-04-26 04:39:08 +000012614 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12615 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012616 return &g_thumb_opcodes[i];
12617 }
12618 return NULL;
12619}
Greg Clayton64c84432011-01-21 22:02:52 +000012620
Greg Clayton31e2a382011-01-30 20:03:56 +000012621bool
Greg Clayton395fc332011-02-15 21:59:32 +000012622EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012623{
Caroline Tice080bf612011-04-05 18:46:00 +000012624 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012625 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012626 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012627 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012628 {
Greg Clayton395fc332011-02-15 21:59:32 +000012629 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12630 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12631 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12632 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12633 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12634 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12635 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12636 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12637 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12638 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +000012639 }
12640 return m_arm_isa != 0;
12641}
12642
Caroline Tice080bf612011-04-05 18:46:00 +000012643bool
Greg Clayton888a7332011-04-26 04:39:08 +000012644EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012645{
Greg Clayton888a7332011-04-26 04:39:08 +000012646 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12647 {
12648 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12649 m_opcode_mode = eModeThumb;
12650 else
12651 {
12652 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012653
Greg Clayton888a7332011-04-26 04:39:08 +000012654 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12655 m_opcode_mode = eModeARM;
12656 else if (addr_class == eAddressClassCodeAlternateISA)
12657 m_opcode_mode = eModeThumb;
12658 else
12659 return false;
12660 }
12661 if (m_opcode_mode == eModeThumb)
12662 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12663 else
12664 m_opcode_cpsr = CPSR_MODE_USR;
12665 return true;
12666 }
12667 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012668}
Greg Clayton31e2a382011-01-30 20:03:56 +000012669
Greg Clayton64c84432011-01-21 22:02:52 +000012670bool
12671EmulateInstructionARM::ReadInstruction ()
12672{
12673 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012674 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012675 if (success)
12676 {
12677 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12678 if (success)
12679 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012680 Context read_inst_context;
12681 read_inst_context.type = eContextReadOpcode;
12682 read_inst_context.SetNoArgs ();
12683
Greg Claytonb3448432011-03-24 21:19:54 +000012684 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012685 {
Greg Claytonb3448432011-03-24 21:19:54 +000012686 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012687 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012688
12689 if (success)
12690 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012691 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012692 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012693 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012694 }
12695 else
12696 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012697 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012698 }
12699 }
12700 }
12701 else
12702 {
Greg Claytonb3448432011-03-24 21:19:54 +000012703 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012704 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012705 }
12706 }
12707 }
12708 if (!success)
12709 {
Greg Claytonb3448432011-03-24 21:19:54 +000012710 m_opcode_mode = eModeInvalid;
12711 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012712 }
12713 return success;
12714}
12715
Johnny Chenee9b1f72011-02-09 01:00:31 +000012716uint32_t
12717EmulateInstructionARM::ArchVersion ()
12718{
12719 return m_arm_isa;
12720}
12721
Greg Clayton64c84432011-01-21 22:02:52 +000012722bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012723EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012724{
Greg Clayton888a7332011-04-26 04:39:08 +000012725 // If we are ignoring conditions, then always return true.
12726 // this allows us to iterate over disassembly code and still
12727 // emulate an instruction even if we don't have all the right
12728 // bits set in the CPSR register...
12729 if (m_ignore_conditions)
12730 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000012731
Greg Clayton7bc39082011-03-24 23:53:38 +000012732 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012733
12734 if (cond == UINT32_MAX)
12735 return false;
12736
12737 bool result = false;
12738 switch (UnsignedBits(cond, 3, 1))
12739 {
Caroline Tice080bf612011-04-05 18:46:00 +000012740 case 0:
12741 if (m_opcode_cpsr == 0)
12742 return true;
12743 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12744 break;
12745 case 1:
12746 if (m_opcode_cpsr == 0)
12747 return true;
12748 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12749 break;
12750 case 2:
12751 if (m_opcode_cpsr == 0)
12752 return true;
12753 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12754 break;
12755 case 3:
12756 if (m_opcode_cpsr == 0)
12757 return true;
12758 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12759 break;
12760 case 4:
12761 if (m_opcode_cpsr == 0)
12762 return true;
12763 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12764 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012765 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012766 if (m_opcode_cpsr == 0)
12767 return true;
12768 else
12769 {
Greg Claytonb3448432011-03-24 21:19:54 +000012770 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12771 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012772 result = n == v;
12773 }
12774 break;
12775 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012776 if (m_opcode_cpsr == 0)
12777 return true;
12778 else
12779 {
Greg Claytonb3448432011-03-24 21:19:54 +000012780 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12781 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12782 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012783 }
12784 break;
12785 case 7:
12786 result = true;
12787 break;
12788 }
12789
12790 if (cond & 1)
12791 result = !result;
12792 return result;
12793}
12794
Johnny Chen9ee056b2011-02-08 00:06:35 +000012795uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012796EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012797{
Greg Claytonb3448432011-03-24 21:19:54 +000012798 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012799 {
12800 default:
12801 case eModeInvalid:
12802 break;
12803
12804 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012805 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012806
12807 case eModeThumb:
12808 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12809 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012810 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012811 const uint32_t byte_size = m_opcode.GetByteSize();
12812 if (byte_size == 2)
12813 {
12814 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12815 return Bits32(opcode, 11, 7);
12816 }
12817 else
12818 {
12819 assert (byte_size == 4);
12820 if (Bits32(opcode, 31, 27) == 0x1e &&
12821 Bits32(opcode, 15, 14) == 0x02 &&
12822 Bits32(opcode, 12, 12) == 0x00 &&
12823 Bits32(opcode, 25, 22) <= 0x0d)
12824 {
12825 return Bits32(opcode, 25, 22);
12826 }
12827 }
12828
12829 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012830 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012831 }
12832 return UINT32_MAX; // Return invalid value
12833}
12834
Johnny Chen9ee056b2011-02-08 00:06:35 +000012835bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012836EmulateInstructionARM::InITBlock()
12837{
12838 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12839}
12840
12841bool
12842EmulateInstructionARM::LastInITBlock()
12843{
12844 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12845}
12846
Caroline Ticeb27771d2011-03-03 22:37:46 +000012847bool
12848EmulateInstructionARM::BadMode (uint32_t mode)
12849{
12850
12851 switch (mode)
12852 {
12853 case 16: return false; // '10000'
12854 case 17: return false; // '10001'
12855 case 18: return false; // '10010'
12856 case 19: return false; // '10011'
12857 case 22: return false; // '10110'
12858 case 23: return false; // '10111'
12859 case 27: return false; // '11011'
12860 case 31: return false; // '11111'
12861 default: return true;
12862 }
12863 return true;
12864}
12865
12866bool
12867EmulateInstructionARM::CurrentModeIsPrivileged ()
12868{
Greg Claytonb3448432011-03-24 21:19:54 +000012869 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012870
12871 if (BadMode (mode))
12872 return false;
12873
12874 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000012875 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012876
12877 return true;
12878}
12879
12880void
12881EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
12882{
12883 bool privileged = CurrentModeIsPrivileged();
12884
12885 uint32_t tmp_cpsr = 0;
12886
Greg Claytonb3448432011-03-24 21:19:54 +000012887 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012888
12889 if (BitIsSet (bytemask, 3))
12890 {
12891 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
12892 if (affect_execstate)
12893 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
12894 }
12895
12896 if (BitIsSet (bytemask, 2))
12897 {
12898 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
12899 }
12900
12901 if (BitIsSet (bytemask, 1))
12902 {
12903 if (affect_execstate)
12904 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
12905 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
12906 if (privileged)
12907 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
12908 }
12909
12910 if (BitIsSet (bytemask, 0))
12911 {
12912 if (privileged)
12913 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
12914 if (affect_execstate)
12915 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
12916 if (privileged)
12917 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
12918 }
12919
Greg Claytonb3448432011-03-24 21:19:54 +000012920 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012921}
12922
12923
Johnny Chen098ae2d2011-02-12 00:50:05 +000012924bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000012925EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
12926{
12927 addr_t target;
12928
Johnny Chenee9b1f72011-02-09 01:00:31 +000012929 // Check the current instruction set.
12930 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012931 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012932 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000012933 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012934
Johnny Chen9ee056b2011-02-08 00:06:35 +000012935 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012936 return false;
12937
12938 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012939}
12940
12941// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
12942bool
Johnny Chen668b4512011-02-15 21:08:58 +000012943EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012944{
12945 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000012946 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
12947 // we want to record it and issue a WriteRegister callback so the clients
12948 // can track the mode changes accordingly.
12949 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012950
12951 if (BitIsSet(addr, 0))
12952 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012953 if (CurrentInstrSet() != eModeThumb)
12954 {
12955 SelectInstrSet(eModeThumb);
12956 cpsr_changed = true;
12957 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012958 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000012959 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012960 }
12961 else if (BitIsClear(addr, 1))
12962 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012963 if (CurrentInstrSet() != eModeARM)
12964 {
12965 SelectInstrSet(eModeARM);
12966 cpsr_changed = true;
12967 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012968 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000012969 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012970 }
12971 else
12972 return false; // address<1:0> == '10' => UNPREDICTABLE
12973
Johnny Chen0f309db2011-02-09 19:11:32 +000012974 if (cpsr_changed)
12975 {
Johnny Chen558133b2011-02-09 23:59:17 +000012976 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000012977 return false;
12978 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012979 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012980 return false;
12981
12982 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012983}
Greg Clayton64c84432011-01-21 22:02:52 +000012984
Johnny Chenee9b1f72011-02-09 01:00:31 +000012985// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
12986bool
Johnny Chen668b4512011-02-15 21:08:58 +000012987EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000012988{
12989 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000012990 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000012991 else
12992 return BranchWritePC((const Context)context, addr);
12993}
12994
Johnny Chen26863dc2011-02-09 23:43:29 +000012995// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
12996bool
Johnny Chen668b4512011-02-15 21:08:58 +000012997EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000012998{
12999 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013000 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013001 else
13002 return BranchWritePC((const Context)context, addr);
13003}
13004
Johnny Chenee9b1f72011-02-09 01:00:31 +000013005EmulateInstructionARM::Mode
13006EmulateInstructionARM::CurrentInstrSet ()
13007{
Greg Claytonb3448432011-03-24 21:19:54 +000013008 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013009}
13010
Greg Claytonb3448432011-03-24 21:19:54 +000013011// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013012// ReadInstruction() is performed. This function has a side effect of updating
13013// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013014bool
13015EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13016{
Greg Claytonb3448432011-03-24 21:19:54 +000013017 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013018 switch (arm_or_thumb)
13019 {
13020 default:
13021 return false;
13022 eModeARM:
13023 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013024 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013025 break;
13026 eModeThumb:
13027 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013028 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013029 break;
13030 }
13031 return true;
13032}
13033
Johnny Chenef21b592011-02-10 01:52:38 +000013034// This function returns TRUE if the processor currently provides support for
13035// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13036// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13037bool
13038EmulateInstructionARM::UnalignedSupport()
13039{
13040 return (ArchVersion() >= ARMv7);
13041}
13042
Johnny Chenbf6ad172011-02-11 01:29:53 +000013043// The main addition and subtraction instructions can produce status information
13044// about both unsigned carry and signed overflow conditions. This status
13045// information can be used to synthesize multi-word additions and subtractions.
13046EmulateInstructionARM::AddWithCarryResult
13047EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13048{
13049 uint32_t result;
13050 uint8_t carry_out;
13051 uint8_t overflow;
13052
13053 uint64_t unsigned_sum = x + y + carry_in;
13054 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13055
13056 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013057// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013058 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013059
13060 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013061 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013062 else
13063 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013064
13065 AddWithCarryResult res = { result, carry_out, overflow };
13066 return res;
13067}
13068
Johnny Chen157b9592011-02-18 21:13:05 +000013069uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013070EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013071{
Johnny Chene39f22d2011-02-19 01:36:13 +000013072 uint32_t reg_kind, reg_num;
13073 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013074 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013075 case SP_REG:
13076 reg_kind = eRegisterKindGeneric;
13077 reg_num = LLDB_REGNUM_GENERIC_SP;
13078 break;
13079 case LR_REG:
13080 reg_kind = eRegisterKindGeneric;
13081 reg_num = LLDB_REGNUM_GENERIC_RA;
13082 break;
13083 case PC_REG:
13084 reg_kind = eRegisterKindGeneric;
13085 reg_num = LLDB_REGNUM_GENERIC_PC;
13086 break;
13087 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013088 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013089 {
13090 reg_kind = eRegisterKindDWARF;
13091 reg_num = dwarf_r0 + num;
13092 }
Johnny Chen157b9592011-02-18 21:13:05 +000013093 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013094 {
13095 assert(0 && "Invalid register number");
13096 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013097 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013098 }
13099 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013100 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013101
13102 // Read our register.
13103 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13104
13105 // When executing an ARM instruction , PC reads as the address of the current
13106 // instruction plus 8.
13107 // When executing a Thumb instruction , PC reads as the address of the current
13108 // instruction plus 4.
13109 if (num == 15)
13110 {
13111 if (CurrentInstrSet() == eModeARM)
13112 val += 8;
13113 else
13114 val += 4;
13115 }
Johnny Chen157b9592011-02-18 21:13:05 +000013116
13117 return val;
13118}
13119
Johnny Chenca67d1c2011-02-17 01:35:27 +000013120// Write the result to the ARM core register Rd, and optionally update the
13121// condition flags based on the result.
13122//
13123// This helper method tries to encapsulate the following pseudocode from the
13124// ARM Architecture Reference Manual:
13125//
13126// if d == 15 then // Can only occur for encoding A1
13127// ALUWritePC(result); // setflags is always FALSE here
13128// else
13129// R[d] = result;
13130// if setflags then
13131// APSR.N = result<31>;
13132// APSR.Z = IsZeroBit(result);
13133// APSR.C = carry;
13134// // APSR.V unchanged
13135//
13136// In the above case, the API client does not pass in the overflow arg, which
13137// defaults to ~0u.
13138bool
Johnny Chen10530c22011-02-17 22:37:12 +000013139EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13140 const uint32_t result,
13141 const uint32_t Rd,
13142 bool setflags,
13143 const uint32_t carry,
13144 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013145{
13146 if (Rd == 15)
13147 {
13148 if (!ALUWritePC (context, result))
13149 return false;
13150 }
13151 else
13152 {
Johnny Chena695f952011-02-23 21:24:25 +000013153 uint32_t reg_kind, reg_num;
13154 switch (Rd)
13155 {
13156 case SP_REG:
13157 reg_kind = eRegisterKindGeneric;
13158 reg_num = LLDB_REGNUM_GENERIC_SP;
13159 break;
13160 case LR_REG:
13161 reg_kind = eRegisterKindGeneric;
13162 reg_num = LLDB_REGNUM_GENERIC_RA;
13163 break;
13164 default:
13165 reg_kind = eRegisterKindDWARF;
13166 reg_num = dwarf_r0 + Rd;
13167 }
13168 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013169 return false;
13170 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013171 return WriteFlags (context, result, carry, overflow);
13172 }
13173 return true;
13174}
13175
13176// This helper method tries to encapsulate the following pseudocode from the
13177// ARM Architecture Reference Manual:
13178//
13179// APSR.N = result<31>;
13180// APSR.Z = IsZeroBit(result);
13181// APSR.C = carry;
13182// APSR.V = overflow
13183//
13184// Default arguments can be specified for carry and overflow parameters, which means
13185// not to update the respective flags.
13186bool
13187EmulateInstructionARM::WriteFlags (Context &context,
13188 const uint32_t result,
13189 const uint32_t carry,
13190 const uint32_t overflow)
13191{
Greg Claytonb3448432011-03-24 21:19:54 +000013192 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013193 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13194 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013195 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013196 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013197 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013198 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013199 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013200 {
13201 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13202 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013203 }
13204 return true;
13205}
13206
Greg Clayton64c84432011-01-21 22:02:52 +000013207bool
Greg Clayton888a7332011-04-26 04:39:08 +000013208EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013209{
Johnny Chenc315f862011-02-05 00:46:10 +000013210 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013211 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013212 m_it_session.ITAdvance();
13213
Greg Clayton888a7332011-04-26 04:39:08 +000013214 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013215
13216 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013217 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013218 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013219 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13220
13221 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013222 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013223
Greg Clayton888a7332011-04-26 04:39:08 +000013224 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13225 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013226
Greg Clayton888a7332011-04-26 04:39:08 +000013227 bool success = false;
13228 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013229 {
Greg Clayton888a7332011-04-26 04:39:08 +000013230 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
13231 dwarf_cpsr,
13232 0,
13233 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013234 }
13235
Greg Clayton888a7332011-04-26 04:39:08 +000013236 // Only return false if we are unable to read the CPSR if we care about conditions
13237 if (success == false && m_ignore_conditions == false)
13238 return false;
13239
13240 uint32_t orig_pc_value = 0;
13241 if (auto_advance_pc)
13242 {
13243 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13244 if (!success)
13245 return false;
13246 }
13247
13248 // Call the Emulate... function.
13249 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13250 if (!success)
13251 return false;
13252
13253 if (auto_advance_pc)
13254 {
13255 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13256 if (!success)
13257 return false;
13258
13259 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13260 {
13261 if (opcode_data->size == eSize32)
13262 after_pc_value += 4;
13263 else if (opcode_data->size == eSize16)
13264 after_pc_value += 2;
13265
13266 EmulateInstruction::Context context;
13267 context.type = eContextAdvancePC;
13268 context.SetNoArgs();
13269 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13270 return false;
13271
13272 }
13273 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013274 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013275}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013276
13277bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013278EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013279{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013280 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013281 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013282 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013283 return false;
13284 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013285
13286 static ConstString opcode_key ("opcode");
13287 static ConstString before_key ("before_state");
13288 static ConstString after_key ("after_state");
13289
13290 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013291
13292 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013293 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013294 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013295 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013296 return false;
13297 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013298 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013299
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013300 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13301 {
13302 m_opcode_mode = eModeARM;
13303 m_opcode.SetOpcode32 (test_opcode);
13304 }
13305 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13306 {
13307 m_opcode_mode = eModeThumb;
13308 if (test_opcode < 0x10000)
13309 m_opcode.SetOpcode16 (test_opcode);
13310 else
13311 m_opcode.SetOpcode32 (test_opcode);
13312
13313 }
13314 else
13315 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013316 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013317 return false;
13318 }
13319
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013320 EmulationStateARM before_state;
13321 EmulationStateARM after_state;
13322
Caroline Ticedfb2e202011-04-22 05:08:45 +000013323 value_sp = test_data->GetValueForKey (before_key);
13324 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013325 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013326 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013327 return false;
13328 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013329
13330 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionaryValue ();
13331 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013332 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013333 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013334 return false;
13335 }
13336
Caroline Ticedfb2e202011-04-22 05:08:45 +000013337 value_sp = test_data->GetValueForKey (after_key);
13338 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013339 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013340 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013341 return false;
13342 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013343
13344 state_dictionary = value_sp->GetAsDictionaryValue ();
13345 if (!after_state.LoadStateFromDictionary (state_dictionary))
13346 {
13347 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13348 return false;
13349 }
13350
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013351 SetBaton ((void *) &before_state);
13352 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13353 &EmulationStateARM::WritePseudoMemory,
13354 &EmulationStateARM::ReadPseudoRegister,
13355 &EmulationStateARM::WritePseudoRegister);
13356
Greg Clayton888a7332011-04-26 04:39:08 +000013357 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013358 if (!success)
13359 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013360 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013361 return false;
13362 }
13363
13364 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013365 if (!success)
13366 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13367
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013368 return success;
13369}
13370
Greg Clayton888a7332011-04-26 04:39:08 +000013371
13372const char *
13373EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13374{
13375 if (reg_kind == eRegisterKindGeneric)
13376 {
13377 switch (reg_num)
13378 {
13379 case LLDB_REGNUM_GENERIC_PC: return "pc";
13380 case LLDB_REGNUM_GENERIC_SP: return "sp";
13381 case LLDB_REGNUM_GENERIC_FP: return "fp";
13382 case LLDB_REGNUM_GENERIC_RA: return "lr";
13383 case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13384 default: return NULL;
13385 }
13386 }
13387 else if (reg_kind == eRegisterKindDWARF)
13388 {
13389 return GetARMDWARFRegisterName (reg_num);
13390 }
13391 return NULL;
13392}
13393