blob: 9e45bc4b0a0bff90242ec51a9dd8c34343ae8ec3 [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 Claytonc07d4512011-04-26 23:48:45 +000019#include "lldb/Symbol/UnwindPlan.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000020
Greg Claytonf29a08f2011-02-09 17:41:27 +000021#include "Plugins/Process/Utility/ARMDefines.h"
22#include "Plugins/Process/Utility/ARMUtils.h"
23#include "Utility/ARM_DWARF_Registers.h"
24
Johnny Chen9b8d7832011-02-02 01:13:56 +000025#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000026 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000027
28using namespace lldb;
29using namespace lldb_private;
30
Johnny Chene97c0d52011-02-18 19:32:20 +000031// Convenient macro definitions.
Greg Claytonb3448432011-03-24 21:19:54 +000032#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
33#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000034
Caroline Ticef55261f2011-02-18 22:24:22 +000035#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
36
Johnny Chen0e00af22011-02-10 19:40:42 +000037//----------------------------------------------------------------------
38//
39// ITSession implementation
40//
41//----------------------------------------------------------------------
42
Johnny Chen93070472011-02-04 23:02:47 +000043// A8.6.50
44// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
Greg Clayton04d397c2011-05-23 18:04:09 +000045static uint32_t
46CountITSize (uint32_t ITMask) {
Johnny Chen93070472011-02-04 23:02:47 +000047 // First count the trailing zeros of the IT mask.
Greg Clayton04d397c2011-05-23 18:04:09 +000048 uint32_t TZ = llvm::CountTrailingZeros_32(ITMask);
Johnny Chen93070472011-02-04 23:02:47 +000049 if (TZ > 3)
50 {
51 printf("Encoding error: IT Mask '0000'\n");
52 return 0;
53 }
54 return (4 - TZ);
55}
56
57// Init ITState. Note that at least one bit is always 1 in mask.
Greg Clayton04d397c2011-05-23 18:04:09 +000058bool ITSession::InitIT(uint32_t bits7_0)
Johnny Chen93070472011-02-04 23:02:47 +000059{
60 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
61 if (ITCounter == 0)
62 return false;
63
64 // A8.6.50 IT
65 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
66 if (FirstCond == 0xF)
67 {
68 printf("Encoding error: IT FirstCond '1111'\n");
69 return false;
70 }
71 if (FirstCond == 0xE && ITCounter != 1)
72 {
73 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
74 return false;
75 }
76
77 ITState = bits7_0;
78 return true;
79}
80
81// Update ITState if necessary.
82void ITSession::ITAdvance()
83{
84 assert(ITCounter);
85 --ITCounter;
86 if (ITCounter == 0)
87 ITState = 0;
88 else
89 {
90 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
91 SetBits32(ITState, 4, 0, NewITState4_0);
92 }
93}
94
95// Return true if we're inside an IT Block.
96bool ITSession::InITBlock()
97{
98 return ITCounter != 0;
99}
100
Johnny Chenc315f862011-02-05 00:46:10 +0000101// Return true if we're the last instruction inside an IT Block.
102bool ITSession::LastInITBlock()
103{
104 return ITCounter == 1;
105}
106
Johnny Chen93070472011-02-04 23:02:47 +0000107// Get condition bits for the current thumb instruction.
108uint32_t ITSession::GetCond()
109{
Johnny Chenc315f862011-02-05 00:46:10 +0000110 if (InITBlock())
111 return Bits32(ITState, 7, 4);
112 else
113 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000114}
115
Greg Clayton64c84432011-01-21 22:02:52 +0000116// ARM constants used during decoding
117#define REG_RD 0
118#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000119#define SP_REG 13
120#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000121#define PC_REG 15
122#define PC_REGLIST_BIT 0x8000
123
Johnny Chen251af6a2011-01-21 22:47:25 +0000124#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000125#define ARMv4T (1u << 1)
126#define ARMv5T (1u << 2)
127#define ARMv5TE (1u << 3)
128#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000129#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000130#define ARMv6K (1u << 6)
131#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000132#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000133#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000134#define ARMvAll (0xffffffffu)
135
Johnny Chen9b8d7832011-02-02 01:13:56 +0000136#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
137#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice1697dd72011-03-30 17:11:45 +0000138#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000139#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000140#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000141#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton04d397c2011-05-23 18:04:09 +0000142#define ARMV7_ABOVE (ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000143
Caroline Tice4f605582011-03-31 00:02:51 +0000144#define No_VFP 0
145#define VFPv1 (1u << 1)
146#define VFPv2 (1u << 2)
147#define VFPv3 (1u << 3)
148#define AdvancedSIMD (1u << 4)
149
150#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
151#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
152#define VFPv2v3 (VFPv2 | VFPv3)
153
Johnny Chen0e00af22011-02-10 19:40:42 +0000154//----------------------------------------------------------------------
155//
156// EmulateInstructionARM implementation
157//
158//----------------------------------------------------------------------
159
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000160void
161EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000162{
Caroline Tice080bf612011-04-05 18:46:00 +0000163 PluginManager::RegisterPlugin (GetPluginNameStatic (),
164 GetPluginDescriptionStatic (),
165 CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000166}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000167
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000168void
169EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000170{
Caroline Tice080bf612011-04-05 18:46:00 +0000171 PluginManager::UnregisterPlugin (CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000172}
173
Caroline Tice080bf612011-04-05 18:46:00 +0000174const char *
175EmulateInstructionARM::GetPluginNameStatic ()
176{
177 return "lldb.emulate-instruction.arm";
178}
179
180const char *
181EmulateInstructionARM::GetPluginDescriptionStatic ()
182{
183 return "Emulate instructions for the ARM architecture.";
184}
185
186EmulateInstruction *
Greg Clayton888a7332011-04-26 04:39:08 +0000187EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
Caroline Tice080bf612011-04-05 18:46:00 +0000188{
Greg Clayton888a7332011-04-26 04:39:08 +0000189 if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
Caroline Tice080bf612011-04-05 18:46:00 +0000190 {
Greg Clayton888a7332011-04-26 04:39:08 +0000191 if (arch.GetTriple().getArch() == llvm::Triple::arm)
192 {
193 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
194
195 if (emulate_insn_ap.get())
196 return emulate_insn_ap.release();
197 }
198 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
199 {
200 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
201
202 if (emulate_insn_ap.get())
203 return emulate_insn_ap.release();
204 }
Caroline Tice080bf612011-04-05 18:46:00 +0000205 }
206
207 return NULL;
208}
209
210bool
211EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
212{
213 if (arch.GetTriple().getArch () == llvm::Triple::arm)
214 return true;
215 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
216 return true;
217
218 return false;
219}
220
Caroline Ticefa172202011-02-11 22:49:54 +0000221// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
222bool
223EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
224{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000225 EmulateInstruction::Context context;
226 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
227 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000228
229 uint32_t random_data = rand ();
230 const uint32_t addr_byte_size = GetAddressByteSize();
231
Caroline Ticecc96eb52011-02-17 19:20:40 +0000232 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000233 return false;
234
235 return true;
236}
237
Caroline Tice713c2662011-02-11 17:59:55 +0000238// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
239bool
240EmulateInstructionARM::WriteBits32Unknown (int n)
241{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000242 EmulateInstruction::Context context;
243 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
244 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000245
Johnny Chen62ff6f52011-02-11 18:11:22 +0000246 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000247 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
248
249 if (!success)
250 return false;
251
252 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
253 return false;
254
255 return true;
256}
257
Greg Claytonc07d4512011-04-26 23:48:45 +0000258bool
259EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
260{
261 if (reg_kind == eRegisterKindGeneric)
262 {
263 switch (reg_num)
264 {
265 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break;
266 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break;
267 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break;
268 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break;
269 case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break;
270 default: return false;
271 }
272 }
273
274 if (reg_kind == eRegisterKindDWARF)
275 return GetARMDWARFRegisterInfo(reg_num, reg_info);
276 return false;
277}
278
Greg Clayton04d397c2011-05-23 18:04:09 +0000279uint32_t
280EmulateInstructionARM::GetFramePointerRegisterNumber () const
281{
282 if (m_opcode_mode == eModeThumb || m_arch.GetTriple().getOS() == llvm::Triple::Darwin)
283 return 7;
284 else
285 return 11;
286}
287
288uint32_t
289EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const
290{
291 if (m_opcode_mode == eModeThumb || m_arch.GetTriple().getOS() == llvm::Triple::Darwin)
292 return dwarf_r7;
293 else
294 return dwarf_r11;
295}
296
Johnny Chen08c25e82011-01-31 18:02:28 +0000297// Push Multiple Registers stores multiple registers to the stack, storing to
298// consecutive memory locations ending just below the address in SP, and updates
299// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000300bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000301EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000302{
303#if 0
304 // ARM pseudo code...
305 if (ConditionPassed())
306 {
307 EncodingSpecificOperations();
308 NullCheckIfThumbEE(13);
309 address = SP - 4*BitCount(registers);
310
311 for (i = 0 to 14)
312 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000313 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000314 {
315 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
316 MemA[address,4] = bits(32) UNKNOWN;
317 else
318 MemA[address,4] = R[i];
319 address = address + 4;
320 }
321 }
322
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000323 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000324 MemA[address,4] = PCStoreValue();
325
326 SP = SP - 4*BitCount(registers);
327 }
328#endif
329
330 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000331 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000332 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000333 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000334 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000335 if (!success)
336 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000337 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000338 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000339 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000340 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000341 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000342 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000343 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000344 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000345 // if BitCount(registers) < 1 then UNPREDICTABLE;
346 if (BitCount(registers) < 1)
347 return false;
348 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000349 case eEncodingT2:
350 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000351 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000352 // if BitCount(registers) < 2 then UNPREDICTABLE;
353 if (BitCount(registers) < 2)
354 return false;
355 break;
356 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000357 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000358 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000359 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000360 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000361 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000362 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000363 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000364 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000365 // Instead of return false, let's handle the following case as well,
366 // which amounts to pushing one reg onto the full descending stacks.
367 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000368 break;
369 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000370 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000371 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000372 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000373 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000374 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000375 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000376 default:
377 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000378 }
Johnny Chence1ca772011-01-25 01:13:00 +0000379 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000380 addr_t addr = sp - sp_offset;
381 uint32_t i;
382
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000383 EmulateInstruction::Context context;
384 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000385 RegisterInfo reg_info;
386 RegisterInfo sp_reg;
387 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Clayton64c84432011-01-21 22:02:52 +0000388 for (i=0; i<15; ++i)
389 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000390 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000391 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000392 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
393 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000394 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000395 if (!success)
396 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000397 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000398 return false;
399 addr += addr_byte_size;
400 }
401 }
402
Johnny Chen7c1bf922011-02-08 23:49:37 +0000403 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000404 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000405 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info);
406 context.SetRegisterPlusOffset (reg_info, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000407 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000408 if (!success)
409 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000410 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000411 return false;
412 }
413
414 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000415 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000416
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000417 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000418 return false;
419 }
420 return true;
421}
422
Johnny Chenef85e912011-01-31 23:07:40 +0000423// Pop Multiple Registers loads multiple registers from the stack, loading from
424// consecutive memory locations staring at the address in SP, and updates
425// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000426bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000427EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000428{
429#if 0
430 // ARM pseudo code...
431 if (ConditionPassed())
432 {
433 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
434 address = SP;
435 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000436 if registers<i> == '1' then
Greg Claytonc07d4512011-04-26 23:48:45 +0000437 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000438 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000439 if UnalignedAllowed then
440 LoadWritePC(MemU[address,4]);
441 else
442 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000443 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
444 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000445 }
446#endif
447
448 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000449
Greg Claytonc07d4512011-04-26 23:48:45 +0000450 if (ConditionPassed(opcode)) {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000451 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000452 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000453 if (!success)
454 return false;
455 uint32_t registers = 0;
456 uint32_t Rt; // the destination register
457 switch (encoding) {
458 case eEncodingT1:
459 registers = Bits32(opcode, 7, 0);
460 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000461 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000462 registers |= (1u << 15);
463 // if BitCount(registers) < 1 then UNPREDICTABLE;
464 if (BitCount(registers) < 1)
465 return false;
466 break;
467 case eEncodingT2:
468 // Ignore bit 13.
469 registers = Bits32(opcode, 15, 0) & ~0x2000;
470 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000471 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000472 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000473 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
474 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
475 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000476 break;
477 case eEncodingT3:
478 Rt = Bits32(opcode, 15, 12);
479 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000480 if (Rt == 13)
481 return false;
482 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000483 return false;
484 registers = (1u << Rt);
485 break;
486 case eEncodingA1:
487 registers = Bits32(opcode, 15, 0);
488 // Instead of return false, let's handle the following case as well,
489 // which amounts to popping one reg from the full descending stacks.
490 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
491
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000492 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000493 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000494 return false;
495 break;
496 case eEncodingA2:
497 Rt = Bits32(opcode, 15, 12);
498 // if t == 13 then UNPREDICTABLE;
499 if (Rt == dwarf_sp)
500 return false;
501 registers = (1u << Rt);
502 break;
503 default:
504 return false;
505 }
506 addr_t sp_offset = addr_byte_size * BitCount (registers);
507 addr_t addr = sp;
508 uint32_t i, data;
509
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000510 EmulateInstruction::Context context;
511 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000512
513 RegisterInfo sp_reg;
514 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
515
Johnny Chenef85e912011-01-31 23:07:40 +0000516 for (i=0; i<15; ++i)
517 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000518 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000519 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000520 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000521 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000522 if (!success)
523 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +0000524 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000525 return false;
526 addr += addr_byte_size;
527 }
528 }
529
Johnny Chen7c1bf922011-02-08 23:49:37 +0000530 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000531 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000532 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000533 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000534 if (!success)
535 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000536 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000537 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000538 return false;
539 addr += addr_byte_size;
540 }
541
542 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000543 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000544
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000545 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000546 return false;
547 }
548 return true;
549}
550
Johnny Chen5b442b72011-01-27 19:34:30 +0000551// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000552// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000553bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000554EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000555{
556#if 0
557 // ARM pseudo code...
558 if (ConditionPassed())
559 {
560 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000561 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000562 if d == 15 then
563 ALUWritePC(result); // setflags is always FALSE here
564 else
565 R[d] = result;
566 if setflags then
567 APSR.N = result<31>;
568 APSR.Z = IsZeroBit(result);
569 APSR.C = carry;
570 APSR.V = overflow;
571 }
572#endif
573
574 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000575
Greg Clayton7bc39082011-03-24 23:53:38 +0000576 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000577 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000578 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000579 if (!success)
580 return false;
581 uint32_t Rd; // the destination register
582 uint32_t imm32;
583 switch (encoding) {
584 case eEncodingT1:
585 Rd = 7;
586 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
587 break;
588 case eEncodingA1:
589 Rd = Bits32(opcode, 15, 12);
590 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
591 break;
592 default:
593 return false;
594 }
595 addr_t sp_offset = imm32;
596 addr_t addr = sp + sp_offset; // a pointer to the stack area
597
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000598 EmulateInstruction::Context context;
Greg Clayton75906e42011-05-11 18:39:18 +0000599 context.type = eContextSetFramePointer;
Greg Claytonc07d4512011-04-26 23:48:45 +0000600 RegisterInfo sp_reg;
601 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000602 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000603
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000604 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000605 return false;
606 }
607 return true;
608}
609
Johnny Chen2ccad832011-01-28 19:57:25 +0000610// Set r7 or ip to the current stack pointer.
611// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000612bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000613EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000614{
615#if 0
616 // ARM pseudo code...
617 if (ConditionPassed())
618 {
619 EncodingSpecificOperations();
620 result = R[m];
621 if d == 15 then
622 ALUWritePC(result); // setflags is always FALSE here
623 else
624 R[d] = result;
625 if setflags then
626 APSR.N = result<31>;
627 APSR.Z = IsZeroBit(result);
628 // APSR.C unchanged
629 // APSR.V unchanged
630 }
631#endif
632
633 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000634
Greg Clayton7bc39082011-03-24 23:53:38 +0000635 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000636 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000637 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000638 if (!success)
639 return false;
640 uint32_t Rd; // the destination register
641 switch (encoding) {
642 case eEncodingT1:
643 Rd = 7;
644 break;
645 case eEncodingA1:
646 Rd = 12;
647 break;
648 default:
649 return false;
650 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000651
652 EmulateInstruction::Context context;
Greg Clayton04d397c2011-05-23 18:04:09 +0000653 if (Rd == GetFramePointerRegisterNumber())
654 context.type = EmulateInstruction::eContextSetFramePointer;
655 else
656 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +0000657 RegisterInfo sp_reg;
658 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000659 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000660
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000661 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000662 return false;
663 }
664 return true;
665}
666
Johnny Chen1c13b622011-01-29 00:11:15 +0000667// Move from high register (r8-r15) to low register (r0-r7).
668// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000669bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000670EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000671{
Greg Clayton7bc39082011-03-24 23:53:38 +0000672 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000673}
674
675// Move from register to register.
676// MOV (register)
677bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000678EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000679{
Johnny Chen1c13b622011-01-29 00:11:15 +0000680#if 0
681 // ARM pseudo code...
682 if (ConditionPassed())
683 {
684 EncodingSpecificOperations();
685 result = R[m];
686 if d == 15 then
687 ALUWritePC(result); // setflags is always FALSE here
688 else
689 R[d] = result;
690 if setflags then
691 APSR.N = result<31>;
692 APSR.Z = IsZeroBit(result);
693 // APSR.C unchanged
694 // APSR.V unchanged
695 }
696#endif
697
698 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000699
Greg Clayton7bc39082011-03-24 23:53:38 +0000700 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000701 {
702 uint32_t Rm; // the source register
703 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000704 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000705 switch (encoding) {
706 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000707 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000708 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000709 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000710 if (Rd == 15 && InITBlock() && !LastInITBlock())
711 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000712 break;
713 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000714 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000715 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000716 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000717 if (InITBlock())
718 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000719 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000720 case eEncodingT3:
721 Rd = Bits32(opcode, 11, 8);
722 Rm = Bits32(opcode, 3, 0);
723 setflags = BitIsSet(opcode, 20);
724 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
725 if (setflags && (BadReg(Rd) || BadReg(Rm)))
726 return false;
727 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
728 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
729 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000730 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000731 case eEncodingA1:
732 Rd = Bits32(opcode, 15, 12);
733 Rm = Bits32(opcode, 3, 0);
734 setflags = BitIsSet(opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +0000735
Johnny Chen01d61572011-02-25 00:23:25 +0000736 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000737 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000738 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000739 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000740 default:
741 return false;
742 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000743 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000744 if (!success)
745 return false;
746
747 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000748 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000749 context.type = EmulateInstruction::eContextRegisterLoad;
Greg Claytonc07d4512011-04-26 23:48:45 +0000750 RegisterInfo dwarf_reg;
751 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000752 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000753
Johnny Chen10530c22011-02-17 22:37:12 +0000754 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000755 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000756 }
757 return true;
758}
759
Johnny Chen357c30f2011-02-14 22:04:25 +0000760// Move (immediate) writes an immediate value to the destination register. It
761// can optionally update the condition flags based on the value.
762// MOV (immediate)
763bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000764EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000765{
766#if 0
767 // ARM pseudo code...
768 if (ConditionPassed())
769 {
770 EncodingSpecificOperations();
771 result = imm32;
772 if d == 15 then // Can only occur for ARM encoding
773 ALUWritePC(result); // setflags is always FALSE here
774 else
775 R[d] = result;
776 if setflags then
777 APSR.N = result<31>;
778 APSR.Z = IsZeroBit(result);
779 APSR.C = carry;
780 // APSR.V unchanged
781 }
782#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000783
Greg Clayton7bc39082011-03-24 23:53:38 +0000784 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000785 {
786 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000787 uint32_t imm32; // the immediate value to be written to Rd
788 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
789 bool setflags;
790 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000791 case eEncodingT1:
792 Rd = Bits32(opcode, 10, 8);
793 setflags = !InITBlock();
794 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
795 carry = APSR_C;
796
797 break;
798
799 case eEncodingT2:
800 Rd = Bits32(opcode, 11, 8);
801 setflags = BitIsSet(opcode, 20);
802 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
803 if (BadReg(Rd))
804 return false;
805
806 break;
807
808 case eEncodingT3:
809 {
810 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
811 Rd = Bits32 (opcode, 11, 8);
812 setflags = false;
813 uint32_t imm4 = Bits32 (opcode, 19, 16);
814 uint32_t imm3 = Bits32 (opcode, 14, 12);
815 uint32_t i = Bit32 (opcode, 26);
816 uint32_t imm8 = Bits32 (opcode, 7, 0);
817 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
818
819 // if BadReg(d) then UNPREDICTABLE;
820 if (BadReg (Rd))
821 return false;
822 }
823 break;
824
825 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +0000826 // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
Caroline Tice89c6d582011-03-29 19:53:44 +0000827 Rd = Bits32 (opcode, 15, 12);
828 setflags = BitIsSet (opcode, 20);
829 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000830
Greg Clayton061b79d2011-05-09 20:18:18 +0000831 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +0000832 if ((Rd == 15) && setflags)
833 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000834
835 break;
836
837 case eEncodingA2:
838 {
839 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
840 Rd = Bits32 (opcode, 15, 12);
841 setflags = false;
842 uint32_t imm4 = Bits32 (opcode, 19, 16);
843 uint32_t imm12 = Bits32 (opcode, 11, 0);
844 imm32 = (imm4 << 12) | imm12;
845
846 // if d == 15 then UNPREDICTABLE;
847 if (Rd == 15)
848 return false;
849 }
850 break;
851
852 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000853 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000854 }
855 uint32_t result = imm32;
856
857 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000858 EmulateInstruction::Context context;
859 context.type = EmulateInstruction::eContextImmediate;
860 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000861
Johnny Chen10530c22011-02-17 22:37:12 +0000862 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000863 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000864 }
865 return true;
866}
867
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000868// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
869// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
870// unsigned values.
871//
872// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
873// limited to only a few forms of the instruction.
874bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000875EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000876{
877#if 0
878 if ConditionPassed() then
879 EncodingSpecificOperations();
880 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
881 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
882 result = operand1 * operand2;
883 R[d] = result<31:0>;
884 if setflags then
885 APSR.N = result<31>;
886 APSR.Z = IsZeroBit(result);
887 if ArchVersion() == 4 then
888 APSR.C = bit UNKNOWN;
889 // else APSR.C unchanged
890 // APSR.V always unchanged
891#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000892
Greg Clayton7bc39082011-03-24 23:53:38 +0000893 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000894 {
895 uint32_t d;
896 uint32_t n;
897 uint32_t m;
898 bool setflags;
899
900 // EncodingSpecificOperations();
901 switch (encoding)
902 {
903 case eEncodingT1:
904 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
905 d = Bits32 (opcode, 2, 0);
906 n = Bits32 (opcode, 5, 3);
907 m = Bits32 (opcode, 2, 0);
908 setflags = !InITBlock();
909
910 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
911 if ((ArchVersion() < ARMv6) && (d == n))
912 return false;
913
914 break;
915
916 case eEncodingT2:
917 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
918 d = Bits32 (opcode, 11, 8);
919 n = Bits32 (opcode, 19, 16);
920 m = Bits32 (opcode, 3, 0);
921 setflags = false;
922
923 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
924 if (BadReg (d) || BadReg (n) || BadReg (m))
925 return false;
926
927 break;
928
929 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000930 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000931 d = Bits32 (opcode, 19, 16);
932 n = Bits32 (opcode, 3, 0);
933 m = Bits32 (opcode, 11, 8);
934 setflags = BitIsSet (opcode, 20);
935
936 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
937 if ((d == 15) || (n == 15) || (m == 15))
938 return false;
939
940 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
941 if ((ArchVersion() < ARMv6) && (d == n))
942 return false;
943
944 break;
945
946 default:
947 return false;
948 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000949
950 bool success = false;
951
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000952 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
953 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
954 if (!success)
955 return false;
956
957 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
958 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
959 if (!success)
960 return false;
961
962 // result = operand1 * operand2;
963 uint64_t result = operand1 * operand2;
964
965 // R[d] = result<31:0>;
Greg Claytonc07d4512011-04-26 23:48:45 +0000966 RegisterInfo op1_reg;
967 RegisterInfo op2_reg;
968 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
969 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000970
971 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +0000972 context.type = eContextArithmetic;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000973 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
974
975 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
976 return false;
977
978 // if setflags then
979 if (setflags)
980 {
981 // APSR.N = result<31>;
982 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000983 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000984 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
985 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000986 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000987 {
988 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
989 return false;
990 }
991
992 // if ArchVersion() == 4 then
993 // APSR.C = bit UNKNOWN;
994 }
995 }
996 return true;
997}
998
Johnny Chend642a6a2011-02-22 01:01:03 +0000999// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
1000// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +00001001bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001002EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +00001003{
1004#if 0
1005 // ARM pseudo code...
1006 if (ConditionPassed())
1007 {
1008 EncodingSpecificOperations();
1009 result = NOT(imm32);
1010 if d == 15 then // Can only occur for ARM encoding
1011 ALUWritePC(result); // setflags is always FALSE here
1012 else
1013 R[d] = result;
1014 if setflags then
1015 APSR.N = result<31>;
1016 APSR.Z = IsZeroBit(result);
1017 APSR.C = carry;
1018 // APSR.V unchanged
1019 }
1020#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001021
Greg Clayton7bc39082011-03-24 23:53:38 +00001022 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001023 {
1024 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +00001025 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1026 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001027 bool setflags;
1028 switch (encoding) {
1029 case eEncodingT1:
1030 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001031 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001032 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001033 break;
1034 case eEncodingA1:
1035 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001036 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001037 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +00001038
Johnny Chend642a6a2011-02-22 01:01:03 +00001039 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +00001040 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001041 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001042 break;
1043 default:
1044 return false;
1045 }
1046 uint32_t result = ~imm32;
1047
1048 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001049 EmulateInstruction::Context context;
1050 context.type = EmulateInstruction::eContextImmediate;
1051 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001052
Johnny Chen10530c22011-02-17 22:37:12 +00001053 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001054 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001055 }
1056 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001057}
1058
Johnny Chend642a6a2011-02-22 01:01:03 +00001059// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1060// It can optionally update the condition flags based on the result.
1061bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001062EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001063{
1064#if 0
1065 // ARM pseudo code...
1066 if (ConditionPassed())
1067 {
1068 EncodingSpecificOperations();
1069 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1070 result = NOT(shifted);
1071 if d == 15 then // Can only occur for ARM encoding
1072 ALUWritePC(result); // setflags is always FALSE here
1073 else
1074 R[d] = result;
1075 if setflags then
1076 APSR.N = result<31>;
1077 APSR.Z = IsZeroBit(result);
1078 APSR.C = carry;
1079 // APSR.V unchanged
1080 }
1081#endif
1082
Greg Clayton7bc39082011-03-24 23:53:38 +00001083 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001084 {
1085 uint32_t Rm; // the source register
1086 uint32_t Rd; // the destination register
1087 ARM_ShifterType shift_t;
1088 uint32_t shift_n; // the shift applied to the value read from Rm
1089 bool setflags;
1090 uint32_t carry; // the carry bit after the shift operation
1091 switch (encoding) {
1092 case eEncodingT1:
1093 Rd = Bits32(opcode, 2, 0);
1094 Rm = Bits32(opcode, 5, 3);
1095 setflags = !InITBlock();
1096 shift_t = SRType_LSL;
1097 shift_n = 0;
1098 if (InITBlock())
1099 return false;
1100 break;
1101 case eEncodingT2:
1102 Rd = Bits32(opcode, 11, 8);
1103 Rm = Bits32(opcode, 3, 0);
1104 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001105 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001106 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001107 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001108 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001109 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001110 case eEncodingA1:
1111 Rd = Bits32(opcode, 15, 12);
1112 Rm = Bits32(opcode, 3, 0);
1113 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001114 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001115 break;
1116 default:
1117 return false;
1118 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001119 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001120 uint32_t value = ReadCoreReg(Rm, &success);
1121 if (!success)
1122 return false;
1123
1124 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1125 uint32_t result = ~shifted;
1126
1127 // The context specifies that an immediate is to be moved into Rd.
1128 EmulateInstruction::Context context;
1129 context.type = EmulateInstruction::eContextImmediate;
1130 context.SetNoArgs ();
1131
1132 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1133 return false;
1134 }
1135 return true;
1136}
1137
Johnny Chen788e0552011-01-27 22:52:23 +00001138// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1139// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001140bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001141EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001142{
1143#if 0
1144 // ARM pseudo code...
1145 if (ConditionPassed())
1146 {
1147 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1148 base = Align(PC,4);
1149 address = if add then (base + imm32) else (base - imm32);
1150 data = MemU[address,4];
1151 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001152 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1153 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001154 R[t] = data;
1155 else // Can only apply before ARMv7
1156 if CurrentInstrSet() == InstrSet_ARM then
1157 R[t] = ROR(data, 8*UInt(address<1:0>));
1158 else
1159 R[t] = bits(32) UNKNOWN;
1160 }
1161#endif
1162
Greg Clayton7bc39082011-03-24 23:53:38 +00001163 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001164 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001165 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001166 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001167 if (!success)
1168 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001169
1170 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001171 EmulateInstruction::Context context;
1172 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001173 RegisterInfo pc_reg;
1174 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001175 context.SetRegisterPlusOffset (pc_reg, 0);
1176
Johnny Chenc9de9102011-02-11 19:12:30 +00001177 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001178 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001179 bool add; // +imm32 or -imm32?
1180 addr_t base; // the base address
1181 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001182 uint32_t data; // the literal data value from the PC relative load
1183 switch (encoding) {
1184 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001185 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001186 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001187 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001188 break;
1189 case eEncodingT2:
1190 Rt = Bits32(opcode, 15, 12);
1191 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1192 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001193 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001194 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001195 break;
1196 default:
1197 return false;
1198 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001199
Johnny Chene39f22d2011-02-19 01:36:13 +00001200 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001201 if (add)
1202 address = base + imm32;
1203 else
1204 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001205
1206 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001207 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001208 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001209 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001210
1211 if (Rt == 15)
1212 {
1213 if (Bits32(address, 1, 0) == 0)
1214 {
1215 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001216 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001217 return false;
1218 }
1219 else
1220 return false;
1221 }
1222 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1223 {
1224 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1225 return false;
1226 }
1227 else // We don't handle ARM for now.
1228 return false;
1229
Johnny Chen788e0552011-01-27 22:52:23 +00001230 }
1231 return true;
1232}
1233
Johnny Chen5b442b72011-01-27 19:34:30 +00001234// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001235// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001236bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001237EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001238{
1239#if 0
1240 // ARM pseudo code...
1241 if (ConditionPassed())
1242 {
1243 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001244 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001245 if d == 15 then // Can only occur for ARM encoding
1246 ALUWritePC(result); // setflags is always FALSE here
1247 else
1248 R[d] = result;
1249 if setflags then
1250 APSR.N = result<31>;
1251 APSR.Z = IsZeroBit(result);
1252 APSR.C = carry;
1253 APSR.V = overflow;
1254 }
1255#endif
1256
1257 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001258
Greg Clayton7bc39082011-03-24 23:53:38 +00001259 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001260 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001261 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001262 if (!success)
1263 return false;
1264 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001265 uint32_t d;
1266 bool setflags;
1267 switch (encoding)
1268 {
1269 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001270 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001271 d = Bits32 (opcode, 10, 8);
1272 setflags = false;
1273 imm32 = (Bits32 (opcode, 7, 0) << 2);
1274
1275 break;
1276
1277 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001278 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001279 d = 13;
1280 setflags = false;
1281 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1282
1283 break;
1284
1285 default:
1286 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001287 }
1288 addr_t sp_offset = imm32;
1289 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1290
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001291 EmulateInstruction::Context context;
1292 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +00001293 RegisterInfo sp_reg;
1294 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001295 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001296
Caroline Ticee2212882011-03-22 22:38:28 +00001297 if (d == 15)
1298 {
1299 if (!ALUWritePC (context, addr))
1300 return false;
1301 }
1302 else
1303 {
1304 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1305 return false;
1306 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001307 }
1308 return true;
1309}
1310
1311// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001312// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001313bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001314EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001315{
1316#if 0
1317 // ARM pseudo code...
1318 if (ConditionPassed())
1319 {
1320 EncodingSpecificOperations();
1321 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001322 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001323 if d == 15 then
1324 ALUWritePC(result); // setflags is always FALSE here
1325 else
1326 R[d] = result;
1327 if setflags then
1328 APSR.N = result<31>;
1329 APSR.Z = IsZeroBit(result);
1330 APSR.C = carry;
1331 APSR.V = overflow;
1332 }
1333#endif
1334
1335 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001336
Greg Clayton7bc39082011-03-24 23:53:38 +00001337 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001338 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001339 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001340 if (!success)
1341 return false;
1342 uint32_t Rm; // the second operand
1343 switch (encoding) {
1344 case eEncodingT2:
1345 Rm = Bits32(opcode, 6, 3);
1346 break;
1347 default:
1348 return false;
1349 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001350 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001351 if (!success)
1352 return false;
1353
1354 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1355
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001356 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00001357 context.type = eContextArithmetic;
1358 RegisterInfo sp_reg;
1359 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1360
1361 RegisterInfo other_reg;
1362 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001363 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001364
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001365 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001366 return false;
1367 }
1368 return true;
1369}
1370
Johnny Chen9b8d7832011-02-02 01:13:56 +00001371// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1372// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1373// from Thumb to ARM.
1374// BLX (immediate)
1375bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001376EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001377{
1378#if 0
1379 // ARM pseudo code...
1380 if (ConditionPassed())
1381 {
1382 EncodingSpecificOperations();
1383 if CurrentInstrSet() == InstrSet_ARM then
1384 LR = PC - 4;
1385 else
1386 LR = PC<31:1> : '1';
1387 if targetInstrSet == InstrSet_ARM then
1388 targetAddress = Align(PC,4) + imm32;
1389 else
1390 targetAddress = PC + imm32;
1391 SelectInstrSet(targetInstrSet);
1392 BranchWritePC(targetAddress);
1393 }
1394#endif
1395
Greg Clayton7bc39082011-03-24 23:53:38 +00001396 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001397
Greg Clayton7bc39082011-03-24 23:53:38 +00001398 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001399 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001400 EmulateInstruction::Context context;
1401 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001402 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001403 if (!success)
1404 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001405 addr_t lr; // next instruction address
1406 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001407 int32_t imm32; // PC-relative offset
1408 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001409 case eEncodingT1:
1410 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001411 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001412 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001413 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001414 uint32_t J1 = Bit32(opcode, 13);
1415 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001416 uint32_t imm11 = Bits32(opcode, 10, 0);
1417 uint32_t I1 = !(J1 ^ S);
1418 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001419 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001420 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001421 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001422 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001423 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001424 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001425 break;
1426 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001427 case eEncodingT2:
1428 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001429 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001430 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001431 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001432 uint32_t J1 = Bit32(opcode, 13);
1433 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001434 uint32_t imm10L = Bits32(opcode, 10, 1);
1435 uint32_t I1 = !(J1 ^ S);
1436 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001437 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001438 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001439 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001440 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001441 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001442 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001443 break;
1444 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001445 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001446 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001447 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001448 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001449 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001450 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001451 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001452 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001453 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001454 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001455 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001456 break;
1457 default:
1458 return false;
1459 }
1460 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1461 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001462 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001463 return false;
1464 }
1465 return true;
1466}
1467
1468// Branch with Link and Exchange (register) calls a subroutine at an address and
1469// instruction set specified by a register.
1470// BLX (register)
1471bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001472EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001473{
1474#if 0
1475 // ARM pseudo code...
1476 if (ConditionPassed())
1477 {
1478 EncodingSpecificOperations();
1479 target = R[m];
1480 if CurrentInstrSet() == InstrSet_ARM then
1481 next_instr_addr = PC - 4;
1482 LR = next_instr_addr;
1483 else
1484 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001485 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001486 BXWritePC(target);
1487 }
1488#endif
1489
1490 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001491
Greg Clayton7bc39082011-03-24 23:53:38 +00001492 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001493 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001494 EmulateInstruction::Context context;
1495 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001496 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001497 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001498 if (!success)
1499 return false;
1500 uint32_t Rm; // the register with the target address
1501 switch (encoding) {
1502 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001503 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001504 Rm = Bits32(opcode, 6, 3);
1505 // if m == 15 then UNPREDICTABLE;
1506 if (Rm == 15)
1507 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001508 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001509 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001510 break;
1511 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001512 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001513 Rm = Bits32(opcode, 3, 0);
1514 // if m == 15 then UNPREDICTABLE;
1515 if (Rm == 15)
1516 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001517 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001518 default:
1519 return false;
1520 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001521 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001522 if (!success)
1523 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001524 RegisterInfo dwarf_reg;
1525 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001526 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001527 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1528 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001529 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001530 return false;
1531 }
1532 return true;
1533}
1534
Johnny Chenab3b3512011-02-12 00:10:51 +00001535// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001536bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001537EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001538{
1539#if 0
1540 // ARM pseudo code...
1541 if (ConditionPassed())
1542 {
1543 EncodingSpecificOperations();
1544 BXWritePC(R[m]);
1545 }
1546#endif
1547
Greg Clayton7bc39082011-03-24 23:53:38 +00001548 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001549 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001550 EmulateInstruction::Context context;
1551 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001552 uint32_t Rm; // the register with the target address
1553 switch (encoding) {
1554 case eEncodingT1:
1555 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001556 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001557 return false;
1558 break;
1559 case eEncodingA1:
1560 Rm = Bits32(opcode, 3, 0);
1561 break;
1562 default:
1563 return false;
1564 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001565 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001566 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001567 if (!success)
1568 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001569
1570 RegisterInfo dwarf_reg;
1571 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen668b4512011-02-15 21:08:58 +00001572 context.SetRegister (dwarf_reg);
1573 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001574 return false;
1575 }
1576 return true;
1577}
1578
Johnny Chen59e6ab72011-02-24 21:01:20 +00001579// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1580// address and instruction set specified by a register as though it were a BX instruction.
1581//
1582// TODO: Emulate Jazelle architecture?
1583// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1584bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001585EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001586{
1587#if 0
1588 // ARM pseudo code...
1589 if (ConditionPassed())
1590 {
1591 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001592 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001593 BXWritePC(R[m]);
1594 else
1595 if JazelleAcceptsExecution() then
1596 SwitchToJazelleExecution();
1597 else
1598 SUBARCHITECTURE_DEFINED handler call;
1599 }
1600#endif
1601
Greg Clayton7bc39082011-03-24 23:53:38 +00001602 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001603 {
1604 EmulateInstruction::Context context;
1605 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1606 uint32_t Rm; // the register with the target address
1607 switch (encoding) {
1608 case eEncodingT1:
1609 Rm = Bits32(opcode, 19, 16);
1610 if (BadReg(Rm))
1611 return false;
1612 if (InITBlock() && !LastInITBlock())
1613 return false;
1614 break;
1615 case eEncodingA1:
1616 Rm = Bits32(opcode, 3, 0);
1617 if (Rm == 15)
1618 return false;
1619 break;
1620 default:
1621 return false;
1622 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001623 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001624 addr_t target = ReadCoreReg (Rm, &success);
1625 if (!success)
1626 return false;
1627
Greg Claytonc07d4512011-04-26 23:48:45 +00001628 RegisterInfo dwarf_reg;
1629 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen59e6ab72011-02-24 21:01:20 +00001630 context.SetRegister (dwarf_reg);
1631 if (!BXWritePC(context, target))
1632 return false;
1633 }
1634 return true;
1635}
1636
Johnny Chen0d0148e2011-01-28 02:26:08 +00001637// Set r7 to point to some ip offset.
1638// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001639bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001640EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001641{
1642#if 0
1643 // ARM pseudo code...
1644 if (ConditionPassed())
1645 {
1646 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001647 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001648 if d == 15 then // Can only occur for ARM encoding
1649 ALUWritePC(result); // setflags is always FALSE here
1650 else
1651 R[d] = result;
1652 if setflags then
1653 APSR.N = result<31>;
1654 APSR.Z = IsZeroBit(result);
1655 APSR.C = carry;
1656 APSR.V = overflow;
1657 }
1658#endif
1659
Greg Clayton7bc39082011-03-24 23:53:38 +00001660 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001661 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001662 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001663 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001664 if (!success)
1665 return false;
1666 uint32_t imm32;
1667 switch (encoding) {
1668 case eEncodingA1:
1669 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1670 break;
1671 default:
1672 return false;
1673 }
1674 addr_t ip_offset = imm32;
1675 addr_t addr = ip - ip_offset; // the adjusted ip value
1676
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001677 EmulateInstruction::Context context;
1678 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001679 RegisterInfo dwarf_reg;
1680 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001681 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001682
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001684 return false;
1685 }
1686 return true;
1687}
1688
1689// Set ip to point to some stack offset.
1690// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001691bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001692EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001693{
1694#if 0
1695 // ARM pseudo code...
1696 if (ConditionPassed())
1697 {
1698 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001699 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001700 if d == 15 then // Can only occur for ARM encoding
1701 ALUWritePC(result); // setflags is always FALSE here
1702 else
1703 R[d] = result;
1704 if setflags then
1705 APSR.N = result<31>;
1706 APSR.Z = IsZeroBit(result);
1707 APSR.C = carry;
1708 APSR.V = overflow;
1709 }
1710#endif
1711
Greg Clayton7bc39082011-03-24 23:53:38 +00001712 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001713 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001714 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001715 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001716 if (!success)
1717 return false;
1718 uint32_t imm32;
1719 switch (encoding) {
1720 case eEncodingA1:
1721 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1722 break;
1723 default:
1724 return false;
1725 }
1726 addr_t sp_offset = imm32;
1727 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1728
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001729 EmulateInstruction::Context context;
1730 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001731 RegisterInfo dwarf_reg;
1732 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001733 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001734
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001735 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001736 return false;
1737 }
1738 return true;
1739}
1740
Johnny Chenc9e747f2011-02-23 01:55:07 +00001741// This instruction subtracts an immediate value from the SP value, and writes
1742// the result to the destination register.
1743//
1744// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001745bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001746EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001747{
1748#if 0
1749 // ARM pseudo code...
1750 if (ConditionPassed())
1751 {
1752 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001753 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001754 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001755 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001756 else
1757 R[d] = result;
1758 if setflags then
1759 APSR.N = result<31>;
1760 APSR.Z = IsZeroBit(result);
1761 APSR.C = carry;
1762 APSR.V = overflow;
1763 }
1764#endif
1765
1766 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001767 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001768 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001769 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001770 if (!success)
1771 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001772
1773 uint32_t Rd;
1774 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001775 uint32_t imm32;
1776 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001777 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001778 Rd = 13;
1779 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001780 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001781 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001782 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001783 Rd = Bits32(opcode, 11, 8);
1784 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001785 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001786 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001787 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001788 if (Rd == 15 && !setflags)
1789 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001790 break;
1791 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001792 Rd = Bits32(opcode, 11, 8);
1793 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001794 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001795 if (Rd == 15)
1796 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001797 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001798 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001799 Rd = Bits32(opcode, 15, 12);
1800 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001801 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001802
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001803 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001804 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001805 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001806 break;
1807 default:
1808 return false;
1809 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001810 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1811
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001812 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001813 if (Rd == 13)
1814 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001815 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1816 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001817 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001818 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001819 }
1820 else
1821 {
1822 context.type = EmulateInstruction::eContextImmediate;
1823 context.SetNoArgs ();
1824 }
1825
1826 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001827 return false;
1828 }
1829 return true;
1830}
1831
Johnny Chen08c25e82011-01-31 18:02:28 +00001832// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001833bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001834EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001835{
1836#if 0
1837 // ARM pseudo code...
1838 if (ConditionPassed())
1839 {
1840 EncodingSpecificOperations();
1841 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1842 address = if index then offset_addr else R[n];
1843 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1844 if wback then R[n] = offset_addr;
1845 }
1846#endif
1847
1848 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001849
Greg Clayton7bc39082011-03-24 23:53:38 +00001850 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001851 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001852 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001853 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001854 if (!success)
1855 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001856 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001857 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001858 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1859
1860 bool index;
1861 bool add;
1862 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001863 switch (encoding) {
1864 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001865 Rt = Bits32(opcode, 15, 12);
1866 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001867 Rn = Bits32 (opcode, 19, 16);
1868
1869 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1870 return false;
1871
1872 index = BitIsSet (opcode, 24);
1873 add = BitIsSet (opcode, 23);
1874 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1875
1876 if (wback && ((Rn == 15) || (Rn == Rt)))
1877 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001878 break;
1879 default:
1880 return false;
1881 }
Caroline Tice3e407972011-03-18 19:41:00 +00001882 addr_t offset_addr;
1883 if (add)
1884 offset_addr = sp + imm12;
1885 else
1886 offset_addr = sp - imm12;
1887
1888 addr_t addr;
1889 if (index)
1890 addr = offset_addr;
1891 else
1892 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001893
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001894 EmulateInstruction::Context context;
1895 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001896 RegisterInfo sp_reg;
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001897 RegisterInfo dwarf_reg;
1898
Greg Claytonc07d4512011-04-26 23:48:45 +00001899 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001900 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1901 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001902 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001903 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001904 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001905 if (!success)
1906 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001907 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001908 return false;
1909 }
1910 else
1911 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001912 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001913 if (!success)
1914 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001915 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001916 return false;
1917 }
1918
Caroline Tice3e407972011-03-18 19:41:00 +00001919
1920 if (wback)
1921 {
1922 context.type = EmulateInstruction::eContextAdjustStackPointer;
1923 context.SetImmediateSigned (addr - sp);
1924 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1925 return false;
1926 }
Johnny Chence1ca772011-01-25 01:13:00 +00001927 }
1928 return true;
1929}
1930
Johnny Chen08c25e82011-01-31 18:02:28 +00001931// Vector Push stores multiple extension registers to the stack.
1932// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001933bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001934EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001935{
1936#if 0
1937 // ARM pseudo code...
1938 if (ConditionPassed())
1939 {
1940 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1941 address = SP - imm32;
1942 SP = SP - imm32;
1943 if single_regs then
1944 for r = 0 to regs-1
1945 MemA[address,4] = S[d+r]; address = address+4;
1946 else
1947 for r = 0 to regs-1
1948 // Store as two word-aligned words in the correct order for current endianness.
1949 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1950 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1951 address = address+8;
1952 }
1953#endif
1954
1955 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001956
Greg Clayton7bc39082011-03-24 23:53:38 +00001957 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001958 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001959 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001960 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001961 if (!success)
1962 return false;
1963 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001964 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001965 uint32_t imm32; // stack offset
1966 uint32_t regs; // number of registers
1967 switch (encoding) {
1968 case eEncodingT1:
1969 case eEncodingA1:
1970 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001971 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001972 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1973 // If UInt(imm8) is odd, see "FSTMX".
1974 regs = Bits32(opcode, 7, 0) / 2;
1975 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1976 if (regs == 0 || regs > 16 || (d + regs) > 32)
1977 return false;
1978 break;
1979 case eEncodingT2:
1980 case eEncodingA2:
1981 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001982 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001983 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1984 regs = Bits32(opcode, 7, 0);
1985 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1986 if (regs == 0 || regs > 16 || (d + regs) > 32)
1987 return false;
1988 break;
1989 default:
1990 return false;
1991 }
1992 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1993 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1994 addr_t sp_offset = imm32;
1995 addr_t addr = sp - sp_offset;
1996 uint32_t i;
1997
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001998 EmulateInstruction::Context context;
1999 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002000 RegisterInfo dwarf_reg;
2001 RegisterInfo sp_reg;
2002 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002003 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00002004 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002005 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002006 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00002007 // uint64_t to accommodate 64-bit registers.
Greg Clayton061b79d2011-05-09 20:18:18 +00002008 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00002009 if (!success)
2010 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002011 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00002012 return false;
2013 addr += reg_byte_size;
2014 }
2015
2016 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002017 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00002018
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002019 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00002020 return false;
2021 }
2022 return true;
2023}
2024
Johnny Chen587a0a42011-02-01 18:35:28 +00002025// Vector Pop loads multiple extension registers from the stack.
2026// It also updates SP to point just above the loaded data.
2027bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002028EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00002029{
2030#if 0
2031 // ARM pseudo code...
2032 if (ConditionPassed())
2033 {
2034 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2035 address = SP;
2036 SP = SP + imm32;
2037 if single_regs then
2038 for r = 0 to regs-1
2039 S[d+r] = MemA[address,4]; address = address+4;
2040 else
2041 for r = 0 to regs-1
2042 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2043 // Combine the word-aligned words in the correct order for current endianness.
2044 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2045 }
2046#endif
2047
2048 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002049
Greg Clayton7bc39082011-03-24 23:53:38 +00002050 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002051 {
2052 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002053 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002054 if (!success)
2055 return false;
2056 bool single_regs;
2057 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2058 uint32_t imm32; // stack offset
2059 uint32_t regs; // number of registers
2060 switch (encoding) {
2061 case eEncodingT1:
2062 case eEncodingA1:
2063 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002064 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002065 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2066 // If UInt(imm8) is odd, see "FLDMX".
2067 regs = Bits32(opcode, 7, 0) / 2;
2068 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2069 if (regs == 0 || regs > 16 || (d + regs) > 32)
2070 return false;
2071 break;
2072 case eEncodingT2:
2073 case eEncodingA2:
2074 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002075 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002076 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2077 regs = Bits32(opcode, 7, 0);
2078 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2079 if (regs == 0 || regs > 16 || (d + regs) > 32)
2080 return false;
2081 break;
2082 default:
2083 return false;
2084 }
2085 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2086 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2087 addr_t sp_offset = imm32;
2088 addr_t addr = sp;
2089 uint32_t i;
2090 uint64_t data; // uint64_t to accomodate 64-bit registers.
2091
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002092 EmulateInstruction::Context context;
2093 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002094 RegisterInfo dwarf_reg;
2095 RegisterInfo sp_reg;
2096 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002097 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002098 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002099 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002100 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002101 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002102 if (!success)
2103 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +00002104 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002105 return false;
2106 addr += reg_byte_size;
2107 }
2108
2109 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002110 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002111
2112 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2113 return false;
2114 }
2115 return true;
2116}
2117
Johnny Chenb77be412011-02-04 00:40:18 +00002118// SVC (previously SWI)
2119bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002120EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002121{
2122#if 0
2123 // ARM pseudo code...
2124 if (ConditionPassed())
2125 {
2126 EncodingSpecificOperations();
2127 CallSupervisor();
2128 }
2129#endif
2130
2131 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002132
Greg Clayton7bc39082011-03-24 23:53:38 +00002133 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002134 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002135 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002136 addr_t lr; // next instruction address
2137 if (!success)
2138 return false;
2139 uint32_t imm32; // the immediate constant
2140 uint32_t mode; // ARM or Thumb mode
2141 switch (encoding) {
2142 case eEncodingT1:
2143 lr = (pc + 2) | 1u; // return address
2144 imm32 = Bits32(opcode, 7, 0);
2145 mode = eModeThumb;
2146 break;
2147 case eEncodingA1:
2148 lr = pc + 4; // return address
2149 imm32 = Bits32(opcode, 23, 0);
2150 mode = eModeARM;
2151 break;
2152 default:
2153 return false;
2154 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002155
2156 EmulateInstruction::Context context;
2157 context.type = EmulateInstruction::eContextSupervisorCall;
Greg Claytonc07d4512011-04-26 23:48:45 +00002158 context.SetISAAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002159 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2160 return false;
2161 }
2162 return true;
2163}
2164
Johnny Chenc315f862011-02-05 00:46:10 +00002165// If Then makes up to four following instructions (the IT block) conditional.
2166bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002167EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002168{
2169#if 0
2170 // ARM pseudo code...
2171 EncodingSpecificOperations();
2172 ITSTATE.IT<7:0> = firstcond:mask;
2173#endif
2174
Johnny Chenc315f862011-02-05 00:46:10 +00002175 m_it_session.InitIT(Bits32(opcode, 7, 0));
2176 return true;
2177}
2178
Greg Clayton04d397c2011-05-23 18:04:09 +00002179bool
2180EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding)
2181{
2182 // NOP, nothing to do...
2183 return true;
2184}
2185
Johnny Chen3b620b32011-02-07 20:11:47 +00002186// Branch causes a branch to a target address.
2187bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002188EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002189{
2190#if 0
2191 // ARM pseudo code...
2192 if (ConditionPassed())
2193 {
2194 EncodingSpecificOperations();
2195 BranchWritePC(PC + imm32);
2196 }
2197#endif
2198
2199 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002200
Greg Clayton7bc39082011-03-24 23:53:38 +00002201 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002202 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002203 EmulateInstruction::Context context;
2204 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002205 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002206 if (!success)
2207 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002208 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002209 int32_t imm32; // PC-relative offset
2210 switch (encoding) {
2211 case eEncodingT1:
2212 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2213 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002214 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002215 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002216 break;
2217 case eEncodingT2:
2218 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002219 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002220 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002221 break;
2222 case eEncodingT3:
2223 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2224 {
Johnny Chenbd599902011-02-10 21:39:01 +00002225 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002226 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002227 uint32_t J1 = Bit32(opcode, 13);
2228 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002229 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002230 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002231 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002232 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002233 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002234 break;
2235 }
2236 case eEncodingT4:
2237 {
Johnny Chenbd599902011-02-10 21:39:01 +00002238 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002239 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002240 uint32_t J1 = Bit32(opcode, 13);
2241 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002242 uint32_t imm11 = Bits32(opcode, 10, 0);
2243 uint32_t I1 = !(J1 ^ S);
2244 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002245 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002246 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002247 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002248 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002249 break;
2250 }
2251 case eEncodingA1:
2252 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002253 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002254 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002255 break;
2256 default:
2257 return false;
2258 }
2259 if (!BranchWritePC(context, target))
2260 return false;
2261 }
2262 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002263}
2264
Johnny Chen53ebab72011-02-08 23:21:57 +00002265// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2266// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2267// CBNZ, CBZ
2268bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002269EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002270{
2271#if 0
2272 // ARM pseudo code...
2273 EncodingSpecificOperations();
2274 if nonzero ^ IsZero(R[n]) then
2275 BranchWritePC(PC + imm32);
2276#endif
2277
2278 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002279
2280 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002281 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002282 if (!success)
2283 return false;
2284
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002285 EmulateInstruction::Context context;
2286 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002287 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002288 if (!success)
2289 return false;
2290
2291 addr_t target; // target address
2292 uint32_t imm32; // PC-relative offset to branch forward
2293 bool nonzero;
2294 switch (encoding) {
2295 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002296 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002297 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002298 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002299 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002300 break;
2301 default:
2302 return false;
2303 }
2304 if (nonzero ^ (reg_val == 0))
2305 if (!BranchWritePC(context, target))
2306 return false;
2307
2308 return true;
2309}
2310
Johnny Chen60299ec2011-02-17 19:34:27 +00002311// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2312// A base register provides a pointer to the table, and a second register supplies an index into the table.
2313// The branch length is twice the value of the byte returned from the table.
2314//
2315// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2316// A base register provides a pointer to the table, and a second register supplies an index into the table.
2317// The branch length is twice the value of the halfword returned from the table.
2318// TBB, TBH
2319bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002320EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002321{
2322#if 0
2323 // ARM pseudo code...
2324 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2325 if is_tbh then
2326 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2327 else
2328 halfwords = UInt(MemU[R[n]+R[m], 1]);
2329 BranchWritePC(PC + 2*halfwords);
2330#endif
2331
2332 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002333
2334 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2335 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2336 bool is_tbh; // true if table branch halfword
2337 switch (encoding) {
2338 case eEncodingT1:
2339 Rn = Bits32(opcode, 19, 16);
2340 Rm = Bits32(opcode, 3, 0);
2341 is_tbh = BitIsSet(opcode, 4);
2342 if (Rn == 13 || BadReg(Rm))
2343 return false;
2344 if (InITBlock() && !LastInITBlock())
2345 return false;
2346 break;
2347 default:
2348 return false;
2349 }
2350
2351 // Read the address of the table from the operand register Rn.
2352 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002353 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002354 if (!success)
2355 return false;
2356
2357 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002358 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002359 if (!success)
2360 return false;
2361
2362 // the offsetted table address
2363 addr_t addr = base + (is_tbh ? index*2 : index);
2364
2365 // PC-relative offset to branch forward
2366 EmulateInstruction::Context context;
2367 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002368 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002369 if (!success)
2370 return false;
2371
Johnny Chene39f22d2011-02-19 01:36:13 +00002372 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002373 if (!success)
2374 return false;
2375
2376 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002377 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002378 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Greg Claytonc07d4512011-04-26 23:48:45 +00002379 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
Johnny Chen60299ec2011-02-17 19:34:27 +00002380
2381 if (!BranchWritePC(context, target))
2382 return false;
2383
2384 return true;
2385}
2386
Caroline Ticedcc11b32011-03-02 23:57:02 +00002387// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2388// It can optionally update the condition flags based on the result.
2389bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002390EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002391{
2392#if 0
2393 if ConditionPassed() then
2394 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002395 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002396 R[d] = result;
2397 if setflags then
2398 APSR.N = result<31>;
2399 APSR.Z = IsZeroBit(result);
2400 APSR.C = carry;
2401 APSR.V = overflow;
2402#endif
2403
2404 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002405
Greg Clayton7bc39082011-03-24 23:53:38 +00002406 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002407 {
2408 uint32_t d;
2409 uint32_t n;
2410 bool setflags;
2411 uint32_t imm32;
2412 uint32_t carry_out;
2413
2414 //EncodingSpecificOperations();
2415 switch (encoding)
2416 {
2417 case eEncodingT1:
2418 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2419 d = Bits32 (opcode, 2, 0);
2420 n = Bits32 (opcode, 5, 3);
2421 setflags = !InITBlock();
2422 imm32 = Bits32 (opcode, 8,6);
2423
2424 break;
2425
2426 case eEncodingT2:
2427 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2428 d = Bits32 (opcode, 10, 8);
2429 n = Bits32 (opcode, 10, 8);
2430 setflags = !InITBlock();
2431 imm32 = Bits32 (opcode, 7, 0);
2432
2433 break;
2434
2435 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002436 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2437 // if Rn == '1101' then SEE ADD (SP plus immediate);
2438 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002439 d = Bits32 (opcode, 11, 8);
2440 n = Bits32 (opcode, 19, 16);
2441 setflags = BitIsSet (opcode, 20);
2442 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2443
2444 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2445 if (BadReg (d) || (n == 15))
2446 return false;
2447
2448 break;
2449
2450 case eEncodingT4:
2451 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002452 // if Rn == '1111' then SEE ADR;
2453 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002454 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2455 d = Bits32 (opcode, 11, 8);
2456 n = Bits32 (opcode, 19, 16);
2457 setflags = false;
2458 uint32_t i = Bit32 (opcode, 26);
2459 uint32_t imm3 = Bits32 (opcode, 14, 12);
2460 uint32_t imm8 = Bits32 (opcode, 7, 0);
2461 imm32 = (i << 11) | (imm3 << 8) | imm8;
2462
2463 // if BadReg(d) then UNPREDICTABLE;
2464 if (BadReg (d))
2465 return false;
2466
2467 break;
2468 }
2469 default:
2470 return false;
2471 }
2472
2473 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2474 if (!success)
2475 return false;
2476
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002477 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002478 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2479
Greg Claytonc07d4512011-04-26 23:48:45 +00002480 RegisterInfo reg_n;
2481 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002482
2483 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002484 context.type = eContextArithmetic;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002485 context.SetRegisterPlusOffset (reg_n, imm32);
2486
2487 //R[d] = result;
2488 //if setflags then
2489 //APSR.N = result<31>;
2490 //APSR.Z = IsZeroBit(result);
2491 //APSR.C = carry;
2492 //APSR.V = overflow;
2493 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2494 return false;
2495
2496 }
2497 return true;
2498}
2499
Johnny Chen8fa20592011-02-18 01:22:22 +00002500// This instruction adds an immediate value to a register value, and writes the result to the destination
2501// register. It can optionally update the condition flags based on the result.
2502bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002503EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002504{
2505#if 0
2506 // ARM pseudo code...
2507 if ConditionPassed() then
2508 EncodingSpecificOperations();
2509 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2510 if d == 15 then
2511 ALUWritePC(result); // setflags is always FALSE here
2512 else
2513 R[d] = result;
2514 if setflags then
2515 APSR.N = result<31>;
2516 APSR.Z = IsZeroBit(result);
2517 APSR.C = carry;
2518 APSR.V = overflow;
2519#endif
2520
2521 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002522
Greg Clayton7bc39082011-03-24 23:53:38 +00002523 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002524 {
2525 uint32_t Rd, Rn;
2526 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2527 bool setflags;
2528 switch (encoding)
2529 {
2530 case eEncodingA1:
2531 Rd = Bits32(opcode, 15, 12);
2532 Rn = Bits32(opcode, 19, 16);
2533 setflags = BitIsSet(opcode, 20);
2534 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2535 break;
2536 default:
2537 return false;
2538 }
2539
Johnny Chen8fa20592011-02-18 01:22:22 +00002540 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002541 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002542 if (!success)
2543 return false;
2544
2545 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2546
2547 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002548 context.type = eContextArithmetic;
2549 RegisterInfo dwarf_reg;
2550 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00002551 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002552
2553 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2554 return false;
2555 }
2556 return true;
2557}
2558
Johnny Chend761dcf2011-02-17 22:03:29 +00002559// This instruction adds a register value and an optionally-shifted register value, and writes the result
2560// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002561bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002562EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002563{
2564#if 0
2565 // ARM pseudo code...
2566 if ConditionPassed() then
2567 EncodingSpecificOperations();
2568 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2569 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2570 if d == 15 then
2571 ALUWritePC(result); // setflags is always FALSE here
2572 else
2573 R[d] = result;
2574 if setflags then
2575 APSR.N = result<31>;
2576 APSR.Z = IsZeroBit(result);
2577 APSR.C = carry;
2578 APSR.V = overflow;
2579#endif
2580
2581 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002582
Greg Clayton7bc39082011-03-24 23:53:38 +00002583 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002584 {
2585 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002586 ARM_ShifterType shift_t;
2587 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002588 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002589 switch (encoding)
2590 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002591 case eEncodingT1:
2592 Rd = Bits32(opcode, 2, 0);
2593 Rn = Bits32(opcode, 5, 3);
2594 Rm = Bits32(opcode, 8, 6);
2595 setflags = !InITBlock();
2596 shift_t = SRType_LSL;
2597 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002598 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002599 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002600 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002601 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002602 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002603 shift_t = SRType_LSL;
2604 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002605 if (Rn == 15 && Rm == 15)
2606 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002607 if (Rd == 15 && InITBlock() && !LastInITBlock())
2608 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002609 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002610 case eEncodingA1:
2611 Rd = Bits32(opcode, 15, 12);
2612 Rn = Bits32(opcode, 19, 16);
2613 Rm = Bits32(opcode, 3, 0);
2614 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002615 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002616 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002617 default:
2618 return false;
2619 }
2620
Johnny Chen26863dc2011-02-09 23:43:29 +00002621 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002622 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002623 if (!success)
2624 return false;
2625
2626 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002627 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002628 if (!success)
2629 return false;
2630
Johnny Chene97c0d52011-02-18 19:32:20 +00002631 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002632 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002633
2634 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002635 context.type = eContextArithmetic;
2636 RegisterInfo op1_reg;
2637 RegisterInfo op2_reg;
2638 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2639 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00002640 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002641
Johnny Chen10530c22011-02-17 22:37:12 +00002642 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002643 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002644 }
2645 return true;
2646}
2647
Johnny Chen34075cb2011-02-22 01:56:31 +00002648// Compare Negative (immediate) adds a register value and an immediate value.
2649// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002650bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002651EmulateInstructionARM::EmulateCMNImm (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 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2658 APSR.N = result<31>;
2659 APSR.Z = IsZeroBit(result);
2660 APSR.C = carry;
2661 APSR.V = overflow;
2662#endif
2663
2664 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002665
2666 uint32_t Rn; // the first operand
2667 uint32_t imm32; // the immediate value to be compared with
2668 switch (encoding) {
2669 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002670 Rn = Bits32(opcode, 19, 16);
2671 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2672 if (Rn == 15)
2673 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002674 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002675 case eEncodingA1:
2676 Rn = Bits32(opcode, 19, 16);
2677 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2678 break;
2679 default:
2680 return false;
2681 }
2682 // Read the register value from the operand register Rn.
2683 uint32_t reg_val = ReadCoreReg(Rn, &success);
2684 if (!success)
2685 return false;
2686
Johnny Chen078fbc62011-02-22 19:48:22 +00002687 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002688
2689 EmulateInstruction::Context context;
2690 context.type = EmulateInstruction::eContextImmediate;
2691 context.SetNoArgs ();
2692 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2693 return false;
2694
2695 return true;
2696}
2697
2698// Compare Negative (register) adds a register value and an optionally-shifted register value.
2699// It updates the condition flags based on the result, and discards the result.
2700bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002701EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002702{
2703#if 0
2704 // ARM pseudo code...
2705 if ConditionPassed() then
2706 EncodingSpecificOperations();
2707 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2708 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2709 APSR.N = result<31>;
2710 APSR.Z = IsZeroBit(result);
2711 APSR.C = carry;
2712 APSR.V = overflow;
2713#endif
2714
2715 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002716
2717 uint32_t Rn; // the first operand
2718 uint32_t Rm; // the second operand
2719 ARM_ShifterType shift_t;
2720 uint32_t shift_n; // the shift applied to the value read from Rm
2721 switch (encoding) {
2722 case eEncodingT1:
2723 Rn = Bits32(opcode, 2, 0);
2724 Rm = Bits32(opcode, 5, 3);
2725 shift_t = SRType_LSL;
2726 shift_n = 0;
2727 break;
2728 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002729 Rn = Bits32(opcode, 19, 16);
2730 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002731 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002732 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2733 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002734 return false;
2735 break;
2736 case eEncodingA1:
2737 Rn = Bits32(opcode, 19, 16);
2738 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002739 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002740 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002741 default:
2742 return false;
2743 }
2744 // Read the register value from register Rn.
2745 uint32_t val1 = ReadCoreReg(Rn, &success);
2746 if (!success)
2747 return false;
2748
2749 // Read the register value from register Rm.
2750 uint32_t val2 = ReadCoreReg(Rm, &success);
2751 if (!success)
2752 return false;
2753
2754 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002755 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002756
2757 EmulateInstruction::Context context;
2758 context.type = EmulateInstruction::eContextImmediate;
2759 context.SetNoArgs();
2760 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2761 return false;
2762
2763 return true;
2764}
2765
2766// Compare (immediate) subtracts an immediate value from a register value.
2767// It updates the condition flags based on the result, and discards the result.
2768bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002769EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002770{
2771#if 0
2772 // ARM pseudo code...
2773 if ConditionPassed() then
2774 EncodingSpecificOperations();
2775 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2776 APSR.N = result<31>;
2777 APSR.Z = IsZeroBit(result);
2778 APSR.C = carry;
2779 APSR.V = overflow;
2780#endif
2781
2782 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002783
2784 uint32_t Rn; // the first operand
2785 uint32_t imm32; // the immediate value to be compared with
2786 switch (encoding) {
2787 case eEncodingT1:
2788 Rn = Bits32(opcode, 10, 8);
2789 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002790 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002791 case eEncodingT2:
2792 Rn = Bits32(opcode, 19, 16);
2793 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2794 if (Rn == 15)
2795 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002796 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002797 case eEncodingA1:
2798 Rn = Bits32(opcode, 19, 16);
2799 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002800 break;
2801 default:
2802 return false;
2803 }
2804 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002805 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002806 if (!success)
2807 return false;
2808
Johnny Chen10530c22011-02-17 22:37:12 +00002809 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2810
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002811 EmulateInstruction::Context context;
2812 context.type = EmulateInstruction::eContextImmediate;
2813 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002814 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2815 return false;
2816
Johnny Chend4dc4442011-02-11 02:02:56 +00002817 return true;
2818}
2819
Johnny Chen34075cb2011-02-22 01:56:31 +00002820// Compare (register) subtracts an optionally-shifted register value from a register value.
2821// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002822bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002823EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002824{
2825#if 0
2826 // ARM pseudo code...
2827 if ConditionPassed() then
2828 EncodingSpecificOperations();
2829 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2830 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2831 APSR.N = result<31>;
2832 APSR.Z = IsZeroBit(result);
2833 APSR.C = carry;
2834 APSR.V = overflow;
2835#endif
2836
2837 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002838
2839 uint32_t Rn; // the first operand
2840 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002841 ARM_ShifterType shift_t;
2842 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002843 switch (encoding) {
2844 case eEncodingT1:
2845 Rn = Bits32(opcode, 2, 0);
2846 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002847 shift_t = SRType_LSL;
2848 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002849 break;
2850 case eEncodingT2:
2851 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2852 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002853 shift_t = SRType_LSL;
2854 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002855 if (Rn < 8 && Rm < 8)
2856 return false;
2857 if (Rn == 15 || Rm == 15)
2858 return false;
2859 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002860 case eEncodingA1:
2861 Rn = Bits32(opcode, 19, 16);
2862 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002863 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002864 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002865 default:
2866 return false;
2867 }
2868 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002869 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002870 if (!success)
2871 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002872
Johnny Chene4a4d302011-02-11 21:53:58 +00002873 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002874 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002875 if (!success)
2876 return false;
2877
Johnny Chen34075cb2011-02-22 01:56:31 +00002878 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2879 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002880
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002881 EmulateInstruction::Context context;
2882 context.type = EmulateInstruction::eContextImmediate;
2883 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002884 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2885 return false;
2886
Johnny Chene4a4d302011-02-11 21:53:58 +00002887 return true;
2888}
2889
Johnny Chen82f16aa2011-02-15 20:10:55 +00002890// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2891// shifting in copies of its sign bit, and writes the result to the destination register. It can
2892// optionally update the condition flags based on the result.
2893bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002894EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002895{
2896#if 0
2897 // ARM pseudo code...
2898 if ConditionPassed() then
2899 EncodingSpecificOperations();
2900 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2901 if d == 15 then // Can only occur for ARM encoding
2902 ALUWritePC(result); // setflags is always FALSE here
2903 else
2904 R[d] = result;
2905 if setflags then
2906 APSR.N = result<31>;
2907 APSR.Z = IsZeroBit(result);
2908 APSR.C = carry;
2909 // APSR.V unchanged
2910#endif
2911
Greg Clayton7bc39082011-03-24 23:53:38 +00002912 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002913}
2914
2915// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2916// shifting in copies of its sign bit, and writes the result to the destination register.
2917// The variable number of bits is read from the bottom byte of a register. It can optionally update
2918// the condition flags based on the result.
2919bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002920EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002921{
2922#if 0
2923 // ARM pseudo code...
2924 if ConditionPassed() then
2925 EncodingSpecificOperations();
2926 shift_n = UInt(R[m]<7:0>);
2927 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2928 R[d] = result;
2929 if setflags then
2930 APSR.N = result<31>;
2931 APSR.Z = IsZeroBit(result);
2932 APSR.C = carry;
2933 // APSR.V unchanged
2934#endif
2935
Greg Clayton7bc39082011-03-24 23:53:38 +00002936 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002937}
2938
2939// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2940// shifting in zeros, and writes the result to the destination register. It can optionally
2941// update the condition flags based on the result.
2942bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002943EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002944{
2945#if 0
2946 // ARM pseudo code...
2947 if ConditionPassed() then
2948 EncodingSpecificOperations();
2949 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2950 if d == 15 then // Can only occur for ARM encoding
2951 ALUWritePC(result); // setflags is always FALSE here
2952 else
2953 R[d] = result;
2954 if setflags then
2955 APSR.N = result<31>;
2956 APSR.Z = IsZeroBit(result);
2957 APSR.C = carry;
2958 // APSR.V unchanged
2959#endif
2960
Greg Clayton7bc39082011-03-24 23:53:38 +00002961 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002962}
2963
2964// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2965// shifting in zeros, and writes the result to the destination register. The variable number
2966// of bits is read from the bottom byte of a register. It can optionally update the condition
2967// flags based on the result.
2968bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002969EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002970{
2971#if 0
2972 // ARM pseudo code...
2973 if ConditionPassed() then
2974 EncodingSpecificOperations();
2975 shift_n = UInt(R[m]<7:0>);
2976 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2977 R[d] = result;
2978 if setflags then
2979 APSR.N = result<31>;
2980 APSR.Z = IsZeroBit(result);
2981 APSR.C = carry;
2982 // APSR.V unchanged
2983#endif
2984
Greg Clayton7bc39082011-03-24 23:53:38 +00002985 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002986}
2987
2988// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2989// shifting in zeros, and writes the result to the destination register. It can optionally
2990// update the condition flags based on the result.
2991bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002992EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002993{
2994#if 0
2995 // ARM pseudo code...
2996 if ConditionPassed() then
2997 EncodingSpecificOperations();
2998 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2999 if d == 15 then // Can only occur for ARM encoding
3000 ALUWritePC(result); // setflags is always FALSE here
3001 else
3002 R[d] = result;
3003 if setflags then
3004 APSR.N = result<31>;
3005 APSR.Z = IsZeroBit(result);
3006 APSR.C = carry;
3007 // APSR.V unchanged
3008#endif
3009
Greg Clayton7bc39082011-03-24 23:53:38 +00003010 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003011}
3012
3013// Logical Shift Right (register) shifts a register value right by a variable number of bits,
3014// shifting in zeros, and writes the result to the destination register. The variable number
3015// of bits is read from the bottom byte of a register. It can optionally update the condition
3016// flags based on the result.
3017bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003018EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003019{
3020#if 0
3021 // ARM pseudo code...
3022 if ConditionPassed() then
3023 EncodingSpecificOperations();
3024 shift_n = UInt(R[m]<7:0>);
3025 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3026 R[d] = result;
3027 if setflags then
3028 APSR.N = result<31>;
3029 APSR.Z = IsZeroBit(result);
3030 APSR.C = carry;
3031 // APSR.V unchanged
3032#endif
3033
Greg Clayton7bc39082011-03-24 23:53:38 +00003034 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003035}
3036
Johnny Cheneeab4852011-02-16 22:14:44 +00003037// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3038// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3039// It can optionally update the condition flags based on the result.
3040bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003041EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003042{
3043#if 0
3044 // ARM pseudo code...
3045 if ConditionPassed() then
3046 EncodingSpecificOperations();
3047 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3048 if d == 15 then // Can only occur for ARM encoding
3049 ALUWritePC(result); // setflags is always FALSE here
3050 else
3051 R[d] = result;
3052 if setflags then
3053 APSR.N = result<31>;
3054 APSR.Z = IsZeroBit(result);
3055 APSR.C = carry;
3056 // APSR.V unchanged
3057#endif
3058
Greg Clayton7bc39082011-03-24 23:53:38 +00003059 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003060}
3061
3062// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3063// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3064// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3065// flags based on the result.
3066bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003067EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003068{
3069#if 0
3070 // ARM pseudo code...
3071 if ConditionPassed() then
3072 EncodingSpecificOperations();
3073 shift_n = UInt(R[m]<7:0>);
3074 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3075 R[d] = result;
3076 if setflags then
3077 APSR.N = result<31>;
3078 APSR.Z = IsZeroBit(result);
3079 APSR.C = carry;
3080 // APSR.V unchanged
3081#endif
3082
Greg Clayton7bc39082011-03-24 23:53:38 +00003083 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003084}
3085
3086// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3087// with the carry flag shifted into bit [31].
3088//
3089// RRX can optionally update the condition flags based on the result.
3090// In that case, bit [0] is shifted into the carry flag.
3091bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003092EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003093{
3094#if 0
3095 // ARM pseudo code...
3096 if ConditionPassed() then
3097 EncodingSpecificOperations();
3098 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3099 if d == 15 then // Can only occur for ARM encoding
3100 ALUWritePC(result); // setflags is always FALSE here
3101 else
3102 R[d] = result;
3103 if setflags then
3104 APSR.N = result<31>;
3105 APSR.Z = IsZeroBit(result);
3106 APSR.C = carry;
3107 // APSR.V unchanged
3108#endif
3109
Greg Clayton7bc39082011-03-24 23:53:38 +00003110 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003111}
3112
Johnny Chen41a0a152011-02-16 01:27:54 +00003113bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003114EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003115{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003116 assert(shift_type == SRType_ASR
3117 || shift_type == SRType_LSL
3118 || shift_type == SRType_LSR
3119 || shift_type == SRType_ROR
3120 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003121
Johnny Chen82f16aa2011-02-15 20:10:55 +00003122 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003123
Greg Clayton7bc39082011-03-24 23:53:38 +00003124 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003125 {
Johnny Chene7f89532011-02-15 23:22:46 +00003126 uint32_t Rd; // the destination register
3127 uint32_t Rm; // the first operand register
3128 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003129 uint32_t carry; // the carry bit after the shift operation
3130 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003131
3132 // Special case handling!
3133 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003134 ARMEncoding use_encoding = encoding;
3135 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003136 {
3137 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3138 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003139 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003140 }
3141
Greg Clayton7bc39082011-03-24 23:53:38 +00003142 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003143 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003144 // Due to the above special case handling!
3145 assert(shift_type != SRType_ROR);
3146
Johnny Chen82f16aa2011-02-15 20:10:55 +00003147 Rd = Bits32(opcode, 2, 0);
3148 Rm = Bits32(opcode, 5, 3);
3149 setflags = !InITBlock();
3150 imm5 = Bits32(opcode, 10, 6);
3151 break;
3152 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003153 // A8.6.141 RRX
3154 assert(shift_type != SRType_RRX);
3155
Johnny Chen82f16aa2011-02-15 20:10:55 +00003156 Rd = Bits32(opcode, 11, 8);
3157 Rm = Bits32(opcode, 3, 0);
3158 setflags = BitIsSet(opcode, 20);
3159 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3160 if (BadReg(Rd) || BadReg(Rm))
3161 return false;
3162 break;
3163 case eEncodingA1:
3164 Rd = Bits32(opcode, 15, 12);
3165 Rm = Bits32(opcode, 3, 0);
3166 setflags = BitIsSet(opcode, 20);
3167 imm5 = Bits32(opcode, 11, 7);
3168 break;
3169 default:
3170 return false;
3171 }
3172
Johnny Cheneeab4852011-02-16 22:14:44 +00003173 // A8.6.139 ROR (immediate)
3174 if (shift_type == SRType_ROR && imm5 == 0)
3175 shift_type = SRType_RRX;
3176
Johnny Chen82f16aa2011-02-15 20:10:55 +00003177 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003178 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003179 if (!success)
3180 return false;
3181
Johnny Cheneeab4852011-02-16 22:14:44 +00003182 // Decode the shift amount if not RRX.
3183 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003184
Johnny Chene97c0d52011-02-18 19:32:20 +00003185 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003186
3187 // The context specifies that an immediate is to be moved into Rd.
3188 EmulateInstruction::Context context;
3189 context.type = EmulateInstruction::eContextImmediate;
3190 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003191
Johnny Chen10530c22011-02-17 22:37:12 +00003192 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003193 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003194 }
3195 return true;
3196}
3197
Johnny Chene7f89532011-02-15 23:22:46 +00003198bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003199EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003200{
Johnny Chen41a0a152011-02-16 01:27:54 +00003201 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003202
3203 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003204
Greg Clayton7bc39082011-03-24 23:53:38 +00003205 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003206 {
3207 uint32_t Rd; // the destination register
3208 uint32_t Rn; // the first operand register
3209 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3210 uint32_t carry; // the carry bit after the shift operation
3211 bool setflags;
3212 switch (encoding) {
3213 case eEncodingT1:
3214 Rd = Bits32(opcode, 2, 0);
3215 Rn = Rd;
3216 Rm = Bits32(opcode, 5, 3);
3217 setflags = !InITBlock();
3218 break;
3219 case eEncodingT2:
3220 Rd = Bits32(opcode, 11, 8);
3221 Rn = Bits32(opcode, 19, 16);
3222 Rm = Bits32(opcode, 3, 0);
3223 setflags = BitIsSet(opcode, 20);
3224 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3225 return false;
3226 break;
3227 case eEncodingA1:
3228 Rd = Bits32(opcode, 15, 12);
3229 Rn = Bits32(opcode, 3, 0);
3230 Rm = Bits32(opcode, 11, 8);
3231 setflags = BitIsSet(opcode, 20);
3232 if (Rd == 15 || Rn == 15 || Rm == 15)
3233 return false;
3234 break;
3235 default:
3236 return false;
3237 }
3238
3239 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003240 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003241 if (!success)
3242 return false;
3243 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003244 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003245 if (!success)
3246 return false;
3247
3248 // Get the shift amount.
3249 uint32_t amt = Bits32(val, 7, 0);
3250
Johnny Chene97c0d52011-02-18 19:32:20 +00003251 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003252
3253 // The context specifies that an immediate is to be moved into Rd.
3254 EmulateInstruction::Context context;
3255 context.type = EmulateInstruction::eContextImmediate;
3256 context.SetNoArgs ();
3257
Johnny Chen10530c22011-02-17 22:37:12 +00003258 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003259 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003260 }
3261 return true;
3262}
3263
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003264// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003265// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003266// can be written back to the base register.
3267bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003268EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003269{
3270#if 0
3271 // ARM pseudo code...
3272 if ConditionPassed()
3273 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3274 address = R[n];
3275
3276 for i = 0 to 14
3277 if registers<i> == '1' then
3278 R[i] = MemA[address, 4]; address = address + 4;
3279 if registers<15> == '1' then
3280 LoadWritePC (MemA[address, 4]);
3281
3282 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3283 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3284
3285#endif
3286
3287 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003288
Greg Clayton7bc39082011-03-24 23:53:38 +00003289 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003290 {
3291 uint32_t n;
3292 uint32_t registers = 0;
3293 bool wback;
3294 const uint32_t addr_byte_size = GetAddressByteSize();
3295 switch (encoding)
3296 {
3297 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003298 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003299 n = Bits32 (opcode, 10, 8);
3300 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003301 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003302 wback = BitIsClear (registers, n);
3303 // if BitCount(registers) < 1 then UNPREDICTABLE;
3304 if (BitCount(registers) < 1)
3305 return false;
3306 break;
3307 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003308 // if W == '1' && Rn == '1101' then SEE POP;
3309 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003310 n = Bits32 (opcode, 19, 16);
3311 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003312 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003313 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003314
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003315 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003316 if ((n == 15)
3317 || (BitCount (registers) < 2)
3318 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3319 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003320
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003321 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003322 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003323 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003324
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003325 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003326 if (wback
3327 && BitIsSet (registers, n))
3328 return false;
3329 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003330
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003331 case eEncodingA1:
3332 n = Bits32 (opcode, 19, 16);
3333 registers = Bits32 (opcode, 15, 0);
3334 wback = BitIsSet (opcode, 21);
3335 if ((n == 15)
3336 || (BitCount (registers) < 1))
3337 return false;
3338 break;
3339 default:
3340 return false;
3341 }
3342
3343 int32_t offset = 0;
3344 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3345 if (!success)
3346 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003347
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003348 EmulateInstruction::Context context;
3349 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003350 RegisterInfo dwarf_reg;
3351 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003352 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003353
3354 for (int i = 0; i < 14; ++i)
3355 {
3356 if (BitIsSet (registers, i))
3357 {
Caroline Tice85aab332011-02-08 23:56:10 +00003358 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003359 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003360 if (wback && (n == 13)) // Pop Instruction
3361 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3362
3363 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003364 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003365 if (!success)
3366 return false;
3367
3368 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3369 return false;
3370
3371 offset += addr_byte_size;
3372 }
3373 }
3374
3375 if (BitIsSet (registers, 15))
3376 {
3377 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003378 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003379 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003380 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003381 if (!success)
3382 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003383 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003384 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003385 return false;
3386 }
3387
3388 if (wback && BitIsClear (registers, n))
3389 {
Caroline Ticefa172202011-02-11 22:49:54 +00003390 // R[n] = R[n] + 4 * BitCount (registers)
3391 int32_t offset = addr_byte_size * BitCount (registers);
3392 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003393 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003394
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003395 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3396 return false;
3397 }
3398 if (wback && BitIsSet (registers, n))
3399 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003400 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003401 }
3402 return true;
3403}
Caroline Tice713c2662011-02-11 17:59:55 +00003404
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003405// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3406// The consecutive memory locations end at this address and the address just below the lowest of those locations
3407// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003408bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003409EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003410{
3411#if 0
3412 // ARM pseudo code...
3413 if ConditionPassed() then
3414 EncodingSpecificOperations();
3415 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003416
Caroline Tice713c2662011-02-11 17:59:55 +00003417 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003418 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003419 R[i] = MemA[address,4]; address = address + 4;
3420
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003421 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003422 LoadWritePC(MemA[address,4]);
3423
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003424 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3425 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003426#endif
3427
3428 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003429
Greg Clayton7bc39082011-03-24 23:53:38 +00003430 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003431 {
3432 uint32_t n;
3433 uint32_t registers = 0;
3434 bool wback;
3435 const uint32_t addr_byte_size = GetAddressByteSize();
3436
3437 // EncodingSpecificOperations();
3438 switch (encoding)
3439 {
3440 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003441 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003442 n = Bits32 (opcode, 19, 16);
3443 registers = Bits32 (opcode, 15, 0);
3444 wback = BitIsSet (opcode, 21);
3445
3446 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3447 if ((n == 15) || (BitCount (registers) < 1))
3448 return false;
3449
3450 break;
3451
3452 default:
3453 return false;
3454 }
3455 // address = R[n] - 4*BitCount(registers) + 4;
3456
3457 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003458 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003459
3460 if (!success)
3461 return false;
3462
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003463 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003464
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003465 EmulateInstruction::Context context;
3466 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003467 RegisterInfo dwarf_reg;
3468 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003469 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003470
3471 // for i = 0 to 14
3472 for (int i = 0; i < 14; ++i)
3473 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003474 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003475 if (BitIsSet (registers, i))
3476 {
3477 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003478 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003479 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003480 if (!success)
3481 return false;
3482 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3483 return false;
3484 offset += addr_byte_size;
3485 }
3486 }
3487
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003488 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003489 // LoadWritePC(MemA[address,4]);
3490 if (BitIsSet (registers, 15))
3491 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003492 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003493 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003494 if (!success)
3495 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003496 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003497 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003498 return false;
3499 }
3500
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003501 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003502 if (wback && BitIsClear (registers, n))
3503 {
Caroline Tice713c2662011-02-11 17:59:55 +00003504 if (!success)
3505 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003506
3507 offset = (addr_byte_size * BitCount (registers)) * -1;
3508 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003509 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003510 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003511 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3512 return false;
3513 }
3514
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003515 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003516 if (wback && BitIsSet (registers, n))
3517 return WriteBits32Unknown (n);
3518 }
3519 return true;
3520}
3521
3522// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3523// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3524// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003525bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003526EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003527{
3528#if 0
3529 // ARM pseudo code...
3530 if ConditionPassed() then
3531 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3532 address = R[n] - 4*BitCount(registers);
3533
3534 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003535 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003536 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003537 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003538 LoadWritePC(MemA[address,4]);
3539
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003540 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3541 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003542#endif
3543
3544 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003545
Greg Clayton7bc39082011-03-24 23:53:38 +00003546 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003547 {
3548 uint32_t n;
3549 uint32_t registers = 0;
3550 bool wback;
3551 const uint32_t addr_byte_size = GetAddressByteSize();
3552 switch (encoding)
3553 {
3554 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003555 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003556 n = Bits32 (opcode, 19, 16);
3557 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003558 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003559 wback = BitIsSet (opcode, 21);
3560
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003561 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003562 if ((n == 15)
3563 || (BitCount (registers) < 2)
3564 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3565 return false;
3566
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003567 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003568 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003569 return false;
3570
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003571 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003572 if (wback && BitIsSet (registers, n))
3573 return false;
3574
3575 break;
3576
3577 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003578 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003579 n = Bits32 (opcode, 19, 16);
3580 registers = Bits32 (opcode, 15, 0);
3581 wback = BitIsSet (opcode, 21);
3582
3583 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3584 if ((n == 15) || (BitCount (registers) < 1))
3585 return false;
3586
3587 break;
3588
3589 default:
3590 return false;
3591 }
3592
Caroline Tice713c2662011-02-11 17:59:55 +00003593 // address = R[n] - 4*BitCount(registers);
3594
Caroline Tice0b29e242011-02-08 23:16:02 +00003595 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003596 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003597
3598 if (!success)
3599 return false;
3600
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003601 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003602 EmulateInstruction::Context context;
3603 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003604 RegisterInfo dwarf_reg;
3605 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003606 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003607
3608 for (int i = 0; i < 14; ++i)
3609 {
3610 if (BitIsSet (registers, i))
3611 {
3612 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003613 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003614 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003615 if (!success)
3616 return false;
3617
3618 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3619 return false;
3620
3621 offset += addr_byte_size;
3622 }
3623 }
3624
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003625 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003626 // LoadWritePC(MemA[address,4]);
3627 if (BitIsSet (registers, 15))
3628 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003629 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003630 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003631 if (!success)
3632 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003633 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003634 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003635 return false;
3636 }
3637
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003638 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003639 if (wback && BitIsClear (registers, n))
3640 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003641 if (!success)
3642 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003643
3644 offset = (addr_byte_size * BitCount (registers)) * -1;
3645 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003646 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003647 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003648 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3649 return false;
3650 }
3651
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003652 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003653 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003654 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003655 }
3656 return true;
3657}
Caroline Tice85aab332011-02-08 23:56:10 +00003658
Caroline Tice713c2662011-02-11 17:59:55 +00003659// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3660// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3661// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003662bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003663EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003664{
3665#if 0
3666 if ConditionPassed() then
3667 EncodingSpecificOperations();
3668 address = R[n] + 4;
3669
3670 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003671 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003672 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003673 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003674 LoadWritePC(MemA[address,4]);
3675
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003676 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3677 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003678#endif
3679
3680 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003681
Greg Clayton7bc39082011-03-24 23:53:38 +00003682 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003683 {
3684 uint32_t n;
3685 uint32_t registers = 0;
3686 bool wback;
3687 const uint32_t addr_byte_size = GetAddressByteSize();
3688 switch (encoding)
3689 {
3690 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003691 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003692 n = Bits32 (opcode, 19, 16);
3693 registers = Bits32 (opcode, 15, 0);
3694 wback = BitIsSet (opcode, 21);
3695
3696 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3697 if ((n == 15) || (BitCount (registers) < 1))
3698 return false;
3699
3700 break;
3701 default:
3702 return false;
3703 }
3704 // address = R[n] + 4;
3705
3706 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003707 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003708
3709 if (!success)
3710 return false;
3711
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003712 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003713
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003714 EmulateInstruction::Context context;
3715 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003716 RegisterInfo dwarf_reg;
3717 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003718 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003719
3720 for (int i = 0; i < 14; ++i)
3721 {
3722 if (BitIsSet (registers, i))
3723 {
3724 // R[i] = MemA[address,4]; address = address + 4;
3725
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003726 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003727 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003728 if (!success)
3729 return false;
3730
3731 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3732 return false;
3733
3734 offset += addr_byte_size;
3735 }
3736 }
3737
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003738 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003739 // LoadWritePC(MemA[address,4]);
3740 if (BitIsSet (registers, 15))
3741 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003742 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003743 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003744 if (!success)
3745 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003746 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003747 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003748 return false;
3749 }
3750
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003751 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003752 if (wback && BitIsClear (registers, n))
3753 {
Caroline Tice85aab332011-02-08 23:56:10 +00003754 if (!success)
3755 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003756
3757 offset = addr_byte_size * BitCount (registers);
3758 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003759 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003760 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003761 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3762 return false;
3763 }
3764
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003765 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003766 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003767 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003768 }
3769 return true;
3770}
Caroline Tice0b29e242011-02-08 23:16:02 +00003771
Johnny Chenef21b592011-02-10 01:52:38 +00003772// Load Register (immediate) calculates an address from a base register value and
3773// an immediate offset, loads a word from memory, and writes to a register.
3774// LDR (immediate, Thumb)
3775bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003776EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003777{
3778#if 0
3779 // ARM pseudo code...
3780 if (ConditionPassed())
3781 {
3782 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3783 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3784 address = if index then offset_addr else R[n];
3785 data = MemU[address,4];
3786 if wback then R[n] = offset_addr;
3787 if t == 15 then
3788 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3789 elsif UnalignedSupport() || address<1:0> = '00' then
3790 R[t] = data;
3791 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3792 }
3793#endif
3794
3795 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003796
Greg Clayton7bc39082011-03-24 23:53:38 +00003797 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003798 {
3799 uint32_t Rt; // the destination register
3800 uint32_t Rn; // the base register
3801 uint32_t imm32; // the immediate offset used to form the address
3802 addr_t offset_addr; // the offset address
3803 addr_t address; // the calculated address
3804 uint32_t data; // the literal data value from memory load
3805 bool add, index, wback;
3806 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003807 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003808 Rt = Bits32(opcode, 2, 0);
3809 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003810 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3811 // index = TRUE; add = TRUE; wback = FALSE
3812 add = true;
3813 index = true;
3814 wback = false;
3815
3816 break;
3817
3818 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003819 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003820 Rt = Bits32 (opcode, 10, 8);
3821 Rn = 13;
3822 imm32 = Bits32 (opcode, 7, 0) << 2;
3823
3824 // index = TRUE; add = TRUE; wback = FALSE;
3825 index = true;
3826 add = true;
3827 wback = false;
3828
3829 break;
3830
3831 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003832 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003833 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3834 Rt = Bits32 (opcode, 15, 12);
3835 Rn = Bits32 (opcode, 19, 16);
3836 imm32 = Bits32 (opcode, 11, 0);
3837
3838 // index = TRUE; add = TRUE; wback = FALSE;
3839 index = true;
3840 add = true;
3841 wback = false;
3842
3843 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3844 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3845 return false;
3846
3847 break;
3848
3849 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003850 // if Rn == '1111' then SEE LDR (literal);
3851 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3852 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3853 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003854 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3855 return false;
3856
3857 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3858 Rt = Bits32 (opcode, 15, 12);
3859 Rn = Bits32 (opcode, 19, 16);
3860 imm32 = Bits32 (opcode, 7, 0);
3861
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003862 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003863 index = BitIsSet (opcode, 10);
3864 add = BitIsSet (opcode, 9);
3865 wback = BitIsSet (opcode, 8);
3866
3867 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3868 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3869 return false;
3870
3871 break;
3872
3873 default:
3874 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003875 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003876 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003877 if (!success)
3878 return false;
3879 if (add)
3880 offset_addr = base + imm32;
3881 else
3882 offset_addr = base - imm32;
3883
3884 address = (index ? offset_addr : base);
3885
Greg Claytonc07d4512011-04-26 23:48:45 +00003886 RegisterInfo base_reg;
3887 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
Johnny Chenef21b592011-02-10 01:52:38 +00003888 if (wback)
3889 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003890 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003891 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3892 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003893
Johnny Chenef21b592011-02-10 01:52:38 +00003894 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3895 return false;
3896 }
3897
3898 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003899 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003900 context.type = EmulateInstruction::eContextRegisterLoad;
3901 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003902
3903 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003904 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003905 if (!success)
3906 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003907
3908 if (Rt == 15)
3909 {
3910 if (Bits32(address, 1, 0) == 0)
3911 {
Johnny Chen668b4512011-02-15 21:08:58 +00003912 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003913 return false;
3914 }
3915 else
3916 return false;
3917 }
3918 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3919 {
3920 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3921 return false;
3922 }
3923 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003924 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003925 }
3926 return true;
3927}
3928
Caroline Ticeaf556562011-02-15 18:42:15 +00003929// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3930// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3931// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003932bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003933EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003934{
3935#if 0
3936 if ConditionPassed() then
3937 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3938 address = R[n];
3939
3940 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003941 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003942 if i == n && wback && i != LowestSetBit(registers) then
3943 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3944 else
3945 MemA[address,4] = R[i];
3946 address = address + 4;
3947
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003948 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003949 MemA[address,4] = PCStoreValue();
3950 if wback then R[n] = R[n] + 4*BitCount(registers);
3951#endif
3952
3953 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003954
Greg Clayton7bc39082011-03-24 23:53:38 +00003955 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003956 {
3957 uint32_t n;
3958 uint32_t registers = 0;
3959 bool wback;
3960 const uint32_t addr_byte_size = GetAddressByteSize();
3961
3962 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3963 switch (encoding)
3964 {
3965 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003966 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003967 n = Bits32 (opcode, 10, 8);
3968 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003969 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003970 wback = true;
3971
3972 // if BitCount(registers) < 1 then UNPREDICTABLE;
3973 if (BitCount (registers) < 1)
3974 return false;
3975
3976 break;
3977
3978 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003979 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003980 n = Bits32 (opcode, 19, 16);
3981 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003982 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003983 wback = BitIsSet (opcode, 21);
3984
3985 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3986 if ((n == 15) || (BitCount (registers) < 2))
3987 return false;
3988
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003989 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003990 if (wback && BitIsSet (registers, n))
3991 return false;
3992
3993 break;
3994
3995 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003996 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003997 n = Bits32 (opcode, 19, 16);
3998 registers = Bits32 (opcode, 15, 0);
3999 wback = BitIsSet (opcode, 21);
4000
4001 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4002 if ((n == 15) || (BitCount (registers) < 1))
4003 return false;
4004
4005 break;
4006
4007 default:
4008 return false;
4009 }
4010
4011 // address = R[n];
4012 int32_t offset = 0;
4013 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4014 if (!success)
4015 return false;
4016
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004017 EmulateInstruction::Context context;
4018 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004019 RegisterInfo base_reg;
4020 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefa172202011-02-11 22:49:54 +00004021
4022 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004023 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00004024 for (int i = 0; i < 14; ++i)
4025 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004026 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00004027 if (BitIsSet (registers, i))
4028 {
4029 if (i < lowest_set_bit)
4030 lowest_set_bit = i;
4031 // if i == n && wback && i != LowestSetBit(registers) then
4032 if ((i == n) && wback && (i != lowest_set_bit))
4033 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4034 WriteBits32UnknownToMemory (address + offset);
4035 else
4036 {
4037 // MemA[address,4] = R[i];
4038 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4039 if (!success)
4040 return false;
4041
Greg Claytonc07d4512011-04-26 23:48:45 +00004042 RegisterInfo data_reg;
4043 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004044 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004045 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004046 return false;
4047 }
4048
4049 // address = address + 4;
4050 offset += addr_byte_size;
4051 }
4052 }
4053
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004054 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004055 // MemA[address,4] = PCStoreValue();
4056 if (BitIsSet (registers, 15))
4057 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004058 RegisterInfo pc_reg;
4059 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004060 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004061 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004062 if (!success)
4063 return false;
4064
Caroline Tice8d681f52011-03-17 23:50:16 +00004065 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004066 return false;
4067 }
4068
4069 // if wback then R[n] = R[n] + 4*BitCount(registers);
4070 if (wback)
4071 {
4072 offset = addr_byte_size * BitCount (registers);
4073 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004074 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004075 addr_t data = address + offset;
4076 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4077 return false;
4078 }
4079 }
4080 return true;
4081}
4082
Caroline Ticeaf556562011-02-15 18:42:15 +00004083// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4084// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4085// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004086bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004087EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004088{
4089#if 0
4090 if ConditionPassed() then
4091 EncodingSpecificOperations();
4092 address = R[n] - 4*BitCount(registers) + 4;
4093
4094 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004095 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004096 if i == n && wback && i != LowestSetBit(registers) then
4097 MemA[address,4] = bits(32) UNKNOWN;
4098 else
4099 MemA[address,4] = R[i];
4100 address = address + 4;
4101
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004102 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004103 MemA[address,4] = PCStoreValue();
4104
4105 if wback then R[n] = R[n] - 4*BitCount(registers);
4106#endif
4107
4108 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004109
Greg Clayton7bc39082011-03-24 23:53:38 +00004110 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004111 {
4112 uint32_t n;
4113 uint32_t registers = 0;
4114 bool wback;
4115 const uint32_t addr_byte_size = GetAddressByteSize();
4116
4117 // EncodingSpecificOperations();
4118 switch (encoding)
4119 {
4120 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004121 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004122 n = Bits32 (opcode, 19, 16);
4123 registers = Bits32 (opcode, 15, 0);
4124 wback = BitIsSet (opcode, 21);
4125
4126 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4127 if ((n == 15) || (BitCount (registers) < 1))
4128 return false;
4129 break;
4130 default:
4131 return false;
4132 }
4133
4134 // address = R[n] - 4*BitCount(registers) + 4;
4135 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004136 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004137 if (!success)
4138 return false;
4139
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004140 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004141
4142 EmulateInstruction::Context context;
4143 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004144 RegisterInfo base_reg;
4145 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004146
4147 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004148 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004149 for (int i = 0; i < 14; ++i)
4150 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004151 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004152 if (BitIsSet (registers, i))
4153 {
4154 if (i < lowest_bit_set)
4155 lowest_bit_set = i;
4156 //if i == n && wback && i != LowestSetBit(registers) then
4157 if ((i == n) && wback && (i != lowest_bit_set))
4158 // MemA[address,4] = bits(32) UNKNOWN;
4159 WriteBits32UnknownToMemory (address + offset);
4160 else
4161 {
4162 // MemA[address,4] = R[i];
4163 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4164 if (!success)
4165 return false;
4166
Greg Claytonc07d4512011-04-26 23:48:45 +00004167 RegisterInfo data_reg;
4168 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004169 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004170 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004171 return false;
4172 }
4173
4174 // address = address + 4;
4175 offset += addr_byte_size;
4176 }
4177 }
4178
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004179 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004180 // MemA[address,4] = PCStoreValue();
4181 if (BitIsSet (registers, 15))
4182 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004183 RegisterInfo pc_reg;
4184 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004185 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004186 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004187 if (!success)
4188 return false;
4189
Caroline Tice8d681f52011-03-17 23:50:16 +00004190 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004191 return false;
4192 }
4193
4194 // if wback then R[n] = R[n] - 4*BitCount(registers);
4195 if (wback)
4196 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004197 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004198 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4199 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004200 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004201 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4202 return false;
4203 }
4204 }
4205 return true;
4206}
4207
Caroline Ticeaf556562011-02-15 18:42:15 +00004208// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4209// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4210// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004211bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004212EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004213{
4214#if 0
4215 if ConditionPassed() then
4216 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4217 address = R[n] - 4*BitCount(registers);
4218
4219 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004220 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004221 if i == n && wback && i != LowestSetBit(registers) then
4222 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4223 else
4224 MemA[address,4] = R[i];
4225 address = address + 4;
4226
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004227 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004228 MemA[address,4] = PCStoreValue();
4229
4230 if wback then R[n] = R[n] - 4*BitCount(registers);
4231#endif
4232
4233
4234 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004235
Greg Clayton7bc39082011-03-24 23:53:38 +00004236 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004237 {
4238 uint32_t n;
4239 uint32_t registers = 0;
4240 bool wback;
4241 const uint32_t addr_byte_size = GetAddressByteSize();
4242
4243 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4244 switch (encoding)
4245 {
4246 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004247 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004248 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4249 {
4250 // See PUSH
4251 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004252 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004253 n = Bits32 (opcode, 19, 16);
4254 registers = Bits32 (opcode, 15, 0);
4255 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4256 wback = BitIsSet (opcode, 21);
4257 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4258 if ((n == 15) || BitCount (registers) < 2)
4259 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004260 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004261 if (wback && BitIsSet (registers, n))
4262 return false;
4263 break;
4264
4265 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00004266 // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004267 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4268 {
4269 // See Push
4270 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004271 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004272 n = Bits32 (opcode, 19, 16);
4273 registers = Bits32 (opcode, 15, 0);
4274 wback = BitIsSet (opcode, 21);
4275 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4276 if ((n == 15) || BitCount (registers) < 1)
4277 return false;
4278 break;
4279
4280 default:
4281 return false;
4282 }
4283
4284 // address = R[n] - 4*BitCount(registers);
4285
4286 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004287 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004288 if (!success)
4289 return false;
4290
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004291 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004292
4293 EmulateInstruction::Context context;
4294 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004295 RegisterInfo base_reg;
4296 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004297
4298 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004299 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004300 for (int i = 0; i < 14; ++i)
4301 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004302 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004303 if (BitIsSet (registers, i))
4304 {
4305 if (i < lowest_set_bit)
4306 lowest_set_bit = i;
4307 // if i == n && wback && i != LowestSetBit(registers) then
4308 if ((i == n) && wback && (i != lowest_set_bit))
4309 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4310 WriteBits32UnknownToMemory (address + offset);
4311 else
4312 {
4313 // MemA[address,4] = R[i];
4314 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4315 if (!success)
4316 return false;
4317
Greg Claytonc07d4512011-04-26 23:48:45 +00004318 RegisterInfo data_reg;
4319 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004320 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004321 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004322 return false;
4323 }
4324
4325 // address = address + 4;
4326 offset += addr_byte_size;
4327 }
4328 }
4329
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004330 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004331 // MemA[address,4] = PCStoreValue();
4332 if (BitIsSet (registers, 15))
4333 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004334 RegisterInfo pc_reg;
4335 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004336 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004337 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004338 if (!success)
4339 return false;
4340
Caroline Tice8d681f52011-03-17 23:50:16 +00004341 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004342 return false;
4343 }
4344
4345 // if wback then R[n] = R[n] - 4*BitCount(registers);
4346 if (wback)
4347 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004348 offset = (addr_byte_size * BitCount (registers)) * -1;
4349 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4350 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004351 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004352 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4353 return false;
4354 }
4355 }
4356 return true;
4357}
4358
4359// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4360// from a base register. The consecutive memory locations start just above this address, and the address of the last
4361// of those locations can optionally be written back to the base register.
4362bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004363EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004364{
4365#if 0
4366 if ConditionPassed() then
4367 EncodingSpecificOperations();
4368 address = R[n] + 4;
4369
4370 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004371 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004372 if i == n && wback && i != LowestSetBit(registers) then
4373 MemA[address,4] = bits(32) UNKNOWN;
4374 else
4375 MemA[address,4] = R[i];
4376 address = address + 4;
4377
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004378 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004379 MemA[address,4] = PCStoreValue();
4380
4381 if wback then R[n] = R[n] + 4*BitCount(registers);
4382#endif
4383
4384 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004385
Greg Clayton7bc39082011-03-24 23:53:38 +00004386 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004387 {
4388 uint32_t n;
4389 uint32_t registers = 0;
4390 bool wback;
4391 const uint32_t addr_byte_size = GetAddressByteSize();
4392
4393 // EncodingSpecificOperations();
4394 switch (encoding)
4395 {
4396 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004397 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004398 n = Bits32 (opcode, 19, 16);
4399 registers = Bits32 (opcode, 15, 0);
4400 wback = BitIsSet (opcode, 21);
4401
4402 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4403 if ((n == 15) && (BitCount (registers) < 1))
4404 return false;
4405 break;
4406 default:
4407 return false;
4408 }
4409 // address = R[n] + 4;
4410
4411 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004412 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004413 if (!success)
4414 return false;
4415
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004416 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004417
4418 EmulateInstruction::Context context;
4419 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004420 RegisterInfo base_reg;
4421 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004422
4423 uint32_t lowest_set_bit = 14;
4424 // for i = 0 to 14
4425 for (int i = 0; i < 14; ++i)
4426 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004427 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004428 if (BitIsSet (registers, i))
4429 {
4430 if (i < lowest_set_bit)
4431 lowest_set_bit = i;
4432 // if i == n && wback && i != LowestSetBit(registers) then
4433 if ((i == n) && wback && (i != lowest_set_bit))
4434 // MemA[address,4] = bits(32) UNKNOWN;
4435 WriteBits32UnknownToMemory (address + offset);
4436 // else
4437 else
4438 {
4439 // MemA[address,4] = R[i];
4440 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4441 if (!success)
4442 return false;
4443
Greg Claytonc07d4512011-04-26 23:48:45 +00004444 RegisterInfo data_reg;
4445 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004446 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004447 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004448 return false;
4449 }
4450
4451 // address = address + 4;
4452 offset += addr_byte_size;
4453 }
4454 }
4455
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004456 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004457 // MemA[address,4] = PCStoreValue();
4458 if (BitIsSet (registers, 15))
4459 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004460 RegisterInfo pc_reg;
4461 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004462 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004463 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004464 if (!success)
4465 return false;
4466
Caroline Tice8d681f52011-03-17 23:50:16 +00004467 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004468 return false;
4469 }
4470
4471 // if wback then R[n] = R[n] + 4*BitCount(registers);
4472 if (wback)
4473 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004474 offset = addr_byte_size * BitCount (registers);
4475 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4476 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004477 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004478 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4479 return false;
4480 }
4481 }
4482 return true;
4483}
Caroline Tice7fac8572011-02-15 22:53:54 +00004484
4485// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4486// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4487bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004488EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004489{
4490#if 0
4491 if ConditionPassed() then
4492 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4493 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4494 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004495 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004496 MemU[address,4] = R[t];
4497 else // Can only occur before ARMv7
4498 MemU[address,4] = bits(32) UNKNOWN;
4499 if wback then R[n] = offset_addr;
4500#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004501
Caroline Tice7fac8572011-02-15 22:53:54 +00004502 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004503
Greg Clayton7bc39082011-03-24 23:53:38 +00004504 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004505 {
4506 const uint32_t addr_byte_size = GetAddressByteSize();
4507
4508 uint32_t t;
4509 uint32_t n;
4510 uint32_t imm32;
4511 bool index;
4512 bool add;
4513 bool wback;
4514 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4515 switch (encoding)
4516 {
4517 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004518 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004519 t = Bits32 (opcode, 2, 0);
4520 n = Bits32 (opcode, 5, 3);
4521 imm32 = Bits32 (opcode, 10, 6) << 2;
4522
4523 // index = TRUE; add = TRUE; wback = FALSE;
4524 index = true;
4525 add = false;
4526 wback = false;
4527 break;
4528
4529 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004530 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004531 t = Bits32 (opcode, 10, 8);
4532 n = 13;
4533 imm32 = Bits32 (opcode, 7, 0) << 2;
4534
4535 // index = TRUE; add = TRUE; wback = FALSE;
4536 index = true;
4537 add = true;
4538 wback = false;
4539 break;
4540
4541 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004542 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004543 if (Bits32 (opcode, 19, 16) == 15)
4544 return false;
4545
4546 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4547 t = Bits32 (opcode, 15, 12);
4548 n = Bits32 (opcode, 19, 16);
4549 imm32 = Bits32 (opcode, 11, 0);
4550
4551 // index = TRUE; add = TRUE; wback = FALSE;
4552 index = true;
4553 add = true;
4554 wback = false;
4555
4556 // if t == 15 then UNPREDICTABLE;
4557 if (t == 15)
4558 return false;
4559 break;
4560
4561 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004562 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4563 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4564 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004565 if ((Bits32 (opcode, 19, 16) == 15)
4566 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4567 return false;
4568
4569 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4570 t = Bits32 (opcode, 15, 12);
4571 n = Bits32 (opcode, 19, 16);
4572 imm32 = Bits32 (opcode, 7, 0);
4573
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004574 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004575 index = BitIsSet (opcode, 10);
4576 add = BitIsSet (opcode, 9);
4577 wback = BitIsSet (opcode, 8);
4578
4579 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4580 if ((t == 15) || (wback && (n == t)))
4581 return false;
4582 break;
4583
4584 default:
4585 return false;
4586 }
4587
4588 addr_t offset_addr;
4589 addr_t address;
4590
4591 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004592 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004593 if (!success)
4594 return false;
4595
4596 if (add)
4597 offset_addr = base_address + imm32;
4598 else
4599 offset_addr = base_address - imm32;
4600
4601 // address = if index then offset_addr else R[n];
4602 if (index)
4603 address = offset_addr;
4604 else
4605 address = base_address;
4606
4607 EmulateInstruction::Context context;
4608 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004609 RegisterInfo base_reg;
4610 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004611
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004612 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004613 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4614 {
4615 // MemU[address,4] = R[t];
4616 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4617 if (!success)
4618 return false;
4619
Greg Claytonc07d4512011-04-26 23:48:45 +00004620 RegisterInfo data_reg;
4621 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004622 int32_t offset = address - base_address;
4623 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004624 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004625 return false;
4626 }
4627 else
4628 {
4629 // MemU[address,4] = bits(32) UNKNOWN;
4630 WriteBits32UnknownToMemory (address);
4631 }
4632
4633 // if wback then R[n] = offset_addr;
4634 if (wback)
4635 {
4636 context.type = eContextRegisterLoad;
4637 context.SetAddress (offset_addr);
4638 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4639 return false;
4640 }
4641 }
4642 return true;
4643}
Caroline Ticeaf556562011-02-15 18:42:15 +00004644
Caroline Tice3fd63e92011-02-16 00:33:43 +00004645// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4646// word from a register to memory. The offset register value can optionally be shifted.
4647bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004648EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004649{
4650#if 0
4651 if ConditionPassed() then
4652 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4653 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4654 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4655 address = if index then offset_addr else R[n];
4656 if t == 15 then // Only possible for encoding A1
4657 data = PCStoreValue();
4658 else
4659 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004660 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004661 MemU[address,4] = data;
4662 else // Can only occur before ARMv7
4663 MemU[address,4] = bits(32) UNKNOWN;
4664 if wback then R[n] = offset_addr;
4665#endif
4666
4667 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004668
Greg Clayton7bc39082011-03-24 23:53:38 +00004669 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004670 {
4671 const uint32_t addr_byte_size = GetAddressByteSize();
4672
4673 uint32_t t;
4674 uint32_t n;
4675 uint32_t m;
4676 ARM_ShifterType shift_t;
4677 uint32_t shift_n;
4678 bool index;
4679 bool add;
4680 bool wback;
4681
4682 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4683 switch (encoding)
4684 {
4685 case eEncodingT1:
4686 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4687 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4688 t = Bits32 (opcode, 2, 0);
4689 n = Bits32 (opcode, 5, 3);
4690 m = Bits32 (opcode, 8, 6);
4691
4692 // index = TRUE; add = TRUE; wback = FALSE;
4693 index = true;
4694 add = true;
4695 wback = false;
4696
4697 // (shift_t, shift_n) = (SRType_LSL, 0);
4698 shift_t = SRType_LSL;
4699 shift_n = 0;
4700 break;
4701
4702 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004703 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004704 if (Bits32 (opcode, 19, 16) == 15)
4705 return false;
4706
4707 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4708 t = Bits32 (opcode, 15, 12);
4709 n = Bits32 (opcode, 19, 16);
4710 m = Bits32 (opcode, 3, 0);
4711
4712 // index = TRUE; add = TRUE; wback = FALSE;
4713 index = true;
4714 add = true;
4715 wback = false;
4716
4717 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4718 shift_t = SRType_LSL;
4719 shift_n = Bits32 (opcode, 5, 4);
4720
4721 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4722 if ((t == 15) || (BadReg (m)))
4723 return false;
4724 break;
4725
4726 case eEncodingA1:
4727 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004728 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004729 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4730 t = Bits32 (opcode, 15, 12);
4731 n = Bits32 (opcode, 19, 16);
4732 m = Bits32 (opcode, 3, 0);
4733
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004734 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004735 index = BitIsSet (opcode, 24);
4736 add = BitIsSet (opcode, 23);
4737 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4738
4739 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4740 uint32_t typ = Bits32 (opcode, 6, 5);
4741 uint32_t imm5 = Bits32 (opcode, 11, 7);
4742 shift_n = DecodeImmShift(typ, imm5, shift_t);
4743
4744 // if m == 15 then UNPREDICTABLE;
4745 if (m == 15)
4746 return false;
4747
4748 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4749 if (wback && ((n == 15) || (n == t)))
4750 return false;
4751
4752 break;
4753 }
4754 default:
4755 return false;
4756 }
4757
4758 addr_t offset_addr;
4759 addr_t address;
4760 int32_t offset = 0;
4761
4762 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4763 if (!success)
4764 return false;
4765
4766 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4767 if (!success)
4768 return false;
4769
4770 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004771 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004772
4773 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4774 if (add)
4775 offset_addr = base_address + offset;
4776 else
4777 offset_addr = base_address - offset;
4778
4779 // address = if index then offset_addr else R[n];
4780 if (index)
4781 address = offset_addr;
4782 else
4783 address = base_address;
4784
4785 uint32_t data;
4786 // if t == 15 then // Only possible for encoding A1
4787 if (t == 15)
4788 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004789 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004790 else
4791 // data = R[t];
4792 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4793
4794 if (!success)
4795 return false;
4796
4797 EmulateInstruction::Context context;
4798 context.type = eContextRegisterStore;
4799
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004800 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004801 if (UnalignedSupport ()
4802 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4803 || CurrentInstrSet() == eModeARM)
4804 {
4805 // MemU[address,4] = data;
4806
Greg Claytonc07d4512011-04-26 23:48:45 +00004807 RegisterInfo base_reg;
4808 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004809
Greg Claytonc07d4512011-04-26 23:48:45 +00004810 RegisterInfo data_reg;
4811 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004812
4813 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004814 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004815 return false;
4816
4817 }
4818 else
4819 // MemU[address,4] = bits(32) UNKNOWN;
4820 WriteBits32UnknownToMemory (address);
4821
4822 // if wback then R[n] = offset_addr;
4823 if (wback)
4824 {
4825 context.type = eContextRegisterLoad;
4826 context.SetAddress (offset_addr);
4827 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4828 return false;
4829 }
4830
4831 }
4832 return true;
4833}
Caroline Tice73a29de2011-02-16 20:22:22 +00004834
4835bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004836EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004837{
4838#if 0
4839 if ConditionPassed() then
4840 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4841 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4842 address = if index then offset_addr else R[n];
4843 MemU[address,1] = R[t]<7:0>;
4844 if wback then R[n] = offset_addr;
4845#endif
4846
4847
4848 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004849
Greg Clayton7bc39082011-03-24 23:53:38 +00004850 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004851 {
4852 uint32_t t;
4853 uint32_t n;
4854 uint32_t imm32;
4855 bool index;
4856 bool add;
4857 bool wback;
4858 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4859 switch (encoding)
4860 {
4861 case eEncodingT1:
4862 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4863 t = Bits32 (opcode, 2, 0);
4864 n = Bits32 (opcode, 5, 3);
4865 imm32 = Bits32 (opcode, 10, 6);
4866
4867 // index = TRUE; add = TRUE; wback = FALSE;
4868 index = true;
4869 add = true;
4870 wback = false;
4871 break;
4872
4873 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004874 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004875 if (Bits32 (opcode, 19, 16) == 15)
4876 return false;
4877
4878 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4879 t = Bits32 (opcode, 15, 12);
4880 n = Bits32 (opcode, 19, 16);
4881 imm32 = Bits32 (opcode, 11, 0);
4882
4883 // index = TRUE; add = TRUE; wback = FALSE;
4884 index = true;
4885 add = true;
4886 wback = false;
4887
4888 // if BadReg(t) then UNPREDICTABLE;
4889 if (BadReg (t))
4890 return false;
4891 break;
4892
4893 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004894 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4895 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004896 if (Bits32 (opcode, 19, 16) == 15)
4897 return false;
4898
4899 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4900 t = Bits32 (opcode, 15, 12);
4901 n = Bits32 (opcode, 19, 16);
4902 imm32 = Bits32 (opcode, 7, 0);
4903
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004904 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004905 index = BitIsSet (opcode, 10);
4906 add = BitIsSet (opcode, 9);
4907 wback = BitIsSet (opcode, 8);
4908
4909 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4910 if ((BadReg (t)) || (wback && (n == t)))
4911 return false;
4912 break;
4913
4914 default:
4915 return false;
4916 }
4917
4918 addr_t offset_addr;
4919 addr_t address;
4920 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4921 if (!success)
4922 return false;
4923
4924 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4925 if (add)
4926 offset_addr = base_address + imm32;
4927 else
4928 offset_addr = base_address - imm32;
4929
4930 // address = if index then offset_addr else R[n];
4931 if (index)
4932 address = offset_addr;
4933 else
4934 address = base_address;
4935
Caroline Ticecc96eb52011-02-17 19:20:40 +00004936 // MemU[address,1] = R[t]<7:0>
Greg Claytonc07d4512011-04-26 23:48:45 +00004937 RegisterInfo base_reg;
4938 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004939
Greg Claytonc07d4512011-04-26 23:48:45 +00004940 RegisterInfo data_reg;
4941 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004942
4943 EmulateInstruction::Context context;
4944 context.type = eContextRegisterStore;
4945 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4946
4947 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4948 if (!success)
4949 return false;
4950
4951 data = Bits32 (data, 7, 0);
4952
Caroline Ticecc96eb52011-02-17 19:20:40 +00004953 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004954 return false;
4955
4956 // if wback then R[n] = offset_addr;
4957 if (wback)
4958 {
4959 context.type = eContextRegisterLoad;
4960 context.SetAddress (offset_addr);
4961 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4962 return false;
4963 }
4964
4965 }
4966
4967 return true;
4968}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004969
4970// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4971// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4972bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004973EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004974{
4975#if 0
4976 if ConditionPassed() then
4977 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4978 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4979 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4980 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004981 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004982 MemU[address,2] = R[t]<15:0>;
4983 else // Can only occur before ARMv7
4984 MemU[address,2] = bits(16) UNKNOWN;
4985 if wback then R[n] = offset_addr;
4986#endif
4987
4988 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004989
Greg Clayton7bc39082011-03-24 23:53:38 +00004990 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004991 {
4992 uint32_t t;
4993 uint32_t n;
4994 uint32_t m;
4995 bool index;
4996 bool add;
4997 bool wback;
4998 ARM_ShifterType shift_t;
4999 uint32_t shift_n;
5000
5001 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5002 switch (encoding)
5003 {
5004 case eEncodingT1:
5005 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5006 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5007 t = Bits32 (opcode, 2, 0);
5008 n = Bits32 (opcode, 5, 3);
5009 m = Bits32 (opcode, 8, 6);
5010
5011 // index = TRUE; add = TRUE; wback = FALSE;
5012 index = true;
5013 add = true;
5014 wback = false;
5015
5016 // (shift_t, shift_n) = (SRType_LSL, 0);
5017 shift_t = SRType_LSL;
5018 shift_n = 0;
5019
5020 break;
5021
5022 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005023 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005024 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5025 t = Bits32 (opcode, 15, 12);
5026 n = Bits32 (opcode, 19, 16);
5027 m = Bits32 (opcode, 3, 0);
5028 if (n == 15)
5029 return false;
5030
5031 // index = TRUE; add = TRUE; wback = FALSE;
5032 index = true;
5033 add = true;
5034 wback = false;
5035
5036 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5037 shift_t = SRType_LSL;
5038 shift_n = Bits32 (opcode, 5, 4);
5039
5040 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5041 if (BadReg (t) || BadReg (m))
5042 return false;
5043
5044 break;
5045
5046 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005047 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005048 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5049 t = Bits32 (opcode, 15, 12);
5050 n = Bits32 (opcode, 19, 16);
5051 m = Bits32 (opcode, 3, 0);
5052
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005053 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005054 index = BitIsSet (opcode, 24);
5055 add = BitIsSet (opcode, 23);
5056 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5057
5058 // (shift_t, shift_n) = (SRType_LSL, 0);
5059 shift_t = SRType_LSL;
5060 shift_n = 0;
5061
5062 // if t == 15 || m == 15 then UNPREDICTABLE;
5063 if ((t == 15) || (m == 15))
5064 return false;
5065
5066 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5067 if (wback && ((n == 15) || (n == t)))
5068 return false;
5069
5070 break;
5071
5072 default:
5073 return false;
5074 }
5075
5076 uint32_t Rm = ReadCoreReg (m, &success);
5077 if (!success)
5078 return false;
5079
5080 uint32_t Rn = ReadCoreReg (n, &success);
5081 if (!success)
5082 return false;
5083
5084 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5085 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5086
5087 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5088 addr_t offset_addr;
5089 if (add)
5090 offset_addr = Rn + offset;
5091 else
5092 offset_addr = Rn - offset;
5093
5094 // address = if index then offset_addr else R[n];
5095 addr_t address;
5096 if (index)
5097 address = offset_addr;
5098 else
5099 address = Rn;
5100
5101 EmulateInstruction::Context context;
5102 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005103 RegisterInfo base_reg;
5104 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5105 RegisterInfo offset_reg;
5106 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005107
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005108 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005109 if (UnalignedSupport() || BitIsClear (address, 0))
5110 {
5111 // MemU[address,2] = R[t]<15:0>;
5112 uint32_t Rt = ReadCoreReg (t, &success);
5113 if (!success)
5114 return false;
5115
5116 EmulateInstruction::Context context;
5117 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005118 RegisterInfo base_reg;
5119 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5120 RegisterInfo offset_reg;
5121 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5122 RegisterInfo data_reg;
5123 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005124 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5125
5126 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5127 return false;
5128 }
5129 else // Can only occur before ARMv7
5130 {
5131 // MemU[address,2] = bits(16) UNKNOWN;
5132 }
5133
5134 // if wback then R[n] = offset_addr;
5135 if (wback)
5136 {
5137 context.type = eContextAdjustBaseRegister;
5138 context.SetAddress (offset_addr);
5139 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5140 return false;
5141 }
5142 }
5143
5144 return true;
5145}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005146
Johnny Chen157b9592011-02-18 21:13:05 +00005147// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5148// and writes the result to the destination register. It can optionally update the condition flags
5149// based on the result.
5150bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005151EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005152{
5153#if 0
5154 // ARM pseudo code...
5155 if ConditionPassed() then
5156 EncodingSpecificOperations();
5157 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5158 if d == 15 then // Can only occur for ARM encoding
5159 ALUWritePC(result); // setflags is always FALSE here
5160 else
5161 R[d] = result;
5162 if setflags then
5163 APSR.N = result<31>;
5164 APSR.Z = IsZeroBit(result);
5165 APSR.C = carry;
5166 APSR.V = overflow;
5167#endif
5168
5169 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005170
Greg Clayton7bc39082011-03-24 23:53:38 +00005171 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005172 {
5173 uint32_t Rd, Rn;
5174 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5175 bool setflags;
5176 switch (encoding)
5177 {
5178 case eEncodingT1:
5179 Rd = Bits32(opcode, 11, 8);
5180 Rn = Bits32(opcode, 19, 16);
5181 setflags = BitIsSet(opcode, 20);
5182 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5183 if (BadReg(Rd) || BadReg(Rn))
5184 return false;
5185 break;
5186 case eEncodingA1:
5187 Rd = Bits32(opcode, 15, 12);
5188 Rn = Bits32(opcode, 19, 16);
5189 setflags = BitIsSet(opcode, 20);
5190 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005191
Johnny Chen157b9592011-02-18 21:13:05 +00005192 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005193 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005194 break;
5195 default:
5196 return false;
5197 }
5198
5199 // Read the first operand.
5200 int32_t val1 = ReadCoreReg(Rn, &success);
5201 if (!success)
5202 return false;
5203
5204 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5205
5206 EmulateInstruction::Context context;
5207 context.type = EmulateInstruction::eContextImmediate;
5208 context.SetNoArgs ();
5209
5210 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5211 return false;
5212 }
5213 return true;
5214}
5215
5216// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5217// register value, and writes the result to the destination register. It can optionally update the
5218// condition flags based on the result.
5219bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005220EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005221{
5222#if 0
5223 // ARM pseudo code...
5224 if ConditionPassed() then
5225 EncodingSpecificOperations();
5226 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5227 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5228 if d == 15 then // Can only occur for ARM encoding
5229 ALUWritePC(result); // setflags is always FALSE here
5230 else
5231 R[d] = result;
5232 if setflags then
5233 APSR.N = result<31>;
5234 APSR.Z = IsZeroBit(result);
5235 APSR.C = carry;
5236 APSR.V = overflow;
5237#endif
5238
5239 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005240
Greg Clayton7bc39082011-03-24 23:53:38 +00005241 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005242 {
5243 uint32_t Rd, Rn, Rm;
5244 ARM_ShifterType shift_t;
5245 uint32_t shift_n; // the shift applied to the value read from Rm
5246 bool setflags;
5247 switch (encoding)
5248 {
5249 case eEncodingT1:
5250 Rd = Rn = Bits32(opcode, 2, 0);
5251 Rm = Bits32(opcode, 5, 3);
5252 setflags = !InITBlock();
5253 shift_t = SRType_LSL;
5254 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005255 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005256 case eEncodingT2:
5257 Rd = Bits32(opcode, 11, 8);
5258 Rn = Bits32(opcode, 19, 16);
5259 Rm = Bits32(opcode, 3, 0);
5260 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005261 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005262 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5263 return false;
5264 break;
5265 case eEncodingA1:
5266 Rd = Bits32(opcode, 15, 12);
5267 Rn = Bits32(opcode, 19, 16);
5268 Rm = Bits32(opcode, 3, 0);
5269 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005270 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005271
Johnny Chen157b9592011-02-18 21:13:05 +00005272 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005273 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005274 break;
5275 default:
5276 return false;
5277 }
5278
5279 // Read the first operand.
5280 int32_t val1 = ReadCoreReg(Rn, &success);
5281 if (!success)
5282 return false;
5283
5284 // Read the second operand.
5285 int32_t val2 = ReadCoreReg(Rm, &success);
5286 if (!success)
5287 return false;
5288
5289 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5290 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5291
5292 EmulateInstruction::Context context;
5293 context.type = EmulateInstruction::eContextImmediate;
5294 context.SetNoArgs ();
5295
5296 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5297 return false;
5298 }
5299 return true;
5300}
5301
Johnny Chena695f952011-02-23 21:24:25 +00005302// This instruction adds an immediate value to the PC value to form a PC-relative address,
5303// and writes the result to the destination register.
5304bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005305EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005306{
5307#if 0
5308 // ARM pseudo code...
5309 if ConditionPassed() then
5310 EncodingSpecificOperations();
5311 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5312 if d == 15 then // Can only occur for ARM encodings
5313 ALUWritePC(result);
5314 else
5315 R[d] = result;
5316#endif
5317
5318 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005319
Greg Clayton7bc39082011-03-24 23:53:38 +00005320 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005321 {
5322 uint32_t Rd;
5323 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5324 bool add;
5325 switch (encoding)
5326 {
5327 case eEncodingT1:
5328 Rd = Bits32(opcode, 10, 8);
5329 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5330 break;
5331 case eEncodingT2:
5332 case eEncodingT3:
5333 Rd = Bits32(opcode, 11, 8);
5334 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5335 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5336 if (BadReg(Rd))
5337 return false;
5338 break;
5339 case eEncodingA1:
5340 case eEncodingA2:
5341 Rd = Bits32(opcode, 15, 12);
5342 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5343 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5344 break;
5345 default:
5346 return false;
5347 }
5348
5349 // Read the PC value.
5350 uint32_t pc = ReadCoreReg(PC_REG, &success);
5351 if (!success)
5352 return false;
5353
5354 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5355
5356 EmulateInstruction::Context context;
5357 context.type = EmulateInstruction::eContextImmediate;
5358 context.SetNoArgs ();
5359
5360 if (!WriteCoreReg(context, result, Rd))
5361 return false;
5362 }
5363 return true;
5364}
5365
Johnny Chene97c0d52011-02-18 19:32:20 +00005366// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5367// to the destination register. It can optionally update the condition flags based on the result.
5368bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005369EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005370{
5371#if 0
5372 // ARM pseudo code...
5373 if ConditionPassed() then
5374 EncodingSpecificOperations();
5375 result = R[n] AND imm32;
5376 if d == 15 then // Can only occur for ARM encoding
5377 ALUWritePC(result); // setflags is always FALSE here
5378 else
5379 R[d] = result;
5380 if setflags then
5381 APSR.N = result<31>;
5382 APSR.Z = IsZeroBit(result);
5383 APSR.C = carry;
5384 // APSR.V unchanged
5385#endif
5386
5387 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005388
Greg Clayton7bc39082011-03-24 23:53:38 +00005389 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005390 {
5391 uint32_t Rd, Rn;
5392 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5393 bool setflags;
5394 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5395 switch (encoding)
5396 {
5397 case eEncodingT1:
5398 Rd = Bits32(opcode, 11, 8);
5399 Rn = Bits32(opcode, 19, 16);
5400 setflags = BitIsSet(opcode, 20);
5401 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005402 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005403 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005404 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005405 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5406 return false;
5407 break;
5408 case eEncodingA1:
5409 Rd = Bits32(opcode, 15, 12);
5410 Rn = Bits32(opcode, 19, 16);
5411 setflags = BitIsSet(opcode, 20);
5412 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005413
Johnny Chene97c0d52011-02-18 19:32:20 +00005414 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005415 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005416 break;
5417 default:
5418 return false;
5419 }
5420
Johnny Chene97c0d52011-02-18 19:32:20 +00005421 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005422 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005423 if (!success)
5424 return false;
5425
5426 uint32_t result = val1 & imm32;
5427
5428 EmulateInstruction::Context context;
5429 context.type = EmulateInstruction::eContextImmediate;
5430 context.SetNoArgs ();
5431
5432 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5433 return false;
5434 }
5435 return true;
5436}
5437
5438// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5439// and writes the result to the destination register. It can optionally update the condition flags
5440// based on the result.
5441bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005442EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005443{
5444#if 0
5445 // ARM pseudo code...
5446 if ConditionPassed() then
5447 EncodingSpecificOperations();
5448 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5449 result = R[n] AND shifted;
5450 if d == 15 then // Can only occur for ARM encoding
5451 ALUWritePC(result); // setflags is always FALSE here
5452 else
5453 R[d] = result;
5454 if setflags then
5455 APSR.N = result<31>;
5456 APSR.Z = IsZeroBit(result);
5457 APSR.C = carry;
5458 // APSR.V unchanged
5459#endif
5460
5461 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005462
Greg Clayton7bc39082011-03-24 23:53:38 +00005463 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005464 {
5465 uint32_t Rd, Rn, Rm;
5466 ARM_ShifterType shift_t;
5467 uint32_t shift_n; // the shift applied to the value read from Rm
5468 bool setflags;
5469 uint32_t carry;
5470 switch (encoding)
5471 {
5472 case eEncodingT1:
5473 Rd = Rn = Bits32(opcode, 2, 0);
5474 Rm = Bits32(opcode, 5, 3);
5475 setflags = !InITBlock();
5476 shift_t = SRType_LSL;
5477 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005478 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005479 case eEncodingT2:
5480 Rd = Bits32(opcode, 11, 8);
5481 Rn = Bits32(opcode, 19, 16);
5482 Rm = Bits32(opcode, 3, 0);
5483 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005484 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005485 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005486 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005487 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005488 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5489 return false;
5490 break;
5491 case eEncodingA1:
5492 Rd = Bits32(opcode, 15, 12);
5493 Rn = Bits32(opcode, 19, 16);
5494 Rm = Bits32(opcode, 3, 0);
5495 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005496 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005497
Johnny Chene97c0d52011-02-18 19:32:20 +00005498 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005499 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005500 break;
5501 default:
5502 return false;
5503 }
5504
Johnny Chene97c0d52011-02-18 19:32:20 +00005505 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005506 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005507 if (!success)
5508 return false;
5509
5510 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005511 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005512 if (!success)
5513 return false;
5514
5515 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5516 uint32_t result = val1 & shifted;
5517
5518 EmulateInstruction::Context context;
5519 context.type = EmulateInstruction::eContextImmediate;
5520 context.SetNoArgs ();
5521
5522 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5523 return false;
5524 }
5525 return true;
5526}
5527
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005528// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5529// immediate value, and writes the result to the destination register. It can optionally update the
5530// condition flags based on the result.
5531bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005532EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005533{
5534#if 0
5535 // ARM pseudo code...
5536 if ConditionPassed() then
5537 EncodingSpecificOperations();
5538 result = R[n] AND NOT(imm32);
5539 if d == 15 then // Can only occur for ARM encoding
5540 ALUWritePC(result); // setflags is always FALSE here
5541 else
5542 R[d] = result;
5543 if setflags then
5544 APSR.N = result<31>;
5545 APSR.Z = IsZeroBit(result);
5546 APSR.C = carry;
5547 // APSR.V unchanged
5548#endif
5549
5550 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005551
Greg Clayton7bc39082011-03-24 23:53:38 +00005552 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005553 {
5554 uint32_t Rd, Rn;
5555 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5556 bool setflags;
5557 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5558 switch (encoding)
5559 {
5560 case eEncodingT1:
5561 Rd = Bits32(opcode, 11, 8);
5562 Rn = Bits32(opcode, 19, 16);
5563 setflags = BitIsSet(opcode, 20);
5564 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5565 if (BadReg(Rd) || BadReg(Rn))
5566 return false;
5567 break;
5568 case eEncodingA1:
5569 Rd = Bits32(opcode, 15, 12);
5570 Rn = Bits32(opcode, 19, 16);
5571 setflags = BitIsSet(opcode, 20);
5572 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005573
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005574 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005575 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005576 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005577 break;
5578 default:
5579 return false;
5580 }
5581
5582 // Read the first operand.
5583 uint32_t val1 = ReadCoreReg(Rn, &success);
5584 if (!success)
5585 return false;
5586
5587 uint32_t result = val1 & ~imm32;
5588
5589 EmulateInstruction::Context context;
5590 context.type = EmulateInstruction::eContextImmediate;
5591 context.SetNoArgs ();
5592
5593 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5594 return false;
5595 }
5596 return true;
5597}
5598
5599// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5600// optionally-shifted register value, and writes the result to the destination register.
5601// It can optionally update the condition flags based on the result.
5602bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005603EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005604{
5605#if 0
5606 // ARM pseudo code...
5607 if ConditionPassed() then
5608 EncodingSpecificOperations();
5609 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5610 result = R[n] AND NOT(shifted);
5611 if d == 15 then // Can only occur for ARM encoding
5612 ALUWritePC(result); // setflags is always FALSE here
5613 else
5614 R[d] = result;
5615 if setflags then
5616 APSR.N = result<31>;
5617 APSR.Z = IsZeroBit(result);
5618 APSR.C = carry;
5619 // APSR.V unchanged
5620#endif
5621
5622 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005623
Greg Clayton7bc39082011-03-24 23:53:38 +00005624 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005625 {
5626 uint32_t Rd, Rn, Rm;
5627 ARM_ShifterType shift_t;
5628 uint32_t shift_n; // the shift applied to the value read from Rm
5629 bool setflags;
5630 uint32_t carry;
5631 switch (encoding)
5632 {
5633 case eEncodingT1:
5634 Rd = Rn = Bits32(opcode, 2, 0);
5635 Rm = Bits32(opcode, 5, 3);
5636 setflags = !InITBlock();
5637 shift_t = SRType_LSL;
5638 shift_n = 0;
5639 break;
5640 case eEncodingT2:
5641 Rd = Bits32(opcode, 11, 8);
5642 Rn = Bits32(opcode, 19, 16);
5643 Rm = Bits32(opcode, 3, 0);
5644 setflags = BitIsSet(opcode, 20);
5645 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5646 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5647 return false;
5648 break;
5649 case eEncodingA1:
5650 Rd = Bits32(opcode, 15, 12);
5651 Rn = Bits32(opcode, 19, 16);
5652 Rm = Bits32(opcode, 3, 0);
5653 setflags = BitIsSet(opcode, 20);
5654 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005655
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005656 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005657 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005658 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005659 break;
5660 default:
5661 return false;
5662 }
5663
5664 // Read the first operand.
5665 uint32_t val1 = ReadCoreReg(Rn, &success);
5666 if (!success)
5667 return false;
5668
5669 // Read the second operand.
5670 uint32_t val2 = ReadCoreReg(Rm, &success);
5671 if (!success)
5672 return false;
5673
5674 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5675 uint32_t result = val1 & ~shifted;
5676
5677 EmulateInstruction::Context context;
5678 context.type = EmulateInstruction::eContextImmediate;
5679 context.SetNoArgs ();
5680
5681 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5682 return false;
5683 }
5684 return true;
5685}
5686
Caroline Tice4d729c52011-02-18 00:55:53 +00005687// 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 +00005688// 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 +00005689bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005690EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005691{
5692#if 0
5693 if ConditionPassed() then
5694 EncodingSpecificOperations();
5695 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5696 address = if index then offset_addr else R[n];
5697 data = MemU[address,4];
5698 if wback then R[n] = offset_addr;
5699 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005700 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5701 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005702 R[t] = data;
5703 else // Can only apply before ARMv7
5704 R[t] = ROR(data, 8*UInt(address<1:0>));
5705#endif
5706
5707 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005708
Greg Clayton7bc39082011-03-24 23:53:38 +00005709 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005710 {
5711 const uint32_t addr_byte_size = GetAddressByteSize();
5712
5713 uint32_t t;
5714 uint32_t n;
5715 uint32_t imm32;
5716 bool index;
5717 bool add;
5718 bool wback;
5719
5720 switch (encoding)
5721 {
5722 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005723 // if Rn == '1111' then SEE LDR (literal);
5724 // if P == '0' && W == '1' then SEE LDRT;
5725 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005726 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5727 t = Bits32 (opcode, 15, 12);
5728 n = Bits32 (opcode, 19, 16);
5729 imm32 = Bits32 (opcode, 11, 0);
5730
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005731 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5732 index = BitIsSet (opcode, 24);
5733 add = BitIsSet (opcode, 23);
5734 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005735
5736 // if wback && n == t then UNPREDICTABLE;
5737 if (wback && (n == t))
5738 return false;
5739
5740 break;
5741
5742 default:
5743 return false;
5744 }
5745
5746 addr_t address;
5747 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005748 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005749 if (!success)
5750 return false;
5751
5752 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5753 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005754 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005755 else
5756 offset_addr = base_address - imm32;
5757
5758 // address = if index then offset_addr else R[n];
5759 if (index)
5760 address = offset_addr;
5761 else
5762 address = base_address;
5763
5764 // data = MemU[address,4];
5765
Greg Claytonc07d4512011-04-26 23:48:45 +00005766 RegisterInfo base_reg;
5767 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4d729c52011-02-18 00:55:53 +00005768
5769 EmulateInstruction::Context context;
5770 context.type = eContextRegisterLoad;
5771 context.SetRegisterPlusOffset (base_reg, address - base_address);
5772
5773 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5774 if (!success)
5775 return false;
5776
5777 // if wback then R[n] = offset_addr;
5778 if (wback)
5779 {
5780 context.type = eContextAdjustBaseRegister;
5781 context.SetAddress (offset_addr);
5782 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5783 return false;
5784 }
5785
5786 // if t == 15 then
5787 if (t == 15)
5788 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005789 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005790 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5791 {
5792 // LoadWritePC (data);
5793 context.type = eContextRegisterLoad;
5794 context.SetRegisterPlusOffset (base_reg, address - base_address);
5795 LoadWritePC (context, data);
5796 }
5797 else
5798 return false;
5799 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005800 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005801 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5802 {
5803 // R[t] = data;
5804 context.type = eContextRegisterLoad;
5805 context.SetRegisterPlusOffset (base_reg, address - base_address);
5806 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5807 return false;
5808 }
5809 // else // Can only apply before ARMv7
5810 else
5811 {
5812 // R[t] = ROR(data, 8*UInt(address<1:0>));
5813 data = ROR (data, Bits32 (address, 1, 0));
5814 context.type = eContextRegisterLoad;
5815 context.SetImmediate (data);
5816 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5817 return false;
5818 }
5819
5820 }
5821 return true;
5822}
5823
Caroline Ticefe479112011-02-18 18:52:37 +00005824// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5825// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5826bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005827EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005828{
5829#if 0
5830 if ConditionPassed() then
5831 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5832 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5833 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5834 address = if index then offset_addr else R[n];
5835 data = MemU[address,4];
5836 if wback then R[n] = offset_addr;
5837 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005838 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5839 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005840 R[t] = data;
5841 else // Can only apply before ARMv7
5842 if CurrentInstrSet() == InstrSet_ARM then
5843 R[t] = ROR(data, 8*UInt(address<1:0>));
5844 else
5845 R[t] = bits(32) UNKNOWN;
5846#endif
5847
5848 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005849
Greg Clayton7bc39082011-03-24 23:53:38 +00005850 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005851 {
5852 const uint32_t addr_byte_size = GetAddressByteSize();
5853
5854 uint32_t t;
5855 uint32_t n;
5856 uint32_t m;
5857 bool index;
5858 bool add;
5859 bool wback;
5860 ARM_ShifterType shift_t;
5861 uint32_t shift_n;
5862
5863 switch (encoding)
5864 {
5865 case eEncodingT1:
5866 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5867 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5868 t = Bits32 (opcode, 2, 0);
5869 n = Bits32 (opcode, 5, 3);
5870 m = Bits32 (opcode, 8, 6);
5871
5872 // index = TRUE; add = TRUE; wback = FALSE;
5873 index = true;
5874 add = true;
5875 wback = false;
5876
5877 // (shift_t, shift_n) = (SRType_LSL, 0);
5878 shift_t = SRType_LSL;
5879 shift_n = 0;
5880
5881 break;
5882
5883 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005884 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005885 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5886 t = Bits32 (opcode, 15, 12);
5887 n = Bits32 (opcode, 19, 16);
5888 m = Bits32 (opcode, 3, 0);
5889
5890 // index = TRUE; add = TRUE; wback = FALSE;
5891 index = true;
5892 add = true;
5893 wback = false;
5894
5895 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5896 shift_t = SRType_LSL;
5897 shift_n = Bits32 (opcode, 5, 4);
5898
5899 // if BadReg(m) then UNPREDICTABLE;
5900 if (BadReg (m))
5901 return false;
5902
5903 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5904 if ((t == 15) && InITBlock() && !LastInITBlock())
5905 return false;
5906
5907 break;
5908
5909 case eEncodingA1:
5910 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005911 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005912 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5913 t = Bits32 (opcode, 15, 12);
5914 n = Bits32 (opcode, 19, 16);
5915 m = Bits32 (opcode, 3, 0);
5916
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005917 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005918 index = BitIsSet (opcode, 24);
5919 add = BitIsSet (opcode, 23);
5920 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5921
5922 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5923 uint32_t type = Bits32 (opcode, 6, 5);
5924 uint32_t imm5 = Bits32 (opcode, 11, 7);
5925 shift_n = DecodeImmShift (type, imm5, shift_t);
5926
5927 // if m == 15 then UNPREDICTABLE;
5928 if (m == 15)
5929 return false;
5930
5931 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5932 if (wback && ((n == 15) || (n == t)))
5933 return false;
5934 }
5935 break;
5936
5937
5938 default:
5939 return false;
5940 }
5941
5942 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5943 if (!success)
5944 return false;
5945
5946 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5947 if (!success)
5948 return false;
5949
5950 addr_t offset_addr;
5951 addr_t address;
5952
5953 // 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 +00005954 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005955
5956 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5957 if (add)
5958 offset_addr = Rn + offset;
5959 else
5960 offset_addr = Rn - offset;
5961
5962 // address = if index then offset_addr else R[n];
5963 if (index)
5964 address = offset_addr;
5965 else
5966 address = Rn;
5967
5968 // data = MemU[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +00005969 RegisterInfo base_reg;
5970 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefe479112011-02-18 18:52:37 +00005971
5972 EmulateInstruction::Context context;
5973 context.type = eContextRegisterLoad;
5974 context.SetRegisterPlusOffset (base_reg, address - Rn);
5975
5976 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5977 if (!success)
5978 return false;
5979
5980 // if wback then R[n] = offset_addr;
5981 if (wback)
5982 {
5983 context.type = eContextAdjustBaseRegister;
5984 context.SetAddress (offset_addr);
5985 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5986 return false;
5987 }
5988
5989 // if t == 15 then
5990 if (t == 15)
5991 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005992 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005993 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5994 {
5995 context.type = eContextRegisterLoad;
5996 context.SetRegisterPlusOffset (base_reg, address - Rn);
5997 LoadWritePC (context, data);
5998 }
5999 else
6000 return false;
6001 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006002 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00006003 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
6004 {
6005 // R[t] = data;
6006 context.type = eContextRegisterLoad;
6007 context.SetRegisterPlusOffset (base_reg, address - Rn);
6008 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6009 return false;
6010 }
6011 else // Can only apply before ARMv7
6012 {
6013 // if CurrentInstrSet() == InstrSet_ARM then
6014 if (CurrentInstrSet () == eModeARM)
6015 {
6016 // R[t] = ROR(data, 8*UInt(address<1:0>));
6017 data = ROR (data, Bits32 (address, 1, 0));
6018 context.type = eContextRegisterLoad;
6019 context.SetImmediate (data);
6020 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6021 return false;
6022 }
6023 else
6024 {
6025 // R[t] = bits(32) UNKNOWN;
6026 WriteBits32Unknown (t);
6027 }
6028 }
6029 }
6030 return true;
6031}
Caroline Tice21b604b2011-02-18 21:06:04 +00006032
6033// LDRB (immediate, Thumb)
6034bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006035EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00006036{
6037#if 0
6038 if ConditionPassed() then
6039 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6040 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6041 address = if index then offset_addr else R[n];
6042 R[t] = ZeroExtend(MemU[address,1], 32);
6043 if wback then R[n] = offset_addr;
6044#endif
6045
6046 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00006047
Greg Clayton7bc39082011-03-24 23:53:38 +00006048 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00006049 {
6050 uint32_t t;
6051 uint32_t n;
6052 uint32_t imm32;
6053 bool index;
6054 bool add;
6055 bool wback;
6056
6057 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6058 switch (encoding)
6059 {
6060 case eEncodingT1:
6061 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6062 t = Bits32 (opcode, 2, 0);
6063 n = Bits32 (opcode, 5, 3);
6064 imm32 = Bits32 (opcode, 10, 6);
6065
6066 // index = TRUE; add = TRUE; wback = FALSE;
6067 index = true;
6068 add = true;
6069 wback= false;
6070
6071 break;
6072
6073 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006074 // if Rt == '1111' then SEE PLD;
6075 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006076 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6077 t = Bits32 (opcode, 15, 12);
6078 n = Bits32 (opcode, 19, 16);
6079 imm32 = Bits32 (opcode, 11, 0);
6080
6081 // index = TRUE; add = TRUE; wback = FALSE;
6082 index = true;
6083 add = true;
6084 wback = false;
6085
6086 // if t == 13 then UNPREDICTABLE;
6087 if (t == 13)
6088 return false;
6089
6090 break;
6091
6092 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006093 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6094 // if Rn == '1111' then SEE LDRB (literal);
6095 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6096 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006097 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6098 return false;
6099
6100 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6101 t = Bits32 (opcode, 15, 12);
6102 n = Bits32 (opcode, 19, 16);
6103 imm32 = Bits32 (opcode, 7, 0);
6104
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006105 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006106 index = BitIsSet (opcode, 10);
6107 add = BitIsSet (opcode, 9);
6108 wback = BitIsSet (opcode, 8);
6109
6110 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6111 if (BadReg (t) || (wback && (n == t)))
6112 return false;
6113
6114 break;
6115
6116 default:
6117 return false;
6118 }
6119
6120 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6121 if (!success)
6122 return false;
6123
6124 addr_t address;
6125 addr_t offset_addr;
6126
6127 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6128 if (add)
6129 offset_addr = Rn + imm32;
6130 else
6131 offset_addr = Rn - imm32;
6132
6133 // address = if index then offset_addr else R[n];
6134 if (index)
6135 address = offset_addr;
6136 else
6137 address = Rn;
6138
6139 // R[t] = ZeroExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006140 RegisterInfo base_reg;
6141 RegisterInfo data_reg;
6142 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6143 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice21b604b2011-02-18 21:06:04 +00006144
6145 EmulateInstruction::Context context;
6146 context.type = eContextRegisterLoad;
6147 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6148
6149 uint64_t data = MemURead (context, address, 1, 0, &success);
6150 if (!success)
6151 return false;
6152
6153 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6154 return false;
6155
6156 // if wback then R[n] = offset_addr;
6157 if (wback)
6158 {
6159 context.type = eContextAdjustBaseRegister;
6160 context.SetAddress (offset_addr);
6161 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6162 return false;
6163 }
6164 }
6165 return true;
6166}
Caroline Ticef55261f2011-02-18 22:24:22 +00006167
6168// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6169// zero-extends it to form a 32-bit word and writes it to a register.
6170bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006171EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006172{
6173#if 0
6174 if ConditionPassed() then
6175 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6176 base = Align(PC,4);
6177 address = if add then (base + imm32) else (base - imm32);
6178 R[t] = ZeroExtend(MemU[address,1], 32);
6179#endif
6180
6181 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006182
Greg Clayton7bc39082011-03-24 23:53:38 +00006183 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006184 {
6185 uint32_t t;
6186 uint32_t imm32;
6187 bool add;
6188 switch (encoding)
6189 {
6190 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006191 // if Rt == '1111' then SEE PLD;
6192 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006193 t = Bits32 (opcode, 15, 12);
6194 imm32 = Bits32 (opcode, 11, 0);
6195 add = BitIsSet (opcode, 23);
6196
6197 // if t == 13 then UNPREDICTABLE;
6198 if (t == 13)
6199 return false;
6200
6201 break;
6202
6203 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006204 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006205 t = Bits32 (opcode, 15, 12);
6206 imm32 = Bits32 (opcode, 11, 0);
6207 add = BitIsSet (opcode, 23);
6208
6209 // if t == 15 then UNPREDICTABLE;
6210 if (t == 15)
6211 return false;
6212 break;
6213
6214 default:
6215 return false;
6216 }
6217
6218 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006219 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006220 if (!success)
6221 return false;
6222
6223 uint32_t base = AlignPC (pc_val);
6224
6225 addr_t address;
6226 // address = if add then (base + imm32) else (base - imm32);
6227 if (add)
6228 address = base + imm32;
6229 else
6230 address = base - imm32;
6231
6232 // R[t] = ZeroExtend(MemU[address,1], 32);
6233 EmulateInstruction::Context context;
6234 context.type = eContextRelativeBranchImmediate;
6235 context.SetImmediate (address - base);
6236
6237 uint64_t data = MemURead (context, address, 1, 0, &success);
6238 if (!success)
6239 return false;
6240
6241 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6242 return false;
6243 }
6244 return true;
6245}
Caroline Tice30fec122011-02-18 23:52:21 +00006246
6247// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6248// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6249// optionally be shifted.
6250bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006251EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006252{
6253#if 0
6254 if ConditionPassed() then
6255 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6256 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6257 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6258 address = if index then offset_addr else R[n];
6259 R[t] = ZeroExtend(MemU[address,1],32);
6260 if wback then R[n] = offset_addr;
6261#endif
6262
6263 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006264
Greg Clayton7bc39082011-03-24 23:53:38 +00006265 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006266 {
6267 uint32_t t;
6268 uint32_t n;
6269 uint32_t m;
6270 bool index;
6271 bool add;
6272 bool wback;
6273 ARM_ShifterType shift_t;
6274 uint32_t shift_n;
6275
6276 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6277 switch (encoding)
6278 {
6279 case eEncodingT1:
6280 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6281 t = Bits32 (opcode, 2, 0);
6282 n = Bits32 (opcode, 5, 3);
6283 m = Bits32 (opcode, 8, 6);
6284
6285 // index = TRUE; add = TRUE; wback = FALSE;
6286 index = true;
6287 add = true;
6288 wback = false;
6289
6290 // (shift_t, shift_n) = (SRType_LSL, 0);
6291 shift_t = SRType_LSL;
6292 shift_n = 0;
6293 break;
6294
6295 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006296 // if Rt == '1111' then SEE PLD;
6297 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006298 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6299 t = Bits32 (opcode, 15, 12);
6300 n = Bits32 (opcode, 19, 16);
6301 m = Bits32 (opcode, 3, 0);
6302
6303 // index = TRUE; add = TRUE; wback = FALSE;
6304 index = true;
6305 add = true;
6306 wback = false;
6307
6308 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6309 shift_t = SRType_LSL;
6310 shift_n = Bits32 (opcode, 5, 4);
6311
6312 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6313 if ((t == 13) || BadReg (m))
6314 return false;
6315 break;
6316
6317 case eEncodingA1:
6318 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006319 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006320 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6321 t = Bits32 (opcode, 15, 12);
6322 n = Bits32 (opcode, 19, 16);
6323 m = Bits32 (opcode, 3, 0);
6324
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006325 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006326 index = BitIsSet (opcode, 24);
6327 add = BitIsSet (opcode, 23);
6328 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6329
6330 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6331 uint32_t type = Bits32 (opcode, 6, 5);
6332 uint32_t imm5 = Bits32 (opcode, 11, 7);
6333 shift_n = DecodeImmShift (type, imm5, shift_t);
6334
6335 // if t == 15 || m == 15 then UNPREDICTABLE;
6336 if ((t == 15) || (m == 15))
6337 return false;
6338
6339 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6340 if (wback && ((n == 15) || (n == t)))
6341 return false;
6342 }
6343 break;
6344
6345 default:
6346 return false;
6347 }
6348
6349 addr_t offset_addr;
6350 addr_t address;
6351
6352 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6353 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6354 if (!success)
6355 return false;
6356
6357 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6358
6359 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6360 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6361 if (!success)
6362 return false;
6363
6364 if (add)
6365 offset_addr = Rn + offset;
6366 else
6367 offset_addr = Rn - offset;
6368
6369 // address = if index then offset_addr else R[n];
6370 if (index)
6371 address = offset_addr;
6372 else
6373 address = Rn;
6374
6375 // R[t] = ZeroExtend(MemU[address,1],32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006376 RegisterInfo base_reg;
6377 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice30fec122011-02-18 23:52:21 +00006378
6379 EmulateInstruction::Context context;
6380 context.type = eContextRegisterLoad;
6381 context.SetRegisterPlusOffset (base_reg, address - Rn);
6382
6383 uint64_t data = MemURead (context, address, 1, 0, &success);
6384 if (!success)
6385 return false;
6386
6387 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6388 return false;
6389
6390 // if wback then R[n] = offset_addr;
6391 if (wback)
6392 {
6393 context.type = eContextAdjustBaseRegister;
6394 context.SetAddress (offset_addr);
6395 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6396 return false;
6397 }
6398 }
6399 return true;
6400}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006401
6402// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6403// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6404// post-indexed, or pre-indexed addressing.
6405bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006406EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006407{
6408#if 0
6409 if ConditionPassed() then
6410 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6411 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6412 address = if index then offset_addr else R[n];
6413 data = MemU[address,2];
6414 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006415 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006416 R[t] = ZeroExtend(data, 32);
6417 else // Can only apply before ARMv7
6418 R[t] = bits(32) UNKNOWN;
6419#endif
6420
6421
6422 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006423
Greg Clayton7bc39082011-03-24 23:53:38 +00006424 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006425 {
6426 uint32_t t;
6427 uint32_t n;
6428 uint32_t imm32;
6429 bool index;
6430 bool add;
6431 bool wback;
6432
6433 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6434 switch (encoding)
6435 {
6436 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006437 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006438 t = Bits32 (opcode, 2, 0);
6439 n = Bits32 (opcode, 5, 3);
6440 imm32 = Bits32 (opcode, 10, 6) << 1;
6441
6442 // index = TRUE; add = TRUE; wback = FALSE;
6443 index = true;
6444 add = true;
6445 wback = false;
6446
6447 break;
6448
6449 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006450 // if Rt == '1111' then SEE "Unallocated memory hints";
6451 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006452 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6453 t = Bits32 (opcode, 15, 12);
6454 n = Bits32 (opcode, 19, 16);
6455 imm32 = Bits32 (opcode, 11, 0);
6456
6457 // index = TRUE; add = TRUE; wback = FALSE;
6458 index = true;
6459 add = true;
6460 wback = false;
6461
6462 // if t == 13 then UNPREDICTABLE;
6463 if (t == 13)
6464 return false;
6465 break;
6466
6467 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006468 // if Rn == '1111' then SEE LDRH (literal);
6469 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6470 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6471 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006472 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6473 return false;
6474
6475 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6476 t = Bits32 (opcode, 15, 12);
6477 n = Bits32 (opcode, 19, 16);
6478 imm32 = Bits32 (opcode, 7, 0);
6479
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006480 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006481 index = BitIsSet (opcode, 10);
6482 add = BitIsSet (opcode, 9);
6483 wback = BitIsSet (opcode, 8);
6484
6485 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6486 if (BadReg (t) || (wback && (n == t)))
6487 return false;
6488 break;
6489
6490 default:
6491 return false;
6492 }
6493
6494 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6495 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6496 if (!success)
6497 return false;
6498
6499 addr_t offset_addr;
6500 addr_t address;
6501
6502 if (add)
6503 offset_addr = Rn + imm32;
6504 else
6505 offset_addr = Rn - imm32;
6506
6507 // address = if index then offset_addr else R[n];
6508 if (index)
6509 address = offset_addr;
6510 else
6511 address = Rn;
6512
6513 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006514 RegisterInfo base_reg;
6515 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006516
6517 EmulateInstruction::Context context;
6518 context.type = eContextRegisterLoad;
6519 context.SetRegisterPlusOffset (base_reg, address - Rn);
6520
6521 uint64_t data = MemURead (context, address, 2, 0, &success);
6522 if (!success)
6523 return false;
6524
6525 // if wback then R[n] = offset_addr;
6526 if (wback)
6527 {
6528 context.type = eContextAdjustBaseRegister;
6529 context.SetAddress (offset_addr);
6530 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6531 return false;
6532 }
6533
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006534 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006535 if (UnalignedSupport () || BitIsClear (address, 0))
6536 {
6537 // R[t] = ZeroExtend(data, 32);
6538 context.type = eContextRegisterLoad;
6539 context.SetRegisterPlusOffset (base_reg, address - Rn);
6540 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6541 return false;
6542 }
6543 else // Can only apply before ARMv7
6544 {
6545 // R[t] = bits(32) UNKNOWN;
6546 WriteBits32Unknown (t);
6547 }
6548 }
6549 return true;
6550}
Caroline Ticefe479112011-02-18 18:52:37 +00006551
Caroline Tice952b5382011-02-28 23:15:24 +00006552// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6553// zero-extends it to form a 32-bit word, and writes it to a register.
6554bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006555EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006556{
6557#if 0
6558 if ConditionPassed() then
6559 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6560 base = Align(PC,4);
6561 address = if add then (base + imm32) else (base - imm32);
6562 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006563 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006564 R[t] = ZeroExtend(data, 32);
6565 else // Can only apply before ARMv7
6566 R[t] = bits(32) UNKNOWN;
6567#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006568
Caroline Tice952b5382011-02-28 23:15:24 +00006569 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006570
Greg Clayton7bc39082011-03-24 23:53:38 +00006571 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006572 {
6573 uint32_t t;
6574 uint32_t imm32;
6575 bool add;
6576
6577 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6578 switch (encoding)
6579 {
6580 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006581 // if Rt == '1111' then SEE "Unallocated memory hints";
6582 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006583 t = Bits32 (opcode, 15, 12);
6584 imm32 = Bits32 (opcode, 11, 0);
6585 add = BitIsSet (opcode, 23);
6586
6587 // if t == 13 then UNPREDICTABLE;
6588 if (t == 13)
6589 return false;
6590
6591 break;
6592
6593 case eEncodingA1:
6594 {
6595 uint32_t imm4H = Bits32 (opcode, 11, 8);
6596 uint32_t imm4L = Bits32 (opcode, 3, 0);
6597
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006598 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006599 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006600 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006601 add = BitIsSet (opcode, 23);
6602
6603 // if t == 15 then UNPREDICTABLE;
6604 if (t == 15)
6605 return false;
6606 break;
6607 }
6608
6609 default:
6610 return false;
6611 }
6612
6613 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006614 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006615 if (!success)
6616 return false;
6617
6618 addr_t base = AlignPC (pc_value);
6619 addr_t address;
6620
6621 // address = if add then (base + imm32) else (base - imm32);
6622 if (add)
6623 address = base + imm32;
6624 else
6625 address = base - imm32;
6626
6627 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006628 RegisterInfo base_reg;
6629 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice952b5382011-02-28 23:15:24 +00006630
6631 EmulateInstruction::Context context;
6632 context.type = eContextRegisterLoad;
6633 context.SetRegisterPlusOffset (base_reg, address - base);
6634
6635 uint64_t data = MemURead (context, address, 2, 0, &success);
6636 if (!success)
6637 return false;
6638
6639
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006640 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006641 if (UnalignedSupport () || BitIsClear (address, 0))
6642 {
6643 // R[t] = ZeroExtend(data, 32);
6644 context.type = eContextRegisterLoad;
6645 context.SetRegisterPlusOffset (base_reg, address - base);
6646 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6647 return false;
6648
6649 }
6650 else // Can only apply before ARMv7
6651 {
6652 // R[t] = bits(32) UNKNOWN;
6653 WriteBits32Unknown (t);
6654 }
6655 }
6656 return true;
6657}
6658
Caroline Tice0e6bc952011-03-01 18:00:42 +00006659// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6660// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6661// be shifted left by 0, 1, 2, or 3 bits.
6662bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006663EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006664{
6665#if 0
6666 if ConditionPassed() then
6667 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6668 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6669 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6670 address = if index then offset_addr else R[n];
6671 data = MemU[address,2];
6672 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006673 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006674 R[t] = ZeroExtend(data, 32);
6675 else // Can only apply before ARMv7
6676 R[t] = bits(32) UNKNOWN;
6677#endif
6678
6679 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006680
Greg Clayton7bc39082011-03-24 23:53:38 +00006681 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006682 {
6683 uint32_t t;
6684 uint32_t n;
6685 uint32_t m;
6686 bool index;
6687 bool add;
6688 bool wback;
6689 ARM_ShifterType shift_t;
6690 uint32_t shift_n;
6691
6692 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6693 switch (encoding)
6694 {
6695 case eEncodingT1:
6696 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6697 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6698 t = Bits32 (opcode, 2, 0);
6699 n = Bits32 (opcode, 5, 3);
6700 m = Bits32 (opcode, 8, 6);
6701
6702 // index = TRUE; add = TRUE; wback = FALSE;
6703 index = true;
6704 add = true;
6705 wback = false;
6706
6707 // (shift_t, shift_n) = (SRType_LSL, 0);
6708 shift_t = SRType_LSL;
6709 shift_n = 0;
6710
6711 break;
6712
6713 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006714 // if Rn == '1111' then SEE LDRH (literal);
6715 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006716 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6717 t = Bits32 (opcode, 15, 12);
6718 n = Bits32 (opcode, 19, 16);
6719 m = Bits32 (opcode, 3, 0);
6720
6721 // index = TRUE; add = TRUE; wback = FALSE;
6722 index = true;
6723 add = true;
6724 wback = false;
6725
6726 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6727 shift_t = SRType_LSL;
6728 shift_n = Bits32 (opcode, 5, 4);
6729
6730 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6731 if ((t == 13) || BadReg (m))
6732 return false;
6733 break;
6734
6735 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006736 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006737 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6738 t = Bits32 (opcode, 15, 12);
6739 n = Bits32 (opcode, 19, 16);
6740 m = Bits32 (opcode, 3, 0);
6741
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006742 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006743 index = BitIsSet (opcode, 24);
6744 add = BitIsSet (opcode, 23);
6745 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6746
6747 // (shift_t, shift_n) = (SRType_LSL, 0);
6748 shift_t = SRType_LSL;
6749 shift_n = 0;
6750
6751 // if t == 15 || m == 15 then UNPREDICTABLE;
6752 if ((t == 15) || (m == 15))
6753 return false;
6754
6755 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6756 if (wback && ((n == 15) || (n == t)))
6757 return false;
6758
6759 break;
6760
6761 default:
6762 return false;
6763 }
6764
6765 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6766
6767 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6768 if (!success)
6769 return false;
6770
6771 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6772
6773 addr_t offset_addr;
6774 addr_t address;
6775
6776 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6777 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6778 if (!success)
6779 return false;
6780
6781 if (add)
6782 offset_addr = Rn + offset;
6783 else
6784 offset_addr = Rn - offset;
6785
6786 // address = if index then offset_addr else R[n];
6787 if (index)
6788 address = offset_addr;
6789 else
6790 address = Rn;
6791
6792 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006793 RegisterInfo base_reg;
6794 RegisterInfo offset_reg;
6795 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6796 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice0e6bc952011-03-01 18:00:42 +00006797
6798 EmulateInstruction::Context context;
6799 context.type = eContextRegisterLoad;
6800 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6801 uint64_t data = MemURead (context, address, 2, 0, &success);
6802 if (!success)
6803 return false;
6804
6805 // if wback then R[n] = offset_addr;
6806 if (wback)
6807 {
6808 context.type = eContextAdjustBaseRegister;
6809 context.SetAddress (offset_addr);
6810 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6811 return false;
6812 }
6813
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006814 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006815 if (UnalignedSupport() || BitIsClear (address, 0))
6816 {
6817 // R[t] = ZeroExtend(data, 32);
6818 context.type = eContextRegisterLoad;
6819 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6820 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6821 return false;
6822 }
6823 else // Can only apply before ARMv7
6824 {
6825 // R[t] = bits(32) UNKNOWN;
6826 WriteBits32Unknown (t);
6827 }
6828 }
6829 return true;
6830}
6831
Caroline Ticea5e28af2011-03-01 21:53:03 +00006832// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6833// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6834// or pre-indexed addressing.
6835bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006836EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006837{
6838#if 0
6839 if ConditionPassed() then
6840 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6841 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6842 address = if index then offset_addr else R[n];
6843 R[t] = SignExtend(MemU[address,1], 32);
6844 if wback then R[n] = offset_addr;
6845#endif
6846
6847 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006848
Greg Clayton7bc39082011-03-24 23:53:38 +00006849 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006850 {
6851 uint32_t t;
6852 uint32_t n;
6853 uint32_t imm32;
6854 bool index;
6855 bool add;
6856 bool wback;
6857
6858 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6859 switch (encoding)
6860 {
6861 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006862 // if Rt == '1111' then SEE PLI;
6863 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006864 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6865 t = Bits32 (opcode, 15, 12);
6866 n = Bits32 (opcode, 19, 16);
6867 imm32 = Bits32 (opcode, 11, 0);
6868
6869 // index = TRUE; add = TRUE; wback = FALSE;
6870 index = true;
6871 add = true;
6872 wback = false;
6873
6874 // if t == 13 then UNPREDICTABLE;
6875 if (t == 13)
6876 return false;
6877
6878 break;
6879
6880 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006881 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6882 // if Rn == '1111' then SEE LDRSB (literal);
6883 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6884 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006885 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6886 return false;
6887
6888 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6889 t = Bits32 (opcode, 15, 12);
6890 n = Bits32 (opcode, 19, 16);
6891 imm32 = Bits32 (opcode, 7, 0);
6892
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006893 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006894 index = BitIsSet (opcode, 10);
6895 add = BitIsSet (opcode, 9);
6896 wback = BitIsSet (opcode, 8);
6897
6898 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006899 if (((t == 13) || ((t == 15)
6900 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6901 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006902 return false;
6903
6904 break;
6905
6906 case eEncodingA1:
6907 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006908 // if Rn == '1111' then SEE LDRSB (literal);
6909 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006910 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6911 t = Bits32 (opcode, 15, 12);
6912 n = Bits32 (opcode, 19, 16);
6913
6914 uint32_t imm4H = Bits32 (opcode, 11, 8);
6915 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006916 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006917
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006918 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006919 index = BitIsSet (opcode, 24);
6920 add = BitIsSet (opcode, 23);
6921 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6922
6923 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6924 if ((t == 15) || (wback && (n == t)))
6925 return false;
6926
6927 break;
6928 }
6929
6930 default:
6931 return false;
6932 }
6933
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006934 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006935 if (!success)
6936 return false;
6937
6938 addr_t offset_addr;
6939 addr_t address;
6940
6941 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6942 if (add)
6943 offset_addr = Rn + imm32;
6944 else
6945 offset_addr = Rn - imm32;
6946
6947 // address = if index then offset_addr else R[n];
6948 if (index)
6949 address = offset_addr;
6950 else
6951 address = Rn;
6952
6953 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006954 RegisterInfo base_reg;
6955 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006956
6957 EmulateInstruction::Context context;
6958 context.type = eContextRegisterLoad;
6959 context.SetRegisterPlusOffset (base_reg, address - Rn);
6960
6961 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6962 if (!success)
6963 return false;
6964
6965 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6966 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6967 return false;
6968
6969 // if wback then R[n] = offset_addr;
6970 if (wback)
6971 {
6972 context.type = eContextAdjustBaseRegister;
6973 context.SetAddress (offset_addr);
6974 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6975 return false;
6976 }
6977 }
6978
6979 return true;
6980}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006981
Caroline Tice5f593912011-03-01 22:25:17 +00006982// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6983// sign-extends it to form a 32-bit word, and writes tit to a register.
6984bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006985EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006986{
6987#if 0
6988 if ConditionPassed() then
6989 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6990 base = Align(PC,4);
6991 address = if add then (base + imm32) else (base - imm32);
6992 R[t] = SignExtend(MemU[address,1], 32);
6993#endif
6994
6995 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006996
Greg Clayton7bc39082011-03-24 23:53:38 +00006997 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006998 {
6999 uint32_t t;
7000 uint32_t imm32;
7001 bool add;
7002
7003 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7004 switch (encoding)
7005 {
7006 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007007 // if Rt == '1111' then SEE PLI;
7008 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007009 t = Bits32 (opcode, 15, 12);
7010 imm32 = Bits32 (opcode, 11, 0);
7011 add = BitIsSet (opcode, 23);
7012
7013 // if t == 13 then UNPREDICTABLE;
7014 if (t == 13)
7015 return false;
7016
7017 break;
7018
7019 case eEncodingA1:
7020 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007021 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007022 t = Bits32 (opcode, 15, 12);
7023 uint32_t imm4H = Bits32 (opcode, 11, 8);
7024 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007025 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00007026 add = BitIsSet (opcode, 23);
7027
7028 // if t == 15 then UNPREDICTABLE;
7029 if (t == 15)
7030 return false;
7031
7032 break;
7033 }
7034
7035 default:
7036 return false;
7037 }
7038
7039 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007040 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007041 if (!success)
7042 return false;
7043 uint64_t base = AlignPC (pc_value);
7044
7045 // address = if add then (base + imm32) else (base - imm32);
7046 addr_t address;
7047 if (add)
7048 address = base + imm32;
7049 else
7050 address = base - imm32;
7051
7052 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007053 RegisterInfo base_reg;
7054 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice5f593912011-03-01 22:25:17 +00007055
7056 EmulateInstruction::Context context;
7057 context.type = eContextRegisterLoad;
7058 context.SetRegisterPlusOffset (base_reg, address - base);
7059
7060 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7061 if (!success)
7062 return false;
7063
7064 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7065 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7066 return false;
7067 }
7068 return true;
7069}
7070
Caroline Tice672f3112011-03-01 23:55:59 +00007071// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7072// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7073// shifted left by 0, 1, 2, or 3 bits.
7074bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007075EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007076{
7077#if 0
7078 if ConditionPassed() then
7079 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7080 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7081 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7082 address = if index then offset_addr else R[n];
7083 R[t] = SignExtend(MemU[address,1], 32);
7084 if wback then R[n] = offset_addr;
7085#endif
7086
7087 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007088
Greg Clayton7bc39082011-03-24 23:53:38 +00007089 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007090 {
7091 uint32_t t;
7092 uint32_t n;
7093 uint32_t m;
7094 bool index;
7095 bool add;
7096 bool wback;
7097 ARM_ShifterType shift_t;
7098 uint32_t shift_n;
7099
7100 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7101 switch (encoding)
7102 {
7103 case eEncodingT1:
7104 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7105 t = Bits32 (opcode, 2, 0);
7106 n = Bits32 (opcode, 5, 3);
7107 m = Bits32 (opcode, 8, 6);
7108
7109 // index = TRUE; add = TRUE; wback = FALSE;
7110 index = true;
7111 add = true;
7112 wback = false;
7113
7114 // (shift_t, shift_n) = (SRType_LSL, 0);
7115 shift_t = SRType_LSL;
7116 shift_n = 0;
7117
7118 break;
7119
7120 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007121 // if Rt == '1111' then SEE PLI;
7122 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007123 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7124 t = Bits32 (opcode, 15, 12);
7125 n = Bits32 (opcode, 19, 16);
7126 m = Bits32 (opcode, 3, 0);
7127
7128 // index = TRUE; add = TRUE; wback = FALSE;
7129 index = true;
7130 add = true;
7131 wback = false;
7132
7133 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7134 shift_t = SRType_LSL;
7135 shift_n = Bits32 (opcode, 5, 4);
7136
7137 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7138 if ((t == 13) || BadReg (m))
7139 return false;
7140 break;
7141
7142 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007143 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007144 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7145 t = Bits32 (opcode, 15, 12);
7146 n = Bits32 (opcode, 19, 16);
7147 m = Bits32 (opcode, 3, 0);
7148
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007149 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007150 index = BitIsSet (opcode, 24);
7151 add = BitIsSet (opcode, 23);
7152 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7153
7154 // (shift_t, shift_n) = (SRType_LSL, 0);
7155 shift_t = SRType_LSL;
7156 shift_n = 0;
7157
7158 // if t == 15 || m == 15 then UNPREDICTABLE;
7159 if ((t == 15) || (m == 15))
7160 return false;
7161
7162 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7163 if (wback && ((n == 15) || (n == t)))
7164 return false;
7165 break;
7166
7167 default:
7168 return false;
7169 }
7170
7171 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7172 if (!success)
7173 return false;
7174
7175 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7176 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7177
7178 addr_t offset_addr;
7179 addr_t address;
7180
7181 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7182 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7183 if (!success)
7184 return false;
7185
7186 if (add)
7187 offset_addr = Rn + offset;
7188 else
7189 offset_addr = Rn - offset;
7190
7191 // address = if index then offset_addr else R[n];
7192 if (index)
7193 address = offset_addr;
7194 else
7195 address = Rn;
7196
7197 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007198 RegisterInfo base_reg;
7199 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7200 RegisterInfo offset_reg;
7201 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice672f3112011-03-01 23:55:59 +00007202
7203 EmulateInstruction::Context context;
7204 context.type = eContextRegisterLoad;
7205 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7206
7207 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7208 if (!success)
7209 return false;
7210
7211 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7212 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7213 return false;
7214
7215 // if wback then R[n] = offset_addr;
7216 if (wback)
7217 {
7218 context.type = eContextAdjustBaseRegister;
7219 context.SetAddress (offset_addr);
7220 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7221 return false;
7222 }
7223 }
7224 return true;
7225}
7226
Caroline Tice78fb5632011-03-02 00:39:42 +00007227// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7228// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7229// pre-indexed addressing.
7230bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007231EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007232{
7233#if 0
7234 if ConditionPassed() then
7235 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7236 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7237 address = if index then offset_addr else R[n];
7238 data = MemU[address,2];
7239 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007240 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007241 R[t] = SignExtend(data, 32);
7242 else // Can only apply before ARMv7
7243 R[t] = bits(32) UNKNOWN;
7244#endif
7245
7246 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007247
Greg Clayton7bc39082011-03-24 23:53:38 +00007248 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007249 {
7250 uint32_t t;
7251 uint32_t n;
7252 uint32_t imm32;
7253 bool index;
7254 bool add;
7255 bool wback;
7256
7257 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7258 switch (encoding)
7259 {
7260 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007261 // if Rn == '1111' then SEE LDRSH (literal);
7262 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007263 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7264 t = Bits32 (opcode, 15, 12);
7265 n = Bits32 (opcode, 19, 16);
7266 imm32 = Bits32 (opcode, 11, 0);
7267
7268 // index = TRUE; add = TRUE; wback = FALSE;
7269 index = true;
7270 add = true;
7271 wback = false;
7272
7273 // if t == 13 then UNPREDICTABLE;
7274 if (t == 13)
7275 return false;
7276
7277 break;
7278
7279 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007280 // if Rn == '1111' then SEE LDRSH (literal);
7281 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7282 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7283 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007284 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7285 return false;
7286
7287 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7288 t = Bits32 (opcode, 15, 12);
7289 n = Bits32 (opcode, 19, 16);
7290 imm32 = Bits32 (opcode, 7, 0);
7291
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007292 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007293 index = BitIsSet (opcode, 10);
7294 add = BitIsSet (opcode, 9);
7295 wback = BitIsSet (opcode, 8);
7296
7297 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7298 if (BadReg (t) || (wback && (n == t)))
7299 return false;
7300
7301 break;
7302
7303 case eEncodingA1:
7304 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007305 // if Rn == '1111' then SEE LDRSH (literal);
7306 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007307 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7308 t = Bits32 (opcode, 15, 12);
7309 n = Bits32 (opcode, 19, 16);
7310 uint32_t imm4H = Bits32 (opcode, 11,8);
7311 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007312 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007313
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007314 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007315 index = BitIsSet (opcode, 24);
7316 add = BitIsSet (opcode, 23);
7317 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7318
7319 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7320 if ((t == 15) || (wback && (n == t)))
7321 return false;
7322
7323 break;
7324 }
7325
7326 default:
7327 return false;
7328 }
7329
7330 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7331 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7332 if (!success)
7333 return false;
7334
7335 addr_t offset_addr;
7336 if (add)
7337 offset_addr = Rn + imm32;
7338 else
7339 offset_addr = Rn - imm32;
7340
7341 // address = if index then offset_addr else R[n];
7342 addr_t address;
7343 if (index)
7344 address = offset_addr;
7345 else
7346 address = Rn;
7347
7348 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007349 RegisterInfo base_reg;
7350 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice78fb5632011-03-02 00:39:42 +00007351
7352 EmulateInstruction::Context context;
7353 context.type = eContextRegisterLoad;
7354 context.SetRegisterPlusOffset (base_reg, address - Rn);
7355
7356 uint64_t data = MemURead (context, address, 2, 0, &success);
7357 if (!success)
7358 return false;
7359
7360 // if wback then R[n] = offset_addr;
7361 if (wback)
7362 {
7363 context.type = eContextAdjustBaseRegister;
7364 context.SetAddress (offset_addr);
7365 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7366 return false;
7367 }
7368
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007369 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007370 if (UnalignedSupport() || BitIsClear (address, 0))
7371 {
7372 // R[t] = SignExtend(data, 32);
7373 int64_t signed_data = llvm::SignExtend64<16>(data);
7374 context.type = eContextRegisterLoad;
7375 context.SetRegisterPlusOffset (base_reg, address - Rn);
7376 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7377 return false;
7378 }
7379 else // Can only apply before ARMv7
7380 {
7381 // R[t] = bits(32) UNKNOWN;
7382 WriteBits32Unknown (t);
7383 }
7384 }
7385 return true;
7386}
7387
Caroline Ticed2fac092011-03-02 19:45:34 +00007388// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7389// sign-extends it to from a 32-bit word, and writes it to a register.
7390bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007391EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007392{
7393#if 0
7394 if ConditionPassed() then
7395 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7396 base = Align(PC,4);
7397 address = if add then (base + imm32) else (base - imm32);
7398 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007399 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007400 R[t] = SignExtend(data, 32);
7401 else // Can only apply before ARMv7
7402 R[t] = bits(32) UNKNOWN;
7403#endif
7404
7405 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007406
Greg Clayton7bc39082011-03-24 23:53:38 +00007407 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007408 {
7409 uint32_t t;
7410 uint32_t imm32;
7411 bool add;
7412
7413 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7414 switch (encoding)
7415 {
7416 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007417 // if Rt == '1111' then SEE "Unallocated memory hints";
7418 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007419 t = Bits32 (opcode, 15, 12);
7420 imm32 = Bits32 (opcode, 11, 0);
7421 add = BitIsSet (opcode, 23);
7422
7423 // if t == 13 then UNPREDICTABLE;
7424 if (t == 13)
7425 return false;
7426
7427 break;
7428
7429 case eEncodingA1:
7430 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007431 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007432 t = Bits32 (opcode, 15, 12);
7433 uint32_t imm4H = Bits32 (opcode, 11, 8);
7434 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007435 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007436 add = BitIsSet (opcode, 23);
7437
7438 // if t == 15 then UNPREDICTABLE;
7439 if (t == 15)
7440 return false;
7441
7442 break;
7443 }
7444 default:
7445 return false;
7446 }
7447
7448 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007449 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007450 if (!success)
7451 return false;
7452
7453 uint64_t base = AlignPC (pc_value);
7454
7455 addr_t address;
7456 // address = if add then (base + imm32) else (base - imm32);
7457 if (add)
7458 address = base + imm32;
7459 else
7460 address = base - imm32;
7461
7462 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007463 RegisterInfo base_reg;
7464 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Ticed2fac092011-03-02 19:45:34 +00007465
7466 EmulateInstruction::Context context;
7467 context.type = eContextRegisterLoad;
7468 context.SetRegisterPlusOffset (base_reg, imm32);
7469
7470 uint64_t data = MemURead (context, address, 2, 0, &success);
7471 if (!success)
7472 return false;
7473
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007474 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007475 if (UnalignedSupport() || BitIsClear (address, 0))
7476 {
7477 // R[t] = SignExtend(data, 32);
7478 int64_t signed_data = llvm::SignExtend64<16>(data);
7479 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7480 return false;
7481 }
7482 else // Can only apply before ARMv7
7483 {
7484 // R[t] = bits(32) UNKNOWN;
7485 WriteBits32Unknown (t);
7486 }
7487 }
7488 return true;
7489}
7490
Caroline Tice291a3e92011-03-02 21:13:44 +00007491// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7492// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7493// shifted left by 0, 1, 2, or 3 bits.
7494bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007495EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007496{
7497#if 0
7498 if ConditionPassed() then
7499 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7500 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7501 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7502 address = if index then offset_addr else R[n];
7503 data = MemU[address,2];
7504 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007505 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007506 R[t] = SignExtend(data, 32);
7507 else // Can only apply before ARMv7
7508 R[t] = bits(32) UNKNOWN;
7509#endif
7510
7511 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007512
Greg Clayton7bc39082011-03-24 23:53:38 +00007513 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007514 {
7515 uint32_t t;
7516 uint32_t n;
7517 uint32_t m;
7518 bool index;
7519 bool add;
7520 bool wback;
7521 ARM_ShifterType shift_t;
7522 uint32_t shift_n;
7523
7524 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7525 switch (encoding)
7526 {
7527 case eEncodingT1:
7528 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7529 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7530 t = Bits32 (opcode, 2, 0);
7531 n = Bits32 (opcode, 5, 3);
7532 m = Bits32 (opcode, 8, 6);
7533
7534 // index = TRUE; add = TRUE; wback = FALSE;
7535 index = true;
7536 add = true;
7537 wback = false;
7538
7539 // (shift_t, shift_n) = (SRType_LSL, 0);
7540 shift_t = SRType_LSL;
7541 shift_n = 0;
7542
7543 break;
7544
7545 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007546 // if Rn == '1111' then SEE LDRSH (literal);
7547 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007548 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7549 t = Bits32 (opcode, 15, 12);
7550 n = Bits32 (opcode, 19, 16);
7551 m = Bits32 (opcode, 3, 0);
7552
7553 // index = TRUE; add = TRUE; wback = FALSE;
7554 index = true;
7555 add = true;
7556 wback = false;
7557
7558 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7559 shift_t = SRType_LSL;
7560 shift_n = Bits32 (opcode, 5, 4);
7561
7562 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7563 if ((t == 13) || BadReg (m))
7564 return false;
7565
7566 break;
7567
7568 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007569 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007570 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7571 t = Bits32 (opcode, 15, 12);
7572 n = Bits32 (opcode, 19, 16);
7573 m = Bits32 (opcode, 3, 0);
7574
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007575 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007576 index = BitIsSet (opcode, 24);
7577 add = BitIsSet (opcode, 23);
7578 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7579
7580 // (shift_t, shift_n) = (SRType_LSL, 0);
7581 shift_t = SRType_LSL;
7582 shift_n = 0;
7583
7584 // if t == 15 || m == 15 then UNPREDICTABLE;
7585 if ((t == 15) || (m == 15))
7586 return false;
7587
7588 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7589 if (wback && ((n == 15) || (n == t)))
7590 return false;
7591
7592 break;
7593
7594 default:
7595 break;
7596 }
7597
7598 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7599 if (!success)
7600 return false;
7601
7602 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7603 if (!success)
7604 return false;
7605
7606 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7607 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7608
7609 addr_t offset_addr;
7610 addr_t address;
7611
7612 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7613 if (add)
7614 offset_addr = Rn + offset;
7615 else
7616 offset_addr = Rn - offset;
7617
7618 // address = if index then offset_addr else R[n];
7619 if (index)
7620 address = offset_addr;
7621 else
7622 address = Rn;
7623
7624 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007625 RegisterInfo base_reg;
7626 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007627
Greg Claytonc07d4512011-04-26 23:48:45 +00007628 RegisterInfo offset_reg;
7629 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007630
7631 EmulateInstruction::Context context;
7632 context.type = eContextRegisterLoad;
7633 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7634
7635 uint64_t data = MemURead (context, address, 2, 0, &success);
7636 if (!success)
7637 return false;
7638
7639 // if wback then R[n] = offset_addr;
7640 if (wback)
7641 {
7642 context.type = eContextAdjustBaseRegister;
7643 context.SetAddress (offset_addr);
7644 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7645 return false;
7646 }
7647
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007648 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007649 if (UnalignedSupport() || BitIsClear (address, 0))
7650 {
7651 // R[t] = SignExtend(data, 32);
7652 context.type = eContextRegisterLoad;
7653 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7654
7655 int64_t signed_data = llvm::SignExtend64<16>(data);
7656 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7657 return false;
7658 }
7659 else // Can only apply before ARMv7
7660 {
7661 // R[t] = bits(32) UNKNOWN;
7662 WriteBits32Unknown (t);
7663 }
7664 }
7665 return true;
7666}
Caroline Tice6bf65162011-03-03 17:42:58 +00007667
7668// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7669// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7670bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007671EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007672{
7673#if 0
7674 if ConditionPassed() then
7675 EncodingSpecificOperations();
7676 rotated = ROR(R[m], rotation);
7677 R[d] = SignExtend(rotated<7:0>, 32);
7678#endif
7679
7680 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007681
Greg Clayton7bc39082011-03-24 23:53:38 +00007682 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007683 {
7684 uint32_t d;
7685 uint32_t m;
7686 uint32_t rotation;
7687
7688 // EncodingSpecificOperations();
7689 switch (encoding)
7690 {
7691 case eEncodingT1:
7692 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7693 d = Bits32 (opcode, 2, 0);
7694 m = Bits32 (opcode, 5, 3);
7695 rotation = 0;
7696
7697 break;
7698
7699 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007700 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007701 d = Bits32 (opcode, 11, 8);
7702 m = Bits32 (opcode, 3, 0);
7703 rotation = Bits32 (opcode, 5, 4) << 3;
7704
7705 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7706 if (BadReg (d) || BadReg (m))
7707 return false;
7708
7709 break;
7710
7711 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007712 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007713 d = Bits32 (opcode, 15, 12);
7714 m = Bits32 (opcode, 3, 0);
7715 rotation = Bits32 (opcode, 11, 10) << 3;
7716
7717 // if d == 15 || m == 15 then UNPREDICTABLE;
7718 if ((d == 15) || (m == 15))
7719 return false;
7720
7721 break;
7722
7723 default:
7724 return false;
7725 }
7726
Caroline Tice868198b2011-03-03 18:04:49 +00007727 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7728 if (!success)
7729 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007730
7731 // rotated = ROR(R[m], rotation);
7732 uint64_t rotated = ROR (Rm, rotation);
7733
7734 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007735 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007736
Greg Claytonc07d4512011-04-26 23:48:45 +00007737 RegisterInfo source_reg;
7738 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice6bf65162011-03-03 17:42:58 +00007739
7740 EmulateInstruction::Context context;
7741 context.type = eContextRegisterLoad;
7742 context.SetRegister (source_reg);
7743
Caroline Tice8ce96d92011-03-03 18:27:17 +00007744 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007745 return false;
7746 }
7747 return true;
7748}
Caroline Tice291a3e92011-03-02 21:13:44 +00007749
Caroline Tice868198b2011-03-03 18:04:49 +00007750// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7751// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7752bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007753EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007754{
7755#if 0
7756 if ConditionPassed() then
7757 EncodingSpecificOperations();
7758 rotated = ROR(R[m], rotation);
7759 R[d] = SignExtend(rotated<15:0>, 32);
7760#endif
7761
7762 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007763
Greg Clayton7bc39082011-03-24 23:53:38 +00007764 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007765 {
7766 uint32_t d;
7767 uint32_t m;
7768 uint32_t rotation;
7769
7770 // EncodingSpecificOperations();
7771 switch (encoding)
7772 {
7773 case eEncodingT1:
7774 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7775 d = Bits32 (opcode, 2, 0);
7776 m = Bits32 (opcode, 5, 3);
7777 rotation = 0;
7778
7779 break;
7780
7781 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007782 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007783 d = Bits32 (opcode, 11, 8);
7784 m = Bits32 (opcode, 3, 0);
7785 rotation = Bits32 (opcode, 5, 4) << 3;
7786
7787 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7788 if (BadReg (d) || BadReg (m))
7789 return false;
7790
7791 break;
7792
7793 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007794 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007795 d = Bits32 (opcode, 15, 12);
7796 m = Bits32 (opcode, 3, 0);
7797 rotation = Bits32 (opcode, 11, 10) << 3;
7798
7799 // if d == 15 || m == 15 then UNPREDICTABLE;
7800 if ((d == 15) || (m == 15))
7801 return false;
7802
7803 break;
7804
7805 default:
7806 return false;
7807 }
7808
7809 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7810 if (!success)
7811 return false;
7812
7813 // rotated = ROR(R[m], rotation);
7814 uint64_t rotated = ROR (Rm, rotation);
7815
7816 // R[d] = SignExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007817 RegisterInfo source_reg;
7818 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice868198b2011-03-03 18:04:49 +00007819
7820 EmulateInstruction::Context context;
7821 context.type = eContextRegisterLoad;
7822 context.SetRegister (source_reg);
7823
Caroline Tice8ce96d92011-03-03 18:27:17 +00007824 int64_t data = llvm::SignExtend64<16> (rotated);
7825 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007826 return false;
7827 }
7828
7829 return true;
7830}
7831
Caroline Tice8ce96d92011-03-03 18:27:17 +00007832// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7833// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7834bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007835EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007836{
7837#if 0
7838 if ConditionPassed() then
7839 EncodingSpecificOperations();
7840 rotated = ROR(R[m], rotation);
7841 R[d] = ZeroExtend(rotated<7:0>, 32);
7842#endif
7843
7844 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007845
Greg Clayton7bc39082011-03-24 23:53:38 +00007846 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007847 {
7848 uint32_t d;
7849 uint32_t m;
7850 uint32_t rotation;
7851
7852 // EncodingSpecificOperations();
7853 switch (encoding)
7854 {
7855 case eEncodingT1:
7856 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7857 d = Bits32 (opcode, 2, 0);
7858 m = Bits32 (opcode, 5, 3);
7859 rotation = 0;
7860
7861 break;
7862
7863 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007864 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007865 d = Bits32 (opcode, 11, 8);
7866 m = Bits32 (opcode, 3, 0);
7867 rotation = Bits32 (opcode, 5, 4) << 3;
7868
7869 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7870 if (BadReg (d) || BadReg (m))
7871 return false;
7872
7873 break;
7874
7875 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007876 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007877 d = Bits32 (opcode, 15, 12);
7878 m = Bits32 (opcode, 3, 0);
7879 rotation = Bits32 (opcode, 11, 10) << 3;
7880
7881 // if d == 15 || m == 15 then UNPREDICTABLE;
7882 if ((d == 15) || (m == 15))
7883 return false;
7884
7885 break;
7886
7887 default:
7888 return false;
7889 }
7890
7891 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7892 if (!success)
7893 return false;
7894
7895 // rotated = ROR(R[m], rotation);
7896 uint64_t rotated = ROR (Rm, rotation);
7897
7898 // R[d] = ZeroExtend(rotated<7:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007899 RegisterInfo source_reg;
7900 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007901
7902 EmulateInstruction::Context context;
7903 context.type = eContextRegisterLoad;
7904 context.SetRegister (source_reg);
7905
7906 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7907 return false;
7908 }
7909 return true;
7910}
7911
Caroline Tice11555f22011-03-03 18:48:58 +00007912// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7913// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7914bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007915EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007916{
7917#if 0
7918 if ConditionPassed() then
7919 EncodingSpecificOperations();
7920 rotated = ROR(R[m], rotation);
7921 R[d] = ZeroExtend(rotated<15:0>, 32);
7922#endif
7923
7924 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007925
Greg Clayton7bc39082011-03-24 23:53:38 +00007926 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007927 {
7928 uint32_t d;
7929 uint32_t m;
7930 uint32_t rotation;
7931
7932 switch (encoding)
7933 {
7934 case eEncodingT1:
7935 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7936 d = Bits32 (opcode, 2, 0);
7937 m = Bits32 (opcode, 5, 3);
7938 rotation = 0;
7939
7940 break;
7941
7942 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007943 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007944 d = Bits32 (opcode, 11, 8);
7945 m = Bits32 (opcode, 3, 0);
7946 rotation = Bits32 (opcode, 5, 4) << 3;
7947
7948 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7949 if (BadReg (d) || BadReg (m))
7950 return false;
7951
7952 break;
7953
7954 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007955 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007956 d = Bits32 (opcode, 15, 12);
7957 m = Bits32 (opcode, 3, 0);
7958 rotation = Bits32 (opcode, 11, 10) << 3;
7959
7960 // if d == 15 || m == 15 then UNPREDICTABLE;
7961 if ((d == 15) || (m == 15))
7962 return false;
7963
7964 break;
7965
7966 default:
7967 return false;
7968 }
7969
7970 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7971 if (!success)
7972 return false;
7973
7974 // rotated = ROR(R[m], rotation);
7975 uint64_t rotated = ROR (Rm, rotation);
7976
7977 // R[d] = ZeroExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007978 RegisterInfo source_reg;
7979 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice11555f22011-03-03 18:48:58 +00007980
7981 EmulateInstruction::Context context;
7982 context.type = eContextRegisterLoad;
7983 context.SetRegister (source_reg);
7984
7985 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7986 return false;
7987 }
7988 return true;
7989}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007990
7991// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7992// word respectively.
7993bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007994EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007995{
7996#if 0
7997 if ConditionPassed() then
7998 EncodingSpecificOperations();
7999 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8000 UNPREDICTABLE;
8001 else
8002 address = if increment then R[n] else R[n]-8;
8003 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008004 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008005 BranchWritePC(MemA[address,4]);
8006 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8007#endif
8008
8009 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008010
Greg Clayton7bc39082011-03-24 23:53:38 +00008011 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00008012 {
8013 uint32_t n;
8014 bool wback;
8015 bool increment;
8016 bool wordhigher;
8017
8018 // EncodingSpecificOperations();
8019 switch (encoding)
8020 {
8021 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008022 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008023 n = Bits32 (opcode, 19, 16);
8024 wback = BitIsSet (opcode, 21);
8025 increment = false;
8026 wordhigher = false;
8027
8028 // if n == 15 then UNPREDICTABLE;
8029 if (n == 15)
8030 return false;
8031
8032 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8033 if (InITBlock() && !LastInITBlock())
8034 return false;
8035
8036 break;
8037
8038 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008039 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008040 n = Bits32 (opcode, 19, 16);
8041 wback = BitIsSet (opcode, 21);
8042 increment = true;
8043 wordhigher = false;
8044
8045 // if n == 15 then UNPREDICTABLE;
8046 if (n == 15)
8047 return false;
8048
8049 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8050 if (InITBlock() && !LastInITBlock())
8051 return false;
8052
8053 break;
8054
8055 case eEncodingA1:
8056 // n = UInt(Rn);
8057 n = Bits32 (opcode, 19, 16);
8058
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008059 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008060 wback = BitIsSet (opcode, 21);
8061 increment = BitIsSet (opcode, 23);
8062 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8063
8064 // if n == 15 then UNPREDICTABLE;
8065 if (n == 15)
8066 return false;
8067
8068 break;
8069
8070 default:
8071 return false;
8072 }
8073
8074 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8075 if (!CurrentModeIsPrivileged ())
8076 // UNPREDICTABLE;
8077 return false;
8078 else
8079 {
8080 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8081 if (!success)
8082 return false;
8083
8084 addr_t address;
8085 // address = if increment then R[n] else R[n]-8;
8086 if (increment)
8087 address = Rn;
8088 else
8089 address = Rn - 8;
8090
8091 // if wordhigher then address = address+4;
8092 if (wordhigher)
8093 address = address + 4;
8094
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008095 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Greg Claytonc07d4512011-04-26 23:48:45 +00008096 RegisterInfo base_reg;
8097 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008098
8099 EmulateInstruction::Context context;
8100 context.type = eContextReturnFromException;
8101 context.SetRegisterPlusOffset (base_reg, address - Rn);
8102
8103 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8104 if (!success)
8105 return false;
8106
8107 CPSRWriteByInstr (data, 15, true);
8108
8109 // BranchWritePC(MemA[address,4]);
8110 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8111 if (!success)
8112 return false;
8113
8114 BranchWritePC (context, data2);
8115
8116 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8117 if (wback)
8118 {
8119 context.type = eContextAdjustBaseRegister;
8120 if (increment)
8121 {
8122 context.SetOffset (8);
8123 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8124 return false;
8125 }
8126 else
8127 {
8128 context.SetOffset (-8);
8129 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8130 return false;
8131 }
8132 } // if wback
8133 }
8134 } // if ConditionPassed()
8135 return true;
8136}
Caroline Tice11555f22011-03-03 18:48:58 +00008137
Johnny Chen2115b412011-02-21 23:42:44 +00008138// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8139// and writes the result to the destination register. It can optionally update the condition flags based on
8140// the result.
8141bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008142EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008143{
8144#if 0
8145 // ARM pseudo code...
8146 if ConditionPassed() then
8147 EncodingSpecificOperations();
8148 result = R[n] EOR imm32;
8149 if d == 15 then // Can only occur for ARM encoding
8150 ALUWritePC(result); // setflags is always FALSE here
8151 else
8152 R[d] = result;
8153 if setflags then
8154 APSR.N = result<31>;
8155 APSR.Z = IsZeroBit(result);
8156 APSR.C = carry;
8157 // APSR.V unchanged
8158#endif
8159
8160 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008161
Greg Clayton7bc39082011-03-24 23:53:38 +00008162 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008163 {
8164 uint32_t Rd, Rn;
8165 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8166 bool setflags;
8167 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8168 switch (encoding)
8169 {
8170 case eEncodingT1:
8171 Rd = Bits32(opcode, 11, 8);
8172 Rn = Bits32(opcode, 19, 16);
8173 setflags = BitIsSet(opcode, 20);
8174 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8175 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8176 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008177 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008178 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8179 return false;
8180 break;
8181 case eEncodingA1:
8182 Rd = Bits32(opcode, 15, 12);
8183 Rn = Bits32(opcode, 19, 16);
8184 setflags = BitIsSet(opcode, 20);
8185 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008186
Johnny Chen2115b412011-02-21 23:42:44 +00008187 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008188 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008189 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008190 break;
8191 default:
8192 return false;
8193 }
8194
8195 // Read the first operand.
8196 uint32_t val1 = ReadCoreReg(Rn, &success);
8197 if (!success)
8198 return false;
8199
8200 uint32_t result = val1 ^ imm32;
8201
8202 EmulateInstruction::Context context;
8203 context.type = EmulateInstruction::eContextImmediate;
8204 context.SetNoArgs ();
8205
8206 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8207 return false;
8208 }
8209 return true;
8210}
8211
8212// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8213// optionally-shifted register value, and writes the result to the destination register.
8214// It can optionally update the condition flags based on the result.
8215bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008216EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008217{
8218#if 0
8219 // ARM pseudo code...
8220 if ConditionPassed() then
8221 EncodingSpecificOperations();
8222 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8223 result = R[n] EOR shifted;
8224 if d == 15 then // Can only occur for ARM encoding
8225 ALUWritePC(result); // setflags is always FALSE here
8226 else
8227 R[d] = result;
8228 if setflags then
8229 APSR.N = result<31>;
8230 APSR.Z = IsZeroBit(result);
8231 APSR.C = carry;
8232 // APSR.V unchanged
8233#endif
8234
8235 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008236
Greg Clayton7bc39082011-03-24 23:53:38 +00008237 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008238 {
8239 uint32_t Rd, Rn, Rm;
8240 ARM_ShifterType shift_t;
8241 uint32_t shift_n; // the shift applied to the value read from Rm
8242 bool setflags;
8243 uint32_t carry;
8244 switch (encoding)
8245 {
8246 case eEncodingT1:
8247 Rd = Rn = Bits32(opcode, 2, 0);
8248 Rm = Bits32(opcode, 5, 3);
8249 setflags = !InITBlock();
8250 shift_t = SRType_LSL;
8251 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008252 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008253 case eEncodingT2:
8254 Rd = Bits32(opcode, 11, 8);
8255 Rn = Bits32(opcode, 19, 16);
8256 Rm = Bits32(opcode, 3, 0);
8257 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008258 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8259 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008260 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008261 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008262 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8263 return false;
8264 break;
8265 case eEncodingA1:
8266 Rd = Bits32(opcode, 15, 12);
8267 Rn = Bits32(opcode, 19, 16);
8268 Rm = Bits32(opcode, 3, 0);
8269 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008270 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008271
Johnny Chen2115b412011-02-21 23:42:44 +00008272 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008273 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008274 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008275 break;
8276 default:
8277 return false;
8278 }
8279
8280 // Read the first operand.
8281 uint32_t val1 = ReadCoreReg(Rn, &success);
8282 if (!success)
8283 return false;
8284
8285 // Read the second operand.
8286 uint32_t val2 = ReadCoreReg(Rm, &success);
8287 if (!success)
8288 return false;
8289
8290 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8291 uint32_t result = val1 ^ shifted;
8292
8293 EmulateInstruction::Context context;
8294 context.type = EmulateInstruction::eContextImmediate;
8295 context.SetNoArgs ();
8296
8297 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8298 return false;
8299 }
8300 return true;
8301}
8302
Johnny Chen7c5234d2011-02-18 23:41:11 +00008303// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8304// writes the result to the destination register. It can optionally update the condition flags based
8305// on the result.
8306bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008307EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008308{
8309#if 0
8310 // ARM pseudo code...
8311 if ConditionPassed() then
8312 EncodingSpecificOperations();
8313 result = R[n] OR imm32;
8314 if d == 15 then // Can only occur for ARM encoding
8315 ALUWritePC(result); // setflags is always FALSE here
8316 else
8317 R[d] = result;
8318 if setflags then
8319 APSR.N = result<31>;
8320 APSR.Z = IsZeroBit(result);
8321 APSR.C = carry;
8322 // APSR.V unchanged
8323#endif
8324
8325 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008326
Greg Clayton7bc39082011-03-24 23:53:38 +00008327 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008328 {
8329 uint32_t Rd, Rn;
8330 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8331 bool setflags;
8332 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8333 switch (encoding)
8334 {
8335 case eEncodingT1:
8336 Rd = Bits32(opcode, 11, 8);
8337 Rn = Bits32(opcode, 19, 16);
8338 setflags = BitIsSet(opcode, 20);
8339 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008340 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008341 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008342 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008343 if (BadReg(Rd) || Rn == 13)
8344 return false;
8345 break;
8346 case eEncodingA1:
8347 Rd = Bits32(opcode, 15, 12);
8348 Rn = Bits32(opcode, 19, 16);
8349 setflags = BitIsSet(opcode, 20);
8350 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008351
Johnny Chen7c5234d2011-02-18 23:41:11 +00008352 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008353 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008354 break;
8355 default:
8356 return false;
8357 }
8358
8359 // Read the first operand.
8360 uint32_t val1 = ReadCoreReg(Rn, &success);
8361 if (!success)
8362 return false;
8363
8364 uint32_t result = val1 | imm32;
8365
8366 EmulateInstruction::Context context;
8367 context.type = EmulateInstruction::eContextImmediate;
8368 context.SetNoArgs ();
8369
8370 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8371 return false;
8372 }
8373 return true;
8374}
8375
8376// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8377// value, and writes the result to the destination register. It can optionally update the condition flags based
8378// on the result.
8379bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008380EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008381{
8382#if 0
8383 // ARM pseudo code...
8384 if ConditionPassed() then
8385 EncodingSpecificOperations();
8386 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8387 result = R[n] OR shifted;
8388 if d == 15 then // Can only occur for ARM encoding
8389 ALUWritePC(result); // setflags is always FALSE here
8390 else
8391 R[d] = result;
8392 if setflags then
8393 APSR.N = result<31>;
8394 APSR.Z = IsZeroBit(result);
8395 APSR.C = carry;
8396 // APSR.V unchanged
8397#endif
8398
8399 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008400
Greg Clayton7bc39082011-03-24 23:53:38 +00008401 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008402 {
8403 uint32_t Rd, Rn, Rm;
8404 ARM_ShifterType shift_t;
8405 uint32_t shift_n; // the shift applied to the value read from Rm
8406 bool setflags;
8407 uint32_t carry;
8408 switch (encoding)
8409 {
8410 case eEncodingT1:
8411 Rd = Rn = Bits32(opcode, 2, 0);
8412 Rm = Bits32(opcode, 5, 3);
8413 setflags = !InITBlock();
8414 shift_t = SRType_LSL;
8415 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008416 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008417 case eEncodingT2:
8418 Rd = Bits32(opcode, 11, 8);
8419 Rn = Bits32(opcode, 19, 16);
8420 Rm = Bits32(opcode, 3, 0);
8421 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008422 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8423 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008424 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008425 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008426 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8427 return false;
8428 break;
8429 case eEncodingA1:
8430 Rd = Bits32(opcode, 15, 12);
8431 Rn = Bits32(opcode, 19, 16);
8432 Rm = Bits32(opcode, 3, 0);
8433 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008434 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008435
Johnny Chen7c5234d2011-02-18 23:41:11 +00008436 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008437 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008438 break;
8439 default:
8440 return false;
8441 }
8442
8443 // Read the first operand.
8444 uint32_t val1 = ReadCoreReg(Rn, &success);
8445 if (!success)
8446 return false;
8447
8448 // Read the second operand.
8449 uint32_t val2 = ReadCoreReg(Rm, &success);
8450 if (!success)
8451 return false;
8452
8453 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008454 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008455
8456 EmulateInstruction::Context context;
8457 context.type = EmulateInstruction::eContextImmediate;
8458 context.SetNoArgs ();
8459
8460 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8461 return false;
8462 }
8463 return true;
8464}
8465
Johnny Chened32e7c2011-02-22 23:42:58 +00008466// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8467// the destination register. It can optionally update the condition flags based on the result.
8468bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008469EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008470{
8471#if 0
8472 // ARM pseudo code...
8473 if ConditionPassed() then
8474 EncodingSpecificOperations();
8475 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8476 if d == 15 then // Can only occur for ARM encoding
8477 ALUWritePC(result); // setflags is always FALSE here
8478 else
8479 R[d] = result;
8480 if setflags then
8481 APSR.N = result<31>;
8482 APSR.Z = IsZeroBit(result);
8483 APSR.C = carry;
8484 APSR.V = overflow;
8485#endif
8486
8487 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008488
8489 uint32_t Rd; // the destination register
8490 uint32_t Rn; // the first operand
8491 bool setflags;
8492 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8493 switch (encoding) {
8494 case eEncodingT1:
8495 Rd = Bits32(opcode, 2, 0);
8496 Rn = Bits32(opcode, 5, 3);
8497 setflags = !InITBlock();
8498 imm32 = 0;
8499 break;
8500 case eEncodingT2:
8501 Rd = Bits32(opcode, 11, 8);
8502 Rn = Bits32(opcode, 19, 16);
8503 setflags = BitIsSet(opcode, 20);
8504 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8505 if (BadReg(Rd) || BadReg(Rn))
8506 return false;
8507 break;
8508 case eEncodingA1:
8509 Rd = Bits32(opcode, 15, 12);
8510 Rn = Bits32(opcode, 19, 16);
8511 setflags = BitIsSet(opcode, 20);
8512 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008513
Johnny Chened32e7c2011-02-22 23:42:58 +00008514 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008515 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008516 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008517 break;
8518 default:
8519 return false;
8520 }
8521 // Read the register value from the operand register Rn.
8522 uint32_t reg_val = ReadCoreReg(Rn, &success);
8523 if (!success)
8524 return false;
8525
8526 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8527
8528 EmulateInstruction::Context context;
8529 context.type = EmulateInstruction::eContextImmediate;
8530 context.SetNoArgs ();
8531
8532 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8533 return false;
8534
8535 return true;
8536}
8537
8538// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8539// result to the destination register. It can optionally update the condition flags based on the result.
8540bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008541EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008542{
8543#if 0
8544 // ARM pseudo code...
8545 if ConditionPassed() then
8546 EncodingSpecificOperations();
8547 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8548 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8549 if d == 15 then // Can only occur for ARM encoding
8550 ALUWritePC(result); // setflags is always FALSE here
8551 else
8552 R[d] = result;
8553 if setflags then
8554 APSR.N = result<31>;
8555 APSR.Z = IsZeroBit(result);
8556 APSR.C = carry;
8557 APSR.V = overflow;
8558#endif
8559
8560 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008561
8562 uint32_t Rd; // the destination register
8563 uint32_t Rn; // the first operand
8564 uint32_t Rm; // the second operand
8565 bool setflags;
8566 ARM_ShifterType shift_t;
8567 uint32_t shift_n; // the shift applied to the value read from Rm
8568 switch (encoding) {
8569 case eEncodingT1:
8570 Rd = Bits32(opcode, 11, 8);
8571 Rn = Bits32(opcode, 19, 16);
8572 Rm = Bits32(opcode, 3, 0);
8573 setflags = BitIsSet(opcode, 20);
8574 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8575 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8576 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8577 return false;
8578 break;
8579 case eEncodingA1:
8580 Rd = Bits32(opcode, 15, 12);
8581 Rn = Bits32(opcode, 19, 16);
8582 Rm = Bits32(opcode, 3, 0);
8583 setflags = BitIsSet(opcode, 20);
8584 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008585
Johnny Chened32e7c2011-02-22 23:42:58 +00008586 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008587 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008588 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008589 break;
8590 default:
8591 return false;
8592 }
8593 // Read the register value from register Rn.
8594 uint32_t val1 = ReadCoreReg(Rn, &success);
8595 if (!success)
8596 return false;
8597
8598 // Read the register value from register Rm.
8599 uint32_t val2 = ReadCoreReg(Rm, &success);
8600 if (!success)
8601 return false;
8602
8603 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8604 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8605
8606 EmulateInstruction::Context context;
8607 context.type = EmulateInstruction::eContextImmediate;
8608 context.SetNoArgs();
8609 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8610 return false;
8611
8612 return true;
8613}
8614
Johnny Chen90e607b2011-02-23 00:07:09 +00008615// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8616// an immediate value, and writes the result to the destination register. It can optionally update the condition
8617// flags based on the result.
8618bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008619EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008620{
8621#if 0
8622 // ARM pseudo code...
8623 if ConditionPassed() then
8624 EncodingSpecificOperations();
8625 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8626 if d == 15 then
8627 ALUWritePC(result); // setflags is always FALSE here
8628 else
8629 R[d] = result;
8630 if setflags then
8631 APSR.N = result<31>;
8632 APSR.Z = IsZeroBit(result);
8633 APSR.C = carry;
8634 APSR.V = overflow;
8635#endif
8636
8637 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008638
8639 uint32_t Rd; // the destination register
8640 uint32_t Rn; // the first operand
8641 bool setflags;
8642 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8643 switch (encoding) {
8644 case eEncodingA1:
8645 Rd = Bits32(opcode, 15, 12);
8646 Rn = Bits32(opcode, 19, 16);
8647 setflags = BitIsSet(opcode, 20);
8648 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008649
Johnny Chen90e607b2011-02-23 00:07:09 +00008650 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008651 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008652 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008653 break;
8654 default:
8655 return false;
8656 }
8657 // Read the register value from the operand register Rn.
8658 uint32_t reg_val = ReadCoreReg(Rn, &success);
8659 if (!success)
8660 return false;
8661
8662 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8663
8664 EmulateInstruction::Context context;
8665 context.type = EmulateInstruction::eContextImmediate;
8666 context.SetNoArgs ();
8667
8668 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8669 return false;
8670
8671 return true;
8672}
8673
8674// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8675// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8676// condition flags based on the result.
8677bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008678EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008679{
8680#if 0
8681 // ARM pseudo code...
8682 if ConditionPassed() then
8683 EncodingSpecificOperations();
8684 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8685 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8686 if d == 15 then
8687 ALUWritePC(result); // setflags is always FALSE here
8688 else
8689 R[d] = result;
8690 if setflags then
8691 APSR.N = result<31>;
8692 APSR.Z = IsZeroBit(result);
8693 APSR.C = carry;
8694 APSR.V = overflow;
8695#endif
8696
8697 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008698
8699 uint32_t Rd; // the destination register
8700 uint32_t Rn; // the first operand
8701 uint32_t Rm; // the second operand
8702 bool setflags;
8703 ARM_ShifterType shift_t;
8704 uint32_t shift_n; // the shift applied to the value read from Rm
8705 switch (encoding) {
8706 case eEncodingA1:
8707 Rd = Bits32(opcode, 15, 12);
8708 Rn = Bits32(opcode, 19, 16);
8709 Rm = Bits32(opcode, 3, 0);
8710 setflags = BitIsSet(opcode, 20);
8711 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008712
Johnny Chen90e607b2011-02-23 00:07:09 +00008713 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008714 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008715 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008716 break;
8717 default:
8718 return false;
8719 }
8720 // Read the register value from register Rn.
8721 uint32_t val1 = ReadCoreReg(Rn, &success);
8722 if (!success)
8723 return false;
8724
8725 // Read the register value from register Rm.
8726 uint32_t val2 = ReadCoreReg(Rm, &success);
8727 if (!success)
8728 return false;
8729
8730 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8731 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8732
8733 EmulateInstruction::Context context;
8734 context.type = EmulateInstruction::eContextImmediate;
8735 context.SetNoArgs();
8736 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8737 return false;
8738
8739 return true;
8740}
8741
Johnny Chen9b381772011-02-23 01:01:21 +00008742// Subtract with Carry (immediate) subtracts an immediate value and the value of
8743// NOT (Carry flag) from a register value, and writes the result to the destination register.
8744// It can optionally update the condition flags based on the result.
8745bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008746EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008747{
8748#if 0
8749 // ARM pseudo code...
8750 if ConditionPassed() then
8751 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008752 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008753 if d == 15 then // Can only occur for ARM encoding
8754 ALUWritePC(result); // setflags is always FALSE here
8755 else
8756 R[d] = result;
8757 if setflags then
8758 APSR.N = result<31>;
8759 APSR.Z = IsZeroBit(result);
8760 APSR.C = carry;
8761 APSR.V = overflow;
8762#endif
8763
8764 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008765
8766 uint32_t Rd; // the destination register
8767 uint32_t Rn; // the first operand
8768 bool setflags;
8769 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8770 switch (encoding) {
8771 case eEncodingT1:
8772 Rd = Bits32(opcode, 11, 8);
8773 Rn = Bits32(opcode, 19, 16);
8774 setflags = BitIsSet(opcode, 20);
8775 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8776 if (BadReg(Rd) || BadReg(Rn))
8777 return false;
8778 break;
8779 case eEncodingA1:
8780 Rd = Bits32(opcode, 15, 12);
8781 Rn = Bits32(opcode, 19, 16);
8782 setflags = BitIsSet(opcode, 20);
8783 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008784
Johnny Chen9b381772011-02-23 01:01:21 +00008785 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008786 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008787 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008788 break;
8789 default:
8790 return false;
8791 }
8792 // Read the register value from the operand register Rn.
8793 uint32_t reg_val = ReadCoreReg(Rn, &success);
8794 if (!success)
8795 return false;
8796
8797 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8798
8799 EmulateInstruction::Context context;
8800 context.type = EmulateInstruction::eContextImmediate;
8801 context.SetNoArgs ();
8802
8803 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8804 return false;
8805
8806 return true;
8807}
8808
8809// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8810// NOT (Carry flag) from a register value, and writes the result to the destination register.
8811// It can optionally update the condition flags based on the result.
8812bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008813EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008814{
8815#if 0
8816 // ARM pseudo code...
8817 if ConditionPassed() then
8818 EncodingSpecificOperations();
8819 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8820 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8821 if d == 15 then // Can only occur for ARM encoding
8822 ALUWritePC(result); // setflags is always FALSE here
8823 else
8824 R[d] = result;
8825 if setflags then
8826 APSR.N = result<31>;
8827 APSR.Z = IsZeroBit(result);
8828 APSR.C = carry;
8829 APSR.V = overflow;
8830#endif
8831
8832 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008833
8834 uint32_t Rd; // the destination register
8835 uint32_t Rn; // the first operand
8836 uint32_t Rm; // the second operand
8837 bool setflags;
8838 ARM_ShifterType shift_t;
8839 uint32_t shift_n; // the shift applied to the value read from Rm
8840 switch (encoding) {
8841 case eEncodingT1:
8842 Rd = Rn = Bits32(opcode, 2, 0);
8843 Rm = Bits32(opcode, 5, 3);
8844 setflags = !InITBlock();
8845 shift_t = SRType_LSL;
8846 shift_n = 0;
8847 break;
8848 case eEncodingT2:
8849 Rd = Bits32(opcode, 11, 8);
8850 Rn = Bits32(opcode, 19, 16);
8851 Rm = Bits32(opcode, 3, 0);
8852 setflags = BitIsSet(opcode, 20);
8853 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8854 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8855 return false;
8856 break;
8857 case eEncodingA1:
8858 Rd = Bits32(opcode, 15, 12);
8859 Rn = Bits32(opcode, 19, 16);
8860 Rm = Bits32(opcode, 3, 0);
8861 setflags = BitIsSet(opcode, 20);
8862 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008863
Johnny Chen9b381772011-02-23 01:01:21 +00008864 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008865 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008866 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008867 break;
8868 default:
8869 return false;
8870 }
8871 // Read the register value from register Rn.
8872 uint32_t val1 = ReadCoreReg(Rn, &success);
8873 if (!success)
8874 return false;
8875
8876 // Read the register value from register Rm.
8877 uint32_t val2 = ReadCoreReg(Rm, &success);
8878 if (!success)
8879 return false;
8880
8881 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8882 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8883
8884 EmulateInstruction::Context context;
8885 context.type = EmulateInstruction::eContextImmediate;
8886 context.SetNoArgs();
8887 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8888 return false;
8889
8890 return true;
8891}
8892
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008893// This instruction subtracts an immediate value from a register value, and writes the result
8894// to the destination register. It can optionally update the condition flags based on the result.
8895bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008896EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008897{
8898#if 0
8899 // ARM pseudo code...
8900 if ConditionPassed() then
8901 EncodingSpecificOperations();
8902 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8903 R[d] = result;
8904 if setflags then
8905 APSR.N = result<31>;
8906 APSR.Z = IsZeroBit(result);
8907 APSR.C = carry;
8908 APSR.V = overflow;
8909#endif
8910
8911 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008912
8913 uint32_t Rd; // the destination register
8914 uint32_t Rn; // the first operand
8915 bool setflags;
8916 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8917 switch (encoding) {
8918 case eEncodingT1:
8919 Rd = Bits32(opcode, 2, 0);
8920 Rn = Bits32(opcode, 5, 3);
8921 setflags = !InITBlock();
8922 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8923 break;
8924 case eEncodingT2:
8925 Rd = Rn = Bits32(opcode, 10, 8);
8926 setflags = !InITBlock();
8927 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8928 break;
8929 case eEncodingT3:
8930 Rd = Bits32(opcode, 11, 8);
8931 Rn = Bits32(opcode, 19, 16);
8932 setflags = BitIsSet(opcode, 20);
8933 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8934
8935 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8936 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008937 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008938
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008939 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008940 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008941 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008942
8943 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8944 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8945 return false;
8946 break;
8947 case eEncodingT4:
8948 Rd = Bits32(opcode, 11, 8);
8949 Rn = Bits32(opcode, 19, 16);
8950 setflags = BitIsSet(opcode, 20);
8951 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8952
8953 // if Rn == '1111' then SEE ADR;
8954 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008955 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008956
8957 // if Rn == '1101' then SEE SUB (SP minus immediate);
8958 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008959 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008960
8961 if (BadReg(Rd))
8962 return false;
8963 break;
8964 default:
8965 return false;
8966 }
8967 // Read the register value from the operand register Rn.
8968 uint32_t reg_val = ReadCoreReg(Rn, &success);
8969 if (!success)
8970 return false;
8971
8972 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8973
8974 EmulateInstruction::Context context;
8975 context.type = EmulateInstruction::eContextImmediate;
8976 context.SetNoArgs ();
8977
8978 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8979 return false;
8980
8981 return true;
8982}
8983
8984// This instruction subtracts an immediate value from a register value, and writes the result
8985// to the destination register. It can optionally update the condition flags based on the result.
8986bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008987EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008988{
8989#if 0
8990 // ARM pseudo code...
8991 if ConditionPassed() then
8992 EncodingSpecificOperations();
8993 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8994 if d == 15 then
8995 ALUWritePC(result); // setflags is always FALSE here
8996 else
8997 R[d] = result;
8998 if setflags then
8999 APSR.N = result<31>;
9000 APSR.Z = IsZeroBit(result);
9001 APSR.C = carry;
9002 APSR.V = overflow;
9003#endif
9004
9005 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009006
9007 uint32_t Rd; // the destination register
9008 uint32_t Rn; // the first operand
9009 bool setflags;
9010 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9011 switch (encoding) {
9012 case eEncodingA1:
9013 Rd = Bits32(opcode, 15, 12);
9014 Rn = Bits32(opcode, 19, 16);
9015 setflags = BitIsSet(opcode, 20);
9016 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9017
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009018 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009019 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00009020 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009021
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009022 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009023 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009024 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009025
9026 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009027 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00009028 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009029 break;
9030 default:
9031 return false;
9032 }
9033 // Read the register value from the operand register Rn.
9034 uint32_t reg_val = ReadCoreReg(Rn, &success);
9035 if (!success)
9036 return false;
9037
9038 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9039
9040 EmulateInstruction::Context context;
9041 context.type = EmulateInstruction::eContextImmediate;
9042 context.SetNoArgs ();
9043
9044 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9045 return false;
9046
9047 return true;
9048}
9049
Johnny Chen2115b412011-02-21 23:42:44 +00009050// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9051// immediate value. It updates the condition flags based on the result, and discards the result.
9052bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009053EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009054{
9055#if 0
9056 // ARM pseudo code...
9057 if ConditionPassed() then
9058 EncodingSpecificOperations();
9059 result = R[n] EOR imm32;
9060 APSR.N = result<31>;
9061 APSR.Z = IsZeroBit(result);
9062 APSR.C = carry;
9063 // APSR.V unchanged
9064#endif
9065
9066 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009067
Greg Clayton7bc39082011-03-24 23:53:38 +00009068 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009069 {
9070 uint32_t Rn;
9071 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9072 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9073 switch (encoding)
9074 {
9075 case eEncodingT1:
9076 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009077 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009078 if (BadReg(Rn))
9079 return false;
9080 break;
9081 case eEncodingA1:
9082 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009083 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009084 break;
9085 default:
9086 return false;
9087 }
9088
9089 // Read the first operand.
9090 uint32_t val1 = ReadCoreReg(Rn, &success);
9091 if (!success)
9092 return false;
9093
9094 uint32_t result = val1 ^ imm32;
9095
9096 EmulateInstruction::Context context;
9097 context.type = EmulateInstruction::eContextImmediate;
9098 context.SetNoArgs ();
9099
9100 if (!WriteFlags(context, result, carry))
9101 return false;
9102 }
9103 return true;
9104}
9105
9106// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9107// optionally-shifted register value. It updates the condition flags based on the result, and discards
9108// the result.
9109bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009110EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009111{
9112#if 0
9113 // ARM pseudo code...
9114 if ConditionPassed() then
9115 EncodingSpecificOperations();
9116 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9117 result = R[n] EOR shifted;
9118 APSR.N = result<31>;
9119 APSR.Z = IsZeroBit(result);
9120 APSR.C = carry;
9121 // APSR.V unchanged
9122#endif
9123
9124 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009125
Greg Clayton7bc39082011-03-24 23:53:38 +00009126 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009127 {
9128 uint32_t Rn, Rm;
9129 ARM_ShifterType shift_t;
9130 uint32_t shift_n; // the shift applied to the value read from Rm
9131 uint32_t carry;
9132 switch (encoding)
9133 {
9134 case eEncodingT1:
9135 Rn = Bits32(opcode, 19, 16);
9136 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009137 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009138 if (BadReg(Rn) || BadReg(Rm))
9139 return false;
9140 break;
9141 case eEncodingA1:
9142 Rn = Bits32(opcode, 19, 16);
9143 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009144 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009145 break;
9146 default:
9147 return false;
9148 }
9149
9150 // Read the first operand.
9151 uint32_t val1 = ReadCoreReg(Rn, &success);
9152 if (!success)
9153 return false;
9154
9155 // Read the second operand.
9156 uint32_t val2 = ReadCoreReg(Rm, &success);
9157 if (!success)
9158 return false;
9159
9160 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9161 uint32_t result = val1 ^ shifted;
9162
9163 EmulateInstruction::Context context;
9164 context.type = EmulateInstruction::eContextImmediate;
9165 context.SetNoArgs ();
9166
9167 if (!WriteFlags(context, result, carry))
9168 return false;
9169 }
9170 return true;
9171}
9172
Johnny Chende3cce32011-02-21 21:24:49 +00009173// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9174// It updates the condition flags based on the result, and discards the result.
9175bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009176EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009177{
9178#if 0
9179 // ARM pseudo code...
9180 if ConditionPassed() then
9181 EncodingSpecificOperations();
9182 result = R[n] AND imm32;
9183 APSR.N = result<31>;
9184 APSR.Z = IsZeroBit(result);
9185 APSR.C = carry;
9186 // APSR.V unchanged
9187#endif
9188
9189 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009190
Greg Clayton7bc39082011-03-24 23:53:38 +00009191 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009192 {
9193 uint32_t Rn;
9194 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9195 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9196 switch (encoding)
9197 {
9198 case eEncodingT1:
9199 Rn = Bits32(opcode, 19, 16);
9200 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9201 if (BadReg(Rn))
9202 return false;
9203 break;
9204 case eEncodingA1:
9205 Rn = Bits32(opcode, 19, 16);
9206 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9207 break;
9208 default:
9209 return false;
9210 }
9211
9212 // Read the first operand.
9213 uint32_t val1 = ReadCoreReg(Rn, &success);
9214 if (!success)
9215 return false;
9216
9217 uint32_t result = val1 & imm32;
9218
9219 EmulateInstruction::Context context;
9220 context.type = EmulateInstruction::eContextImmediate;
9221 context.SetNoArgs ();
9222
9223 if (!WriteFlags(context, result, carry))
9224 return false;
9225 }
9226 return true;
9227}
9228
9229// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9230// It updates the condition flags based on the result, and discards the result.
9231bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009232EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009233{
9234#if 0
9235 // ARM pseudo code...
9236 if ConditionPassed() then
9237 EncodingSpecificOperations();
9238 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9239 result = R[n] AND shifted;
9240 APSR.N = result<31>;
9241 APSR.Z = IsZeroBit(result);
9242 APSR.C = carry;
9243 // APSR.V unchanged
9244#endif
9245
9246 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009247
Greg Clayton7bc39082011-03-24 23:53:38 +00009248 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009249 {
9250 uint32_t Rn, Rm;
9251 ARM_ShifterType shift_t;
9252 uint32_t shift_n; // the shift applied to the value read from Rm
9253 uint32_t carry;
9254 switch (encoding)
9255 {
9256 case eEncodingT1:
9257 Rn = Bits32(opcode, 2, 0);
9258 Rm = Bits32(opcode, 5, 3);
9259 shift_t = SRType_LSL;
9260 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009261 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009262 case eEncodingT2:
9263 Rn = Bits32(opcode, 19, 16);
9264 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009265 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009266 if (BadReg(Rn) || BadReg(Rm))
9267 return false;
9268 break;
9269 case eEncodingA1:
9270 Rn = Bits32(opcode, 19, 16);
9271 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009272 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009273 break;
9274 default:
9275 return false;
9276 }
9277
9278 // Read the first operand.
9279 uint32_t val1 = ReadCoreReg(Rn, &success);
9280 if (!success)
9281 return false;
9282
9283 // Read the second operand.
9284 uint32_t val2 = ReadCoreReg(Rm, &success);
9285 if (!success)
9286 return false;
9287
9288 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9289 uint32_t result = val1 & shifted;
9290
9291 EmulateInstruction::Context context;
9292 context.type = EmulateInstruction::eContextImmediate;
9293 context.SetNoArgs ();
9294
9295 if (!WriteFlags(context, result, carry))
9296 return false;
9297 }
9298 return true;
9299}
Caroline Ticed05b4902011-03-29 21:24:06 +00009300
9301// A8.6.216 SUB (SP minus register)
9302bool
9303EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9304{
9305#if 0
9306 if ConditionPassed() then
9307 EncodingSpecificOperations();
9308 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009309 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009310 if d == 15 then // Can only occur for ARM encoding
9311 ALUWritePC(result); // setflags is always FALSE here
9312 else
9313 R[d] = result;
9314 if setflags then
9315 APSR.N = result<31>;
9316 APSR.Z = IsZeroBit(result);
9317 APSR.C = carry;
9318 APSR.V = overflow;
9319#endif
9320
9321 bool success = false;
9322
9323 if (ConditionPassed(opcode))
9324 {
9325 uint32_t d;
9326 uint32_t m;
9327 bool setflags;
9328 ARM_ShifterType shift_t;
9329 uint32_t shift_n;
9330
9331 switch (encoding)
9332 {
9333 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009334 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009335 d = Bits32 (opcode, 11, 8);
9336 m = Bits32 (opcode, 3, 0);
9337 setflags = BitIsSet (opcode, 20);
9338
9339 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9340 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9341
9342 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9343 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9344 return false;
9345
9346 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9347 if ((d == 15) || BadReg (m))
9348 return false;
9349 break;
9350
9351 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009352 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009353 d = Bits32 (opcode, 15, 12);
9354 m = Bits32 (opcode, 3, 0);
9355 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009356
Greg Clayton061b79d2011-05-09 20:18:18 +00009357 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009358 if (d == 15 && setflags)
9359 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009360
9361 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9362 shift_n = DecodeImmShiftARM (opcode, shift_t);
9363 break;
9364
9365 default:
9366 return false;
9367 }
9368
9369 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9370 uint32_t Rm = ReadCoreReg (m, &success);
9371 if (!success)
9372 return false;
9373
9374 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9375
Greg Clayton061b79d2011-05-09 20:18:18 +00009376 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009377 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9378 if (!success)
9379 return false;
9380
9381 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9382
9383 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009384 context.type = eContextArithmetic;
9385 RegisterInfo sp_reg;
9386 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9387 RegisterInfo dwarf_reg;
9388 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +00009389 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9390
Caroline Ticeef440002011-03-30 05:40:56 +00009391 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009392 return false;
9393 }
9394 return true;
9395}
9396
9397
9398// A8.6.7 ADD (register-shifted register)
9399bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009400EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009401{
9402#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009403 if ConditionPassed() then
9404 EncodingSpecificOperations();
9405 shift_n = UInt(R[s]<7:0>);
9406 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009407 (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009408 R[d] = result;
9409 if setflags then
9410 APSR.N = result<31>;
9411 APSR.Z = IsZeroBit(result);
9412 APSR.C = carry;
9413 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009414#endif
9415
Caroline Ticec08ed382011-03-29 23:03:16 +00009416 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009417
9418 if (ConditionPassed(opcode))
9419 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009420 uint32_t d;
9421 uint32_t n;
9422 uint32_t m;
9423 uint32_t s;
9424 bool setflags;
9425 ARM_ShifterType shift_t;
9426
Caroline Ticed05b4902011-03-29 21:24:06 +00009427 switch (encoding)
9428 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009429 case eEncodingA1:
9430 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9431 d = Bits32 (opcode, 15, 12);
9432 n = Bits32 (opcode, 19, 16);
9433 m = Bits32 (opcode, 3, 0);
9434 s = Bits32 (opcode, 11, 8);
9435
Greg Clayton061b79d2011-05-09 20:18:18 +00009436 // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
Caroline Ticec08ed382011-03-29 23:03:16 +00009437 setflags = BitIsSet (opcode, 20);
9438 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9439
9440 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9441 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9442 return false;
9443 break;
9444
9445 default:
9446 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009447 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009448
9449 // shift_n = UInt(R[s]<7:0>);
9450 uint32_t Rs = ReadCoreReg (s, &success);
9451 if (!success)
9452 return false;
9453
9454 uint32_t shift_n = Bits32 (Rs, 7, 0);
9455
9456 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9457 uint32_t Rm = ReadCoreReg (m, &success);
9458 if (!success)
9459 return false;
9460
9461 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9462
Greg Clayton061b79d2011-05-09 20:18:18 +00009463 // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009464 uint32_t Rn = ReadCoreReg (n, &success);
9465 if (!success)
9466 return false;
9467
9468 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9469
9470 // R[d] = result;
9471 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009472 context.type = eContextArithmetic;
9473 RegisterInfo reg_n;
9474 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9475 RegisterInfo reg_m;
9476 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009477
9478 context.SetRegisterRegisterOperands (reg_n, reg_m);
9479
9480 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9481 return false;
9482
9483 // if setflags then
9484 // APSR.N = result<31>;
9485 // APSR.Z = IsZeroBit(result);
9486 // APSR.C = carry;
9487 // APSR.V = overflow;
9488 if (setflags)
9489 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009490 }
9491 return true;
9492}
9493
9494// A8.6.213 SUB (register)
9495bool
9496EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9497{
9498#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009499 if ConditionPassed() then
9500 EncodingSpecificOperations();
9501 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009502 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009503 if d == 15 then // Can only occur for ARM encoding
9504 ALUWritePC(result); // setflags is always FALSE here
9505 else
9506 R[d] = result;
9507 if setflags then
9508 APSR.N = result<31>;
9509 APSR.Z = IsZeroBit(result);
9510 APSR.C = carry;
9511 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009512#endif
9513
Caroline Tice4cccd532011-03-29 23:44:20 +00009514 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009515
9516 if (ConditionPassed(opcode))
9517 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009518 uint32_t d;
9519 uint32_t n;
9520 uint32_t m;
9521 bool setflags;
9522 ARM_ShifterType shift_t;
9523 uint32_t shift_n;
9524
Caroline Ticed05b4902011-03-29 21:24:06 +00009525 switch (encoding)
9526 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009527 case eEncodingT1:
9528 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9529 d = Bits32 (opcode, 2, 0);
9530 n = Bits32 (opcode, 5, 3);
9531 m = Bits32 (opcode, 8, 6);
9532 setflags = !InITBlock();
9533
9534 // (shift_t, shift_n) = (SRType_LSL, 0);
9535 shift_t = SRType_LSL;
9536 shift_n = 0;
9537
9538 break;
9539
9540 case eEncodingT2:
Greg Clayton061b79d2011-05-09 20:18:18 +00009541 // if Rd == Ô1111Õ && S == Ô1Õ then SEE CMP (register);
9542 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9543 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009544 d = Bits32 (opcode, 11, 8);
9545 n = Bits32 (opcode, 19, 16);
9546 m = Bits32 (opcode, 3, 0);
9547 setflags = BitIsSet (opcode, 20);
9548
9549 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9550 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9551
9552 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9553 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9554 return false;
9555
9556 break;
9557
9558 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009559 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9560 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009561 d = Bits32 (opcode, 15, 12);
9562 n = Bits32 (opcode, 19, 16);
9563 m = Bits32 (opcode, 3, 0);
9564 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009565
Greg Clayton061b79d2011-05-09 20:18:18 +00009566 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009567 if ((d == 15) && setflags)
9568 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009569
9570 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9571 shift_n = DecodeImmShiftARM (opcode, shift_t);
9572
9573 break;
9574
9575 default:
9576 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009577 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009578
9579 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9580 uint32_t Rm = ReadCoreReg (m, &success);
9581 if (!success)
9582 return false;
9583
9584 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9585
Greg Clayton061b79d2011-05-09 20:18:18 +00009586 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009587 uint32_t Rn = ReadCoreReg (n, &success);
9588 if (!success)
9589 return false;
9590
9591 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9592
9593 // if d == 15 then // Can only occur for ARM encoding
9594 // ALUWritePC(result); // setflags is always FALSE here
9595 // else
9596 // R[d] = result;
9597 // if setflags then
9598 // APSR.N = result<31>;
9599 // APSR.Z = IsZeroBit(result);
9600 // APSR.C = carry;
9601 // APSR.V = overflow;
9602
9603 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009604 context.type = eContextArithmetic;
9605 RegisterInfo reg_n;
9606 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9607 RegisterInfo reg_m;
9608 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009609 context.SetRegisterRegisterOperands (reg_n, reg_m);
9610
Caroline Ticeef440002011-03-30 05:40:56 +00009611 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009612 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009613 }
9614 return true;
9615}
Caroline Tice4cccd532011-03-29 23:44:20 +00009616
Caroline Ticed05b4902011-03-29 21:24:06 +00009617// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009618// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9619// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009620bool
9621EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9622{
9623#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009624 if ConditionPassed() then
9625 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9626 address = R[n] + imm32;
9627 if ExclusiveMonitorsPass(address,4) then
9628 MemA[address,4] = R[t];
9629 R[d] = 0;
9630 else
9631 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009632#endif
9633
Caroline Tice5168b6c2011-03-30 05:15:46 +00009634 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009635
9636 if (ConditionPassed(opcode))
9637 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009638 uint32_t d;
9639 uint32_t t;
9640 uint32_t n;
9641 uint32_t imm32;
9642 const uint32_t addr_byte_size = GetAddressByteSize();
9643
Caroline Ticed05b4902011-03-29 21:24:06 +00009644 switch (encoding)
9645 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009646 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009647 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009648 d = Bits32 (opcode, 11, 8);
9649 t = Bits32 (opcode, 15, 12);
9650 n = Bits32 (opcode, 19, 16);
9651 imm32 = Bits32 (opcode, 7, 0) << 2;
9652
9653 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9654 if (BadReg (d) || BadReg (t) || (n == 15))
9655 return false;
9656
9657 // if d == n || d == t then UNPREDICTABLE;
9658 if ((d == n) || (d == t))
9659 return false;
9660
9661 break;
9662
9663 case eEncodingA1:
9664 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9665 d = Bits32 (opcode, 15, 12);
9666 t = Bits32 (opcode, 3, 0);
9667 n = Bits32 (opcode, 19, 16);
9668 imm32 = 0;
9669
9670 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9671 if ((d == 15) || (t == 15) || (n == 15))
9672 return false;
9673
9674 // if d == n || d == t then UNPREDICTABLE;
9675 if ((d == n) || (d == t))
9676 return false;
9677
9678 break;
9679
9680 default:
9681 return false;
9682 }
9683
9684 // address = R[n] + imm32;
9685 uint32_t Rn = ReadCoreReg (n, &success);
9686 if (!success)
9687 return false;
9688
9689 addr_t address = Rn + imm32;
9690
Greg Claytonc07d4512011-04-26 23:48:45 +00009691 RegisterInfo base_reg;
9692 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9693 RegisterInfo data_reg;
9694 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009695 EmulateInstruction::Context context;
9696 context.type = eContextRegisterStore;
9697 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9698
9699 // if ExclusiveMonitorsPass(address,4) then
9700 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9701 // always return true.
9702 if (true)
9703 {
9704 // MemA[address,4] = R[t];
9705 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9706 if (!success)
9707 return false;
9708
9709 if (!MemAWrite (context, address, Rt, addr_byte_size))
9710 return false;
9711
9712 // R[d] = 0;
9713 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9714 return false;
9715 }
9716 else
9717 {
9718 // R[d] = 1;
9719 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9720 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009721 }
9722 }
9723 return true;
9724}
9725
9726// A8.6.197 STRB (immediate, ARM)
9727bool
9728EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9729{
9730#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009731 if ConditionPassed() then
9732 EncodingSpecificOperations();
9733 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9734 address = if index then offset_addr else R[n];
9735 MemU[address,1] = R[t]<7:0>;
9736 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009737#endif
9738
Caroline Ticeef440002011-03-30 05:40:56 +00009739 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009740
9741 if (ConditionPassed(opcode))
9742 {
Caroline Ticeef440002011-03-30 05:40:56 +00009743 uint32_t t;
9744 uint32_t n;
9745 uint32_t imm32;
9746 bool index;
9747 bool add;
9748 bool wback;
9749
Caroline Ticed05b4902011-03-29 21:24:06 +00009750 switch (encoding)
9751 {
Caroline Ticeef440002011-03-30 05:40:56 +00009752 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009753 // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
Caroline Ticeef440002011-03-30 05:40:56 +00009754 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9755 t = Bits32 (opcode, 15, 12);
9756 n = Bits32 (opcode, 19, 16);
9757 imm32 = Bits32 (opcode, 11, 0);
9758
Greg Clayton061b79d2011-05-09 20:18:18 +00009759 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeef440002011-03-30 05:40:56 +00009760 index = BitIsSet (opcode, 24);
9761 add = BitIsSet (opcode, 23);
9762 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9763
9764 // if t == 15 then UNPREDICTABLE;
9765 if (t == 15)
9766 return false;
9767
9768 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9769 if (wback && ((n == 15) || (n == t)))
9770 return false;
9771
9772 break;
9773
9774 default:
9775 return false;
9776 }
9777
9778 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9779 uint32_t Rn = ReadCoreReg (n, &success);
9780 if (!success)
9781 return false;
9782
9783 addr_t offset_addr;
9784 if (add)
9785 offset_addr = Rn + imm32;
9786 else
9787 offset_addr = Rn - imm32;
9788
9789 // address = if index then offset_addr else R[n];
9790 addr_t address;
9791 if (index)
9792 address = offset_addr;
9793 else
9794 address = Rn;
9795
9796 // MemU[address,1] = R[t]<7:0>;
9797 uint32_t Rt = ReadCoreReg (t, &success);
9798 if (!success)
9799 return false;
9800
Greg Claytonc07d4512011-04-26 23:48:45 +00009801 RegisterInfo base_reg;
9802 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9803 RegisterInfo data_reg;
9804 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticeef440002011-03-30 05:40:56 +00009805 EmulateInstruction::Context context;
9806 context.type = eContextRegisterStore;
9807 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9808
9809 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9810 return false;
9811
9812 // if wback then R[n] = offset_addr;
9813 if (wback)
9814 {
Caroline Tice523c5542011-04-13 00:42:12 +00009815 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009816 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009817 }
9818 }
9819 return true;
9820}
9821
9822// A8.6.194 STR (immediate, ARM)
9823bool
9824EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9825{
9826#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009827 if ConditionPassed() then
9828 EncodingSpecificOperations();
9829 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9830 address = if index then offset_addr else R[n];
9831 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9832 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009833#endif
9834
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009835 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009836
9837 if (ConditionPassed(opcode))
9838 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009839 uint32_t t;
9840 uint32_t n;
9841 uint32_t imm32;
9842 bool index;
9843 bool add;
9844 bool wback;
9845
9846 const uint32_t addr_byte_size = GetAddressByteSize();
9847
Caroline Ticed05b4902011-03-29 21:24:06 +00009848 switch (encoding)
9849 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009850 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009851 // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
9852 // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009853 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9854 t = Bits32 (opcode, 15, 12);
9855 n = Bits32 (opcode, 19, 16);
9856 imm32 = Bits32 (opcode, 11, 0);
9857
Greg Clayton061b79d2011-05-09 20:18:18 +00009858 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009859 index = BitIsSet (opcode, 24);
9860 add = BitIsSet (opcode, 23);
9861 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9862
9863 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9864 if (wback && ((n == 15) || (n == t)))
9865 return false;
9866
9867 break;
9868
9869 default:
9870 return false;
9871 }
9872
9873 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9874 uint32_t Rn = ReadCoreReg (n, &success);
9875 if (!success)
9876 return false;
9877
9878 addr_t offset_addr;
9879 if (add)
9880 offset_addr = Rn + imm32;
9881 else
9882 offset_addr = Rn - imm32;
9883
9884 // address = if index then offset_addr else R[n];
9885 addr_t address;
9886 if (index)
9887 address = offset_addr;
9888 else
9889 address = Rn;
9890
Greg Claytonc07d4512011-04-26 23:48:45 +00009891 RegisterInfo base_reg;
9892 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9893 RegisterInfo data_reg;
9894 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009895 EmulateInstruction::Context context;
9896 context.type = eContextRegisterStore;
9897 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9898
9899 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9900 uint32_t Rt = ReadCoreReg (t, &success);
9901 if (!success)
9902 return false;
9903
9904 if (t == 15)
9905 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009906 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009907 if (!success)
9908 return false;
9909
9910 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9911 return false;
9912 }
9913 else
9914 {
9915 if (!MemUWrite (context, address, Rt, addr_byte_size))
9916 return false;
9917 }
9918
9919 // if wback then R[n] = offset_addr;
9920 if (wback)
9921 {
9922 context.type = eContextAdjustBaseRegister;
9923 context.SetImmediate (offset_addr);
9924
9925 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9926 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009927 }
9928 }
9929 return true;
9930}
9931
Caroline Ticed05b4902011-03-29 21:24:06 +00009932// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009933// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9934// 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 +00009935bool
9936EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9937{
9938#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009939 if ConditionPassed() then
9940 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9941 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9942 address = if index then offset_addr else R[n];
9943 R[t] = MemA[address,4];
9944 R[t2] = MemA[address+4,4];
9945 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009946#endif
9947
Caroline Tice1697dd72011-03-30 17:11:45 +00009948 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009949
9950 if (ConditionPassed(opcode))
9951 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009952 uint32_t t;
9953 uint32_t t2;
9954 uint32_t n;
9955 uint32_t imm32;
9956 bool index;
9957 bool add;
9958 bool wback;
9959
Caroline Ticed05b4902011-03-29 21:24:06 +00009960 switch (encoding)
9961 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009962 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009963 //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
9964 //if Rn == Ô1111Õ then SEE LDRD (literal);
9965 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice1697dd72011-03-30 17:11:45 +00009966 t = Bits32 (opcode, 15, 12);
9967 t2 = Bits32 (opcode, 11, 8);
9968 n = Bits32 (opcode, 19, 16);
9969 imm32 = Bits32 (opcode, 7, 0) << 2;
9970
Greg Clayton061b79d2011-05-09 20:18:18 +00009971 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +00009972 index = BitIsSet (opcode, 24);
9973 add = BitIsSet (opcode, 23);
9974 wback = BitIsSet (opcode, 21);
9975
9976 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9977 if (wback && ((n == t) || (n == t2)))
9978 return false;
9979
9980 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9981 if (BadReg (t) || BadReg (t2) || (t == t2))
9982 return false;
9983
9984 break;
9985
9986 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009987 //if Rn == Ô1111Õ then SEE LDRD (literal);
9988 //if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +00009989 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9990 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009991 if (BitIsSet (t, 0))
9992 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009993 t2 = t + 1;
9994 n = Bits32 (opcode, 19, 16);
9995 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9996
Greg Clayton061b79d2011-05-09 20:18:18 +00009997 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +00009998 index = BitIsSet (opcode, 24);
9999 add = BitIsSet (opcode, 23);
10000 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10001
Greg Clayton061b79d2011-05-09 20:18:18 +000010002 //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010003 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10004 return false;
10005
10006 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10007 if (wback && ((n == t) || (n == t2)))
10008 return false;
10009
10010 //if t2 == 15 then UNPREDICTABLE;
10011 if (t2 == 15)
10012 return false;
10013
10014 break;
10015
10016 default:
10017 return false;
10018 }
10019
10020 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10021 uint32_t Rn = ReadCoreReg (n, &success);
10022 if (!success)
10023 return false;
10024
10025 addr_t offset_addr;
10026 if (add)
10027 offset_addr = Rn + imm32;
10028 else
10029 offset_addr = Rn - imm32;
10030
10031 //address = if index then offset_addr else R[n];
10032 addr_t address;
10033 if (index)
10034 address = offset_addr;
10035 else
10036 address = Rn;
10037
10038 //R[t] = MemA[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +000010039 RegisterInfo base_reg;
10040 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1697dd72011-03-30 17:11:45 +000010041
10042 EmulateInstruction::Context context;
10043 context.type = eContextRegisterLoad;
10044 context.SetRegisterPlusOffset (base_reg, address - Rn);
10045
10046 const uint32_t addr_byte_size = GetAddressByteSize();
10047 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10048 if (!success)
10049 return false;
10050
10051 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10052 return false;
10053
10054 //R[t2] = MemA[address+4,4];
10055
10056 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10057 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10058 if (!success)
10059 return false;
10060
10061 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10062 return false;
10063
10064 //if wback then R[n] = offset_addr;
10065 if (wback)
10066 {
10067 context.type = eContextAdjustBaseRegister;
10068 context.SetAddress (offset_addr);
10069
10070 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10071 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010072 }
10073 }
10074 return true;
10075}
10076
Caroline Ticed05b4902011-03-29 21:24:06 +000010077// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010078// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10079// 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 +000010080bool
10081EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10082{
10083#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010084 if ConditionPassed() then
10085 EncodingSpecificOperations();
10086 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10087 address = if index then offset_addr else R[n];
10088 R[t] = MemA[address,4];
10089 R[t2] = MemA[address+4,4];
10090 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010091#endif
10092
Caroline Ticeeab301f2011-03-30 17:54:52 +000010093 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010094
10095 if (ConditionPassed(opcode))
10096 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010097 uint32_t t;
10098 uint32_t t2;
10099 uint32_t n;
10100 uint32_t m;
10101 bool index;
10102 bool add;
10103 bool wback;
10104
Caroline Ticed05b4902011-03-29 21:24:06 +000010105 switch (encoding)
10106 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010107 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010108 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010109 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10110 t = Bits32 (opcode, 15, 12);
10111 if (BitIsSet (t, 0))
10112 return false;
10113 t2 = t + 1;
10114 n = Bits32 (opcode, 19, 16);
10115 m = Bits32 (opcode, 3, 0);
10116
Greg Clayton061b79d2011-05-09 20:18:18 +000010117 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010118 index = BitIsSet (opcode, 24);
10119 add = BitIsSet (opcode, 23);
10120 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10121
Greg Clayton061b79d2011-05-09 20:18:18 +000010122 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010123 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10124 return false;
10125
10126 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10127 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10128 return false;
10129
10130 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10131 if (wback && ((n == 15) || (n == t) || (n == t2)))
10132 return false;
10133
10134 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10135 if ((ArchVersion() < 6) && wback && (m == n))
10136 return false;
10137 break;
10138
10139 default:
10140 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010141 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010142
Caroline Ticeeab301f2011-03-30 17:54:52 +000010143 uint32_t Rn = ReadCoreReg (n, &success);
10144 if (!success)
10145 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010146 RegisterInfo base_reg;
10147 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010148
Caroline Ticeeab301f2011-03-30 17:54:52 +000010149 uint32_t Rm = ReadCoreReg (m, &success);
10150 if (!success)
10151 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010152 RegisterInfo offset_reg;
10153 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010154
Caroline Ticeeab301f2011-03-30 17:54:52 +000010155 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10156 addr_t offset_addr;
10157 if (add)
10158 offset_addr = Rn + Rm;
10159 else
10160 offset_addr = Rn - Rm;
10161
10162 // address = if index then offset_addr else R[n];
10163 addr_t address;
10164 if (index)
10165 address = offset_addr;
10166 else
10167 address = Rn;
10168
10169 EmulateInstruction::Context context;
10170 context.type = eContextRegisterLoad;
10171 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10172
10173 // R[t] = MemA[address,4];
10174 const uint32_t addr_byte_size = GetAddressByteSize();
10175 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10176 if (!success)
10177 return false;
10178
10179 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10180 return false;
10181
10182 // R[t2] = MemA[address+4,4];
10183
10184 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10185 if (!success)
10186 return false;
10187
10188 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10189 return false;
10190
10191 // if wback then R[n] = offset_addr;
10192 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010193 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010194 context.type = eContextAdjustBaseRegister;
10195 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010196
Caroline Ticeeab301f2011-03-30 17:54:52 +000010197 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10198 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010199 }
10200 }
10201 return true;
10202}
Caroline Ticed05b4902011-03-29 21:24:06 +000010203
10204// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010205// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10206// 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 +000010207bool
10208EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10209{
10210#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010211 if ConditionPassed() then
10212 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10213 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10214 address = if index then offset_addr else R[n];
10215 MemA[address,4] = R[t];
10216 MemA[address+4,4] = R[t2];
10217 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010218#endif
10219
Caroline Tice74467fe2011-03-30 19:02:56 +000010220 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010221
Caroline Tice74467fe2011-03-30 19:02:56 +000010222 if (ConditionPassed(opcode))
10223 {
10224 uint32_t t;
10225 uint32_t t2;
10226 uint32_t n;
10227 uint32_t imm32;
10228 bool index;
10229 bool add;
10230 bool wback;
10231
10232 switch (encoding)
10233 {
10234 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010235 // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10236 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice74467fe2011-03-30 19:02:56 +000010237 t = Bits32 (opcode, 15, 12);
10238 t2 = Bits32 (opcode, 11, 8);
10239 n = Bits32 (opcode, 19, 16);
10240 imm32 = Bits32 (opcode, 7, 0) << 2;
10241
Greg Clayton061b79d2011-05-09 20:18:18 +000010242 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010243 index = BitIsSet (opcode, 24);
10244 add = BitIsSet (opcode, 23);
10245 wback = BitIsSet (opcode, 21);
10246
10247 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10248 if (wback && ((n == t) || (n == t2)))
10249 return false;
10250
10251 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10252 if ((n == 15) || BadReg (t) || BadReg (t2))
10253 return false;
10254
10255 break;
10256
10257 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010258 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010259 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10260 t = Bits32 (opcode, 15, 12);
10261 if (BitIsSet (t, 0))
10262 return false;
10263
10264 t2 = t + 1;
10265 n = Bits32 (opcode, 19, 16);
10266 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10267
Greg Clayton061b79d2011-05-09 20:18:18 +000010268 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010269 index = BitIsSet (opcode, 24);
10270 add = BitIsSet (opcode, 23);
10271 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10272
Greg Clayton061b79d2011-05-09 20:18:18 +000010273 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010274 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10275 return false;
10276
10277 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10278 if (wback && ((n == 15) || (n == t) || (n == t2)))
10279 return false;
10280
10281 // if t2 == 15 then UNPREDICTABLE;
10282 if (t2 == 15)
10283 return false;
10284
10285 break;
10286
10287 default:
10288 return false;
10289 }
10290
Greg Claytonc07d4512011-04-26 23:48:45 +000010291 RegisterInfo base_reg;
10292 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010293
10294 uint32_t Rn = ReadCoreReg (n, &success);
10295 if (!success)
10296 return false;
10297
10298 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10299 addr_t offset_addr;
10300 if (add)
10301 offset_addr = Rn + imm32;
10302 else
10303 offset_addr = Rn - imm32;
10304
10305 //address = if index then offset_addr else R[n];
10306 addr_t address;
10307 if (index)
10308 address = offset_addr;
10309 else
10310 address = Rn;
10311
10312 //MemA[address,4] = R[t];
Greg Claytonc07d4512011-04-26 23:48:45 +000010313 RegisterInfo data_reg;
10314 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010315
10316 uint32_t data = ReadCoreReg (t, &success);
10317 if (!success)
10318 return false;
10319
10320 EmulateInstruction::Context context;
10321 context.type = eContextRegisterStore;
10322 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10323
10324 const uint32_t addr_byte_size = GetAddressByteSize();
10325
10326 if (!MemAWrite (context, address, data, addr_byte_size))
10327 return false;
10328
10329 //MemA[address+4,4] = R[t2];
Greg Claytonc07d4512011-04-26 23:48:45 +000010330 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010331 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10332
10333 data = ReadCoreReg (t2, &success);
10334 if (!success)
10335 return false;
10336
10337 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10338 return false;
10339
10340 //if wback then R[n] = offset_addr;
10341 if (wback)
10342 {
10343 context.type = eContextAdjustBaseRegister;
10344 context.SetAddress (offset_addr);
10345
10346 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10347 return false;
10348 }
10349 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010350 return true;
10351}
10352
10353
10354// A8.6.201 STRD (register)
10355bool
10356EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10357{
10358#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010359 if ConditionPassed() then
10360 EncodingSpecificOperations();
10361 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10362 address = if index then offset_addr else R[n];
10363 MemA[address,4] = R[t];
10364 MemA[address+4,4] = R[t2];
10365 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010366#endif
10367
Caroline Tice74467fe2011-03-30 19:02:56 +000010368 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010369
Caroline Tice74467fe2011-03-30 19:02:56 +000010370 if (ConditionPassed(opcode))
10371 {
10372 uint32_t t;
10373 uint32_t t2;
10374 uint32_t n;
10375 uint32_t m;
10376 bool index;
10377 bool add;
10378 bool wback;
10379
10380 switch (encoding)
10381 {
10382 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010383 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010384 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10385 t = Bits32 (opcode, 15, 12);
10386 if (BitIsSet (t, 0))
10387 return false;
10388
10389 t2 = t+1;
10390 n = Bits32 (opcode, 19, 16);
10391 m = Bits32 (opcode, 3, 0);
10392
Greg Clayton061b79d2011-05-09 20:18:18 +000010393 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010394 index = BitIsSet (opcode, 24);
10395 add = BitIsSet (opcode, 23);
10396 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10397
Greg Clayton061b79d2011-05-09 20:18:18 +000010398 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010399 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10400 return false;
10401
10402 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10403 if ((t2 == 15) || (m == 15))
10404 return false;
10405
10406 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10407 if (wback && ((n == 15) || (n == t) || (n == t2)))
10408 return false;
10409
10410 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010411 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010412 return false;
10413
10414 break;
10415
10416 default:
10417 return false;
10418 }
10419
Greg Claytonc07d4512011-04-26 23:48:45 +000010420 RegisterInfo base_reg;
10421 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10422 RegisterInfo offset_reg;
10423 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10424 RegisterInfo data_reg;
Caroline Tice74467fe2011-03-30 19:02:56 +000010425
10426 uint32_t Rn = ReadCoreReg (n, &success);
10427 if (!success)
10428 return false;
10429
10430 uint32_t Rm = ReadCoreReg (m, &success);
10431 if (!success)
10432 return false;
10433
10434 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10435 addr_t offset_addr;
10436 if (add)
10437 offset_addr = Rn + Rm;
10438 else
10439 offset_addr = Rn - Rm;
10440
10441 // address = if index then offset_addr else R[n];
10442 addr_t address;
10443 if (index)
10444 address = offset_addr;
10445 else
10446 address = Rn;
10447 // MemA[address,4] = R[t];
10448 uint32_t Rt = ReadCoreReg (t, &success);
10449 if (!success)
10450 return false;
10451
10452 EmulateInstruction::Context context;
10453 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +000010454 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010455 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10456
10457 const uint32_t addr_byte_size = GetAddressByteSize();
10458
10459 if (!MemAWrite (context, address, Rt, addr_byte_size))
10460 return false;
10461
10462 // MemA[address+4,4] = R[t2];
10463 uint32_t Rt2 = ReadCoreReg (t2, &success);
10464 if (!success)
10465 return false;
10466
Greg Claytonc07d4512011-04-26 23:48:45 +000010467 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010468
10469 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10470
10471 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10472 return false;
10473
10474 // if wback then R[n] = offset_addr;
10475 if (wback)
10476 {
10477 context.type = eContextAdjustBaseRegister;
10478 context.SetAddress (offset_addr);
10479
10480 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10481 return false;
10482
10483 }
10484 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010485 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010486}
10487
Caroline Tice4f605582011-03-31 00:02:51 +000010488// A8.6.319 VLDM
10489// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10490// an ARM core register.
10491bool
10492EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10493{
10494#if 0
10495 if ConditionPassed() then
10496 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10497 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010498 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010499 for r = 0 to regs-1
10500 if single_regs then
10501 S[d+r] = MemA[address,4]; address = address+4;
10502 else
10503 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10504 // Combine the word-aligned words in the correct order for current endianness.
10505 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10506#endif
10507
10508 bool success = false;
10509
10510 if (ConditionPassed(opcode))
10511 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010512 bool single_regs;
10513 bool add;
10514 bool wback;
10515 uint32_t d;
10516 uint32_t n;
10517 uint32_t imm32;
10518 uint32_t regs;
10519
Caroline Tice4f605582011-03-31 00:02:51 +000010520 switch (encoding)
10521 {
10522 case eEncodingT1:
10523 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010524 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10525 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10526 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10527 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010528 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10529 return false;
10530
10531 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010532 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice4f605582011-03-31 00:02:51 +000010533 single_regs = false;
10534 add = BitIsSet (opcode, 23);
10535 wback = BitIsSet (opcode, 21);
10536
Greg Clayton061b79d2011-05-09 20:18:18 +000010537 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice4f605582011-03-31 00:02:51 +000010538 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10539 n = Bits32 (opcode, 19, 16);
10540 imm32 = Bits32 (opcode, 7, 0) << 2;
10541
Greg Clayton061b79d2011-05-09 20:18:18 +000010542 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
Caroline Tice4f605582011-03-31 00:02:51 +000010543 regs = Bits32 (opcode, 7, 0) / 2;
10544
10545 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10546 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10547 return false;
10548
10549 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10550 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10551 return false;
10552
10553 break;
10554
10555 case eEncodingT2:
10556 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010557 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10558 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10559 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10560 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010561 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10562 return false;
10563
10564 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010565 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Tice4f605582011-03-31 00:02:51 +000010566 single_regs = true;
10567 add = BitIsSet (opcode, 23);
10568 wback = BitIsSet (opcode, 21);
10569 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10570 n = Bits32 (opcode, 19, 16);
10571
Greg Clayton061b79d2011-05-09 20:18:18 +000010572 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Tice4f605582011-03-31 00:02:51 +000010573 imm32 = Bits32 (opcode, 7, 0) << 2;
10574 regs = Bits32 (opcode, 7, 0);
10575
10576 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10577 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10578 return false;
10579
10580 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10581 if ((regs == 0) || ((d + regs) > 32))
10582 return false;
10583 break;
10584
10585 default:
10586 return false;
10587 }
10588
Greg Claytonc07d4512011-04-26 23:48:45 +000010589 RegisterInfo base_reg;
10590 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4f605582011-03-31 00:02:51 +000010591
10592 uint32_t Rn = ReadCoreReg (n, &success);
10593 if (!success)
10594 return false;
10595
10596 // address = if add then R[n] else R[n]-imm32;
10597 addr_t address;
10598 if (add)
10599 address = Rn;
10600 else
10601 address = Rn - imm32;
10602
Greg Claytonc07d4512011-04-26 23:48:45 +000010603 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010604 EmulateInstruction::Context context;
10605
10606 if (wback)
10607 {
10608 uint32_t value;
10609 if (add)
10610 value = Rn + imm32;
10611 else
10612 value = Rn - imm32;
10613
10614 context.type = eContextAdjustBaseRegister;
10615 context.SetImmediateSigned (value - Rn);
10616 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10617 return false;
10618
10619 }
10620
10621 const uint32_t addr_byte_size = GetAddressByteSize();
10622 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10623
10624 context.type = eContextRegisterLoad;
10625
10626 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010627 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010628 {
10629 if (single_regs)
10630 {
10631 // S[d+r] = MemA[address,4]; address = address+4;
10632 context.SetRegisterPlusOffset (base_reg, address - Rn);
10633
10634 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10635 if (!success)
10636 return false;
10637
10638 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10639 return false;
10640
10641 address = address + 4;
10642 }
10643 else
10644 {
10645 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10646 context.SetRegisterPlusOffset (base_reg, address - Rn);
10647 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10648 if (!success)
10649 return false;
10650
10651 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10652 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10653 if (!success)
10654 return false;
10655
10656 address = address + 8;
10657 // // Combine the word-aligned words in the correct order for current endianness.
10658 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10659 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010660 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010661 {
10662 data = word1;
10663 data = (data << 32) | word2;
10664 }
10665 else
10666 {
10667 data = word2;
10668 data = (data << 32) | word1;
10669 }
10670
10671 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10672 return false;
10673 }
10674 }
10675 }
10676 return true;
10677}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010678
10679// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010680// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10681// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010682bool
10683EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10684{
10685#if 0
10686 if ConditionPassed() then
10687 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10688 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010689 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010690 for r = 0 to regs-1
10691 if single_regs then
10692 MemA[address,4] = S[d+r]; address = address+4;
10693 else
10694 // Store as two word-aligned words in the correct order for current endianness.
10695 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10696 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10697 address = address+8;
10698#endif
10699
10700 bool success = false;
10701
10702 if (ConditionPassed (opcode))
10703 {
10704 bool single_regs;
10705 bool add;
10706 bool wback;
10707 uint32_t d;
10708 uint32_t n;
10709 uint32_t imm32;
10710 uint32_t regs;
10711
10712 switch (encoding)
10713 {
10714 case eEncodingT1:
10715 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010716 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10717 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10718 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10719 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010720 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10721 return false;
10722
10723 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010724 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010725 single_regs = false;
10726 add = BitIsSet (opcode, 23);
10727 wback = BitIsSet (opcode, 21);
10728
Greg Clayton061b79d2011-05-09 20:18:18 +000010729 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010730 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10731 n = Bits32 (opcode, 19, 16);
10732 imm32 = Bits32 (opcode, 7, 0) << 2;
10733
Greg Clayton061b79d2011-05-09 20:18:18 +000010734 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010735 regs = Bits32 (opcode, 7, 0) / 2;
10736
10737 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10738 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10739 return false;
10740
10741 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10742 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10743 return false;
10744
10745 break;
10746
10747 case eEncodingT2:
10748 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010749 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10750 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10751 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10752 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010753 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10754 return false;
10755
10756 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010757 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010758 single_regs = true;
10759 add = BitIsSet (opcode, 23);
10760 wback = BitIsSet (opcode, 21);
10761 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10762 n = Bits32 (opcode, 19, 16);
10763
Greg Clayton061b79d2011-05-09 20:18:18 +000010764 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010765 imm32 = Bits32 (opcode, 7, 0) << 2;
10766 regs = Bits32 (opcode, 7, 0);
10767
10768 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10769 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10770 return false;
10771
10772 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10773 if ((regs == 0) || ((d + regs) > 32))
10774 return false;
10775
10776 break;
10777
10778 default:
10779 return false;
10780 }
10781
Greg Claytonc07d4512011-04-26 23:48:45 +000010782 RegisterInfo base_reg;
10783 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010784
10785 uint32_t Rn = ReadCoreReg (n, &success);
10786 if (!success)
10787 return false;
10788
10789 // address = if add then R[n] else R[n]-imm32;
10790 addr_t address;
10791 if (add)
10792 address = Rn;
10793 else
10794 address = Rn - imm32;
10795
10796 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +000010797 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010798 if (wback)
10799 {
10800 uint32_t value;
10801 if (add)
10802 value = Rn + imm32;
10803 else
10804 value = Rn - imm32;
10805
10806 context.type = eContextAdjustBaseRegister;
10807 context.SetRegisterPlusOffset (base_reg, value - Rn);
10808
10809 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10810 return false;
10811 }
10812
10813 const uint32_t addr_byte_size = GetAddressByteSize();
10814 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10815
10816 context.type = eContextRegisterStore;
10817 // for r = 0 to regs-1
10818 for (int r = 0; r < regs; ++r)
10819 {
Greg Claytonc07d4512011-04-26 23:48:45 +000010820
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010821 if (single_regs)
10822 {
10823 // MemA[address,4] = S[d+r]; address = address+4;
10824 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10825 if (!success)
10826 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010827
10828 RegisterInfo data_reg;
10829 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010830 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10831 if (!MemAWrite (context, address, data, addr_byte_size))
10832 return false;
10833
10834 address = address + 4;
10835 }
10836 else
10837 {
10838 // // Store as two word-aligned words in the correct order for current endianness.
10839 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10840 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10841 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10842 if (!success)
10843 return false;
10844
Greg Claytonc07d4512011-04-26 23:48:45 +000010845 RegisterInfo data_reg;
10846 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010847
Greg Clayton888a7332011-04-26 04:39:08 +000010848 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010849 {
10850 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10851 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10852 return false;
10853
10854 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10855 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10856 return false;
10857 }
10858 else
10859 {
10860 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10861 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10862 return false;
10863
10864 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10865 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10866 return false;
10867 }
10868 // address = address+8;
10869 address = address + 8;
10870 }
10871 }
10872 }
10873 return true;
10874}
10875
Caroline Tice917ad352011-03-31 05:05:30 +000010876// A8.6.320
10877// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10878// an optional offset.
10879bool
10880EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10881{
10882#if 0
10883 if ConditionPassed() then
10884 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10885 base = if n == 15 then Align(PC,4) else R[n];
10886 address = if add then (base + imm32) else (base - imm32);
10887 if single_reg then
10888 S[d] = MemA[address,4];
10889 else
10890 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10891 // Combine the word-aligned words in the correct order for current endianness.
10892 D[d] = if BigEndian() then word1:word2 else word2:word1;
10893#endif
10894
10895 bool success = false;
10896
10897 if (ConditionPassed (opcode))
10898 {
10899 bool single_reg;
10900 bool add;
10901 uint32_t imm32;
10902 uint32_t d;
10903 uint32_t n;
10904
10905 switch (encoding)
10906 {
10907 case eEncodingT1:
10908 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010909 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010910 single_reg = false;
10911 add = BitIsSet (opcode, 23);
10912 imm32 = Bits32 (opcode, 7, 0) << 2;
10913
10914 // d = UInt(D:Vd); n = UInt(Rn);
10915 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10916 n = Bits32 (opcode, 19, 16);
10917
10918 break;
10919
10920 case eEncodingT2:
10921 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010922 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010923 single_reg = true;
10924 add = BitIsSet (opcode, 23);
10925 imm32 = Bits32 (opcode, 7, 0) << 2;
10926
10927 // d = UInt(Vd:D); n = UInt(Rn);
10928 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10929 n = Bits32 (opcode, 19, 16);
10930
10931 break;
10932
10933 default:
10934 return false;
10935 }
Greg Claytonc07d4512011-04-26 23:48:45 +000010936 RegisterInfo base_reg;
10937 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice917ad352011-03-31 05:05:30 +000010938
10939 uint32_t Rn = ReadCoreReg (n, &success);
10940 if (!success)
10941 return false;
10942
10943 // base = if n == 15 then Align(PC,4) else R[n];
10944 uint32_t base;
10945 if (n == 15)
10946 base = AlignPC (Rn);
10947 else
10948 base = Rn;
10949
10950 // address = if add then (base + imm32) else (base - imm32);
10951 addr_t address;
10952 if (add)
10953 address = base + imm32;
10954 else
10955 address = base - imm32;
10956
10957 const uint32_t addr_byte_size = GetAddressByteSize();
10958 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
10959
10960 EmulateInstruction::Context context;
10961 context.type = eContextRegisterLoad;
10962 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010963
Caroline Tice917ad352011-03-31 05:05:30 +000010964 if (single_reg)
10965 {
10966 // S[d] = MemA[address,4];
10967 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10968 if (!success)
10969 return false;
10970
10971 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
10972 return false;
10973 }
10974 else
10975 {
10976 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
10977 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10978 if (!success)
10979 return false;
10980
10981 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
10982 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10983 if (!success)
10984 return false;
10985 // // Combine the word-aligned words in the correct order for current endianness.
10986 // D[d] = if BigEndian() then word1:word2 else word2:word1;
10987 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000010988 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000010989 {
10990 data64 = word1;
10991 data64 = (data64 << 32) | word2;
10992 }
10993 else
10994 {
10995 data64 = word2;
10996 data64 = (data64 << 32) | word1;
10997 }
10998
10999 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
11000 return false;
11001 }
11002 }
11003 return true;
11004}
Caroline Tice424652f2011-03-31 05:38:36 +000011005
11006// A8.6.400 VSTR
11007// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
11008// optional offset.
11009bool
11010EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
11011{
11012#if 0
11013 if ConditionPassed() then
11014 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11015 address = if add then (R[n] + imm32) else (R[n] - imm32);
11016 if single_reg then
11017 MemA[address,4] = S[d];
11018 else
11019 // Store as two word-aligned words in the correct order for current endianness.
11020 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11021 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11022#endif
11023
11024 bool success = false;
11025
11026 if (ConditionPassed (opcode))
11027 {
11028 bool single_reg;
11029 bool add;
11030 uint32_t imm32;
11031 uint32_t d;
11032 uint32_t n;
11033
11034 switch (encoding)
11035 {
11036 case eEncodingT1:
11037 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011038 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011039 single_reg = false;
11040 add = BitIsSet (opcode, 23);
11041 imm32 = Bits32 (opcode, 7, 0) << 2;
11042
11043 // d = UInt(D:Vd); n = UInt(Rn);
11044 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11045 n = Bits32 (opcode, 19, 16);
11046
11047 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11048 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11049 return false;
11050
11051 break;
11052
11053 case eEncodingT2:
11054 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011055 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011056 single_reg = true;
11057 add = BitIsSet (opcode, 23);
11058 imm32 = Bits32 (opcode, 7, 0) << 2;
11059
11060 // d = UInt(Vd:D); n = UInt(Rn);
11061 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11062 n = Bits32 (opcode, 19, 16);
11063
11064 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11065 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11066 return false;
11067
11068 break;
11069
11070 default:
11071 return false;
11072 }
11073
Greg Claytonc07d4512011-04-26 23:48:45 +000011074 RegisterInfo base_reg;
11075 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011076
11077 uint32_t Rn = ReadCoreReg (n, &success);
11078 if (!success)
11079 return false;
11080
11081 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11082 addr_t address;
11083 if (add)
11084 address = Rn + imm32;
11085 else
11086 address = Rn - imm32;
11087
11088 const uint32_t addr_byte_size = GetAddressByteSize();
11089 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11090
Greg Claytonc07d4512011-04-26 23:48:45 +000011091 RegisterInfo data_reg;
11092 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011093 EmulateInstruction::Context context;
11094 context.type = eContextRegisterStore;
11095 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11096
11097 if (single_reg)
11098 {
11099 // MemA[address,4] = S[d];
11100 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11101 if (!success)
11102 return false;
11103
11104 if (!MemAWrite (context, address, data, addr_byte_size))
11105 return false;
11106 }
11107 else
11108 {
11109 // // Store as two word-aligned words in the correct order for current endianness.
11110 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11111 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11112 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11113 if (!success)
11114 return false;
11115
Greg Clayton888a7332011-04-26 04:39:08 +000011116 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011117 {
11118 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11119 return false;
11120
11121 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11122 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11123 return false;
11124 }
11125 else
11126 {
11127 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11128 return false;
11129
11130 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11131 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11132 return false;
11133 }
11134 }
11135 }
11136 return true;
11137}
Caroline Tice9121b352011-03-31 16:41:19 +000011138
11139// A8.6.307 VLDI1 (multiple single elements)
11140// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11141// element of each register is loaded.
11142bool
11143EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11144{
11145#if 0
11146 if ConditionPassed() then
11147 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11148 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11149 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11150 for r = 0 to regs-1
11151 for e = 0 to elements-1
11152 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11153 address = address + ebytes;
11154#endif
11155
11156 bool success = false;
11157
11158 if (ConditionPassed (opcode))
11159 {
11160 uint32_t regs;
11161 uint32_t alignment;
11162 uint32_t ebytes;
11163 uint32_t esize;
11164 uint32_t elements;
11165 uint32_t d;
11166 uint32_t n;
11167 uint32_t m;
11168 bool wback;
11169 bool register_index;
11170
11171 switch (encoding)
11172 {
11173 case eEncodingT1:
11174 case eEncodingA1:
11175 {
11176 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011177 // when Ô0111Õ
11178 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
11179 // when Ô1010Õ
11180 // regs = 2; if align == Ô11Õ then UNDEFINED;
11181 // when Ô0110Õ
11182 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
11183 // when Ô0010Õ
Caroline Tice9121b352011-03-31 16:41:19 +000011184 // regs = 4;
11185 // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011186 // SEE ÒRelated encodingsÓ;
Caroline Tice9121b352011-03-31 16:41:19 +000011187 uint32_t type = Bits32 (opcode, 11, 8);
11188 uint32_t align = Bits32 (opcode, 5, 4);
11189 if (type == 7) // '0111'
11190 {
11191 regs = 1;
11192 if (BitIsSet (align, 1))
11193 return false;
11194 }
11195 else if (type == 10) // '1010'
11196 {
11197 regs = 2;
11198 if (align == 3)
11199 return false;
11200
11201 }
11202 else if (type == 6) // '0110'
11203 {
11204 regs = 3;
11205 if (BitIsSet (align, 1))
11206 return false;
11207 }
11208 else if (type == 2) // '0010'
11209 {
11210 regs = 4;
11211 }
11212 else
11213 return false;
11214
Greg Clayton061b79d2011-05-09 20:18:18 +000011215 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice9121b352011-03-31 16:41:19 +000011216 if (align == 0)
11217 alignment = 1;
11218 else
11219 alignment = 4 << align;
11220
11221 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11222 ebytes = 1 << Bits32 (opcode, 7, 6);
11223 esize = 8 * ebytes;
11224 elements = 8 / ebytes;
11225
11226 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11227 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11228 n = Bits32 (opcode, 19, 15);
11229 m = Bits32 (opcode, 3, 0);
11230
11231 // wback = (m != 15); register_index = (m != 15 && m != 13);
11232 wback = (m != 15);
11233 register_index = ((m != 15) && (m != 13));
11234
11235 // if d+regs > 32 then UNPREDICTABLE;
11236 if ((d + regs) > 32)
11237 return false;
11238 }
11239 break;
11240
11241 default:
11242 return false;
11243 }
11244
Greg Claytonc07d4512011-04-26 23:48:45 +000011245 RegisterInfo base_reg;
11246 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice9121b352011-03-31 16:41:19 +000011247
11248 uint32_t Rn = ReadCoreReg (n, &success);
11249 if (!success)
11250 return false;
11251
11252 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11253 addr_t address = Rn;
11254 if ((address % alignment) != 0)
11255 return false;
11256
11257 EmulateInstruction::Context context;
11258 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11259 if (wback)
11260 {
11261 uint32_t Rm = ReadCoreReg (m, &success);
11262 if (!success)
11263 return false;
11264
11265 uint32_t offset;
11266 if (register_index)
11267 offset = Rm;
11268 else
11269 offset = 8 * regs;
11270
11271 uint32_t value = Rn + offset;
11272 context.type = eContextAdjustBaseRegister;
11273 context.SetRegisterPlusOffset (base_reg, offset);
11274
11275 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11276 return false;
11277
11278 }
11279
11280 // for r = 0 to regs-1
11281 for (int r = 0; r < regs; ++r)
11282 {
11283 // for e = 0 to elements-1
11284 uint64_t assembled_data = 0;
11285 for (int e = 0; e < elements; ++e)
11286 {
11287 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11288 context.type = eContextRegisterLoad;
11289 context.SetRegisterPlusOffset (base_reg, address - Rn);
11290 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11291 if (!success)
11292 return false;
11293
11294 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11295
11296 // address = address + ebytes;
11297 address = address + ebytes;
11298 }
11299 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11300 return false;
11301 }
11302 }
11303 return true;
11304}
11305
Caroline Ticeb6281b12011-03-31 17:58:23 +000011306// A8.6.308 VLD1 (single element to one lane)
11307//
11308bool
11309EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11310{
11311#if 0
11312 if ConditionPassed() then
11313 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11314 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11315 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11316 Elem[D[d],index,esize] = MemU[address,ebytes];
11317#endif
11318
11319 bool success = false;
11320
11321 if (ConditionPassed (opcode))
11322 {
11323 uint32_t ebytes;
11324 uint32_t esize;
11325 uint32_t index;
11326 uint32_t alignment;
11327 uint32_t d;
11328 uint32_t n;
11329 uint32_t m;
11330 bool wback;
11331 bool register_index;
11332
11333 switch (encoding)
11334 {
11335 case eEncodingT1:
11336 case eEncodingA1:
11337 {
11338 uint32_t size = Bits32 (opcode, 11, 10);
11339 uint32_t index_align = Bits32 (opcode, 7, 4);
Greg Clayton061b79d2011-05-09 20:18:18 +000011340 // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011341 if (size == 3)
11342 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011343 // case size of
11344 if (size == 0) // when '00'
11345 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011346 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011347 if (BitIsClear (index_align, 0))
11348 return false;
11349
11350 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11351 ebytes = 1;
11352 esize = 8;
11353 index = Bits32 (index_align, 3, 1);
11354 alignment = 1;
11355 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011356 else if (size == 1) // when Ô01Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011357 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011358 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011359 if (BitIsClear (index_align, 1))
11360 return false;
11361
11362 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11363 ebytes = 2;
11364 esize = 16;
11365 index = Bits32 (index_align, 3, 2);
11366
Greg Clayton061b79d2011-05-09 20:18:18 +000011367 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011368 if (BitIsClear (index_align, 0))
11369 alignment = 1;
11370 else
11371 alignment = 2;
11372 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011373 else if (size == 2) // when Ô10Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011374 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011375 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011376 if (BitIsClear (index_align, 2))
11377 return false;
11378
Greg Clayton061b79d2011-05-09 20:18:18 +000011379 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011380 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11381 return false;
11382
11383 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11384 ebytes = 4;
11385 esize = 32;
11386 index = Bit32 (index_align, 3);
11387
Greg Clayton061b79d2011-05-09 20:18:18 +000011388 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011389 if (Bits32 (index_align, 1, 0) == 0)
11390 alignment = 1;
11391 else
11392 alignment = 4;
11393 }
11394 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11395 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11396 n = Bits32 (opcode, 19, 16);
11397 m = Bits32 (opcode, 3, 0);
11398
11399 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11400 wback = (m != 15);
11401 register_index = ((m != 15) && (m != 13));
11402
11403 if (n == 15)
11404 return false;
11405
11406 }
11407 break;
11408
11409 default:
11410 return false;
11411 }
11412
Greg Claytonc07d4512011-04-26 23:48:45 +000011413 RegisterInfo base_reg;
11414 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011415
11416 uint32_t Rn = ReadCoreReg (n, &success);
11417 if (!success)
11418 return false;
11419
11420 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11421 addr_t address = Rn;
11422 if ((address % alignment) != 0)
11423 return false;
11424
11425 EmulateInstruction::Context context;
11426 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11427 if (wback)
11428 {
11429 uint32_t Rm = ReadCoreReg (m, &success);
11430 if (!success)
11431 return false;
11432
11433 uint32_t offset;
11434 if (register_index)
11435 offset = Rm;
11436 else
11437 offset = ebytes;
11438
11439 uint32_t value = Rn + offset;
11440
11441 context.type = eContextAdjustBaseRegister;
11442 context.SetRegisterPlusOffset (base_reg, offset);
11443
11444 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11445 return false;
11446 }
11447
11448 // Elem[D[d],index,esize] = MemU[address,ebytes];
11449 uint32_t element = MemURead (context, address, esize, 0, &success);
11450 if (!success)
11451 return false;
11452
11453 element = element << (index * esize);
11454
11455 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11456 if (!success)
11457 return false;
11458
11459 uint64_t all_ones = -1;
11460 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11461 // at element & to the right of element.
11462 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011463 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 +000011464 // now mask should be 0's where element goes & 1's
11465 // everywhere else.
11466
11467 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11468 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11469
11470 context.type = eContextRegisterLoad;
11471 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11472 return false;
11473 }
11474 return true;
11475}
11476
Caroline Tice1e542e32011-03-31 18:44:04 +000011477// A8.6.391 VST1 (multiple single elements)
11478// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11479// interleaving. Every element of each register is stored.
11480bool
11481EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11482{
11483#if 0
11484 if ConditionPassed() then
11485 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11486 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11487 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11488 for r = 0 to regs-1
11489 for e = 0 to elements-1
11490 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11491 address = address + ebytes;
11492#endif
11493
11494 bool success = false;
11495
11496 if (ConditionPassed (opcode))
11497 {
11498 uint32_t regs;
11499 uint32_t alignment;
11500 uint32_t ebytes;
11501 uint32_t esize;
11502 uint32_t elements;
11503 uint32_t d;
11504 uint32_t n;
11505 uint32_t m;
11506 bool wback;
11507 bool register_index;
11508
11509 switch (encoding)
11510 {
11511 case eEncodingT1:
11512 case eEncodingA1:
11513 {
11514 uint32_t type = Bits32 (opcode, 11, 8);
11515 uint32_t align = Bits32 (opcode, 5, 4);
11516
11517 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011518 if (type == 7) // when Ô0111Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011519 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011520 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011521 regs = 1;
11522 if (BitIsSet (align, 1))
11523 return false;
11524 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011525 else if (type == 10) // when Ô1010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011526 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011527 // regs = 2; if align == Ô11Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011528 regs = 2;
11529 if (align == 3)
11530 return false;
11531 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011532 else if (type == 6) // when Ô0110Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011533 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011534 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011535 regs = 3;
11536 if (BitIsSet (align, 1))
11537 return false;
11538 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011539 else if (type == 2) // when Ô0010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011540 // regs = 4;
11541 regs = 4;
11542 else // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011543 // SEE ÒRelated encodingsÓ;
Caroline Tice1e542e32011-03-31 18:44:04 +000011544 return false;
11545
Greg Clayton061b79d2011-05-09 20:18:18 +000011546 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice1e542e32011-03-31 18:44:04 +000011547 if (align == 0)
11548 alignment = 0;
11549 else
11550 alignment = 4 << align;
11551
11552 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11553 ebytes = 1 << Bits32 (opcode,7, 6);
11554 esize = 8 * ebytes;
11555 elements = 8 / ebytes;
11556
11557 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11558 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11559 n = Bits32 (opcode, 19, 16);
11560 m = Bits32 (opcode, 3, 0);
11561
11562 // wback = (m != 15); register_index = (m != 15 && m != 13);
11563 wback = (m != 15);
11564 register_index = ((m != 15) && (m != 13));
11565
11566 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11567 if ((d + regs) > 32)
11568 return false;
11569
11570 if (n == 15)
11571 return false;
11572
11573 }
11574 break;
11575
11576 default:
11577 return false;
11578 }
11579
Greg Claytonc07d4512011-04-26 23:48:45 +000011580 RegisterInfo base_reg;
11581 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011582
11583 uint32_t Rn = ReadCoreReg (n, &success);
11584 if (!success)
11585 return false;
11586
11587 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11588 addr_t address = Rn;
11589 if ((address % alignment) != 0)
11590 return false;
11591
11592 EmulateInstruction::Context context;
11593 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11594 if (wback)
11595 {
11596 uint32_t Rm = ReadCoreReg (m, &success);
11597 if (!success)
11598 return false;
11599
11600 uint32_t offset;
11601 if (register_index)
11602 offset = Rm;
11603 else
11604 offset = 8 * regs;
11605
11606 context.type = eContextAdjustBaseRegister;
11607 context.SetRegisterPlusOffset (base_reg, offset);
11608
11609 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11610 return false;
11611 }
11612
Greg Claytonc07d4512011-04-26 23:48:45 +000011613 RegisterInfo data_reg;
Caroline Tice1e542e32011-03-31 18:44:04 +000011614 context.type = eContextRegisterStore;
Caroline Tice1e542e32011-03-31 18:44:04 +000011615 // for r = 0 to regs-1
11616 for (int r = 0; r < regs; ++r)
11617 {
Greg Claytonc07d4512011-04-26 23:48:45 +000011618 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011619 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11620 if (!success)
11621 return false;
11622
11623 // for e = 0 to elements-1
11624 for (int e = 0; e < elements; ++e)
11625 {
11626 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011627 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011628
11629 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11630 if (!MemUWrite (context, address, word, ebytes))
11631 return false;
11632
11633 // address = address + ebytes;
11634 address = address + ebytes;
11635 }
11636 }
11637 }
11638 return true;
11639}
11640
Caroline Tice7b880942011-03-31 19:17:12 +000011641// A8.6.392 VST1 (single element from one lane)
11642// This instruction stores one element to memory from one element of a register.
11643bool
11644EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11645{
11646#if 0
11647 if ConditionPassed() then
11648 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11649 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11650 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11651 MemU[address,ebytes] = Elem[D[d],index,esize];
11652#endif
11653
11654 bool success = false;
11655
11656 if (ConditionPassed (opcode))
11657 {
11658 uint32_t ebytes;
11659 uint32_t esize;
11660 uint32_t index;
11661 uint32_t alignment;
11662 uint32_t d;
11663 uint32_t n;
11664 uint32_t m;
11665 bool wback;
11666 bool register_index;
11667
11668 switch (encoding)
11669 {
11670 case eEncodingT1:
11671 case eEncodingA1:
11672 {
11673 uint32_t size = Bits32 (opcode, 11, 10);
11674 uint32_t index_align = Bits32 (opcode, 7, 4);
11675
Greg Clayton061b79d2011-05-09 20:18:18 +000011676 // if size == Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011677 if (size == 3)
11678 return false;
11679
11680 // case size of
Greg Clayton061b79d2011-05-09 20:18:18 +000011681 if (size == 0) // when Ô00Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011682 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011683 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011684 if (BitIsClear (index_align, 0))
11685 return false;
11686 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11687 ebytes = 1;
11688 esize = 8;
11689 index = Bits32 (index_align, 3, 1);
11690 alignment = 1;
11691 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011692 else if (size == 1) // when Ô01Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011693 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011694 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011695 if (BitIsClear (index_align, 1))
11696 return false;
11697
11698 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11699 ebytes = 2;
11700 esize = 16;
11701 index = Bits32 (index_align, 3, 2);
11702
Greg Clayton061b79d2011-05-09 20:18:18 +000011703 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Tice7b880942011-03-31 19:17:12 +000011704 if (BitIsClear (index_align, 0))
11705 alignment = 1;
11706 else
11707 alignment = 2;
11708 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011709 else if (size == 2) // when Ô10Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011710 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011711 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011712 if (BitIsClear (index_align, 2))
11713 return false;
11714
Greg Clayton061b79d2011-05-09 20:18:18 +000011715 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011716 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11717 return false;
11718
11719 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11720 ebytes = 4;
11721 esize = 32;
11722 index = Bit32 (index_align, 3);
11723
Greg Clayton061b79d2011-05-09 20:18:18 +000011724 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Tice7b880942011-03-31 19:17:12 +000011725 if (Bits32 (index_align, 1, 0) == 0)
11726 alignment = 1;
11727 else
11728 alignment = 4;
11729 }
11730 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11731 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11732 n = Bits32 (opcode, 19, 16);
11733 m = Bits32 (opcode, 3, 0);
11734
11735 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11736 wback = (m != 15);
11737 register_index = ((m != 15) && (m != 13));
11738
11739 if (n == 15)
11740 return false;
11741 }
11742 break;
11743
11744 default:
11745 return false;
11746 }
11747
Greg Claytonc07d4512011-04-26 23:48:45 +000011748 RegisterInfo base_reg;
11749 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011750
11751 uint32_t Rn = ReadCoreReg (n, &success);
11752 if (!success)
11753 return false;
11754
11755 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11756 addr_t address = Rn;
11757 if ((address % alignment) != 0)
11758 return false;
11759
11760 EmulateInstruction::Context context;
11761 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11762 if (wback)
11763 {
11764 uint32_t Rm = ReadCoreReg (m, &success);
11765 if (!success)
11766 return false;
11767
11768 uint32_t offset;
11769 if (register_index)
11770 offset = Rm;
11771 else
11772 offset = ebytes;
11773
11774 context.type = eContextAdjustBaseRegister;
11775 context.SetRegisterPlusOffset (base_reg, offset);
11776
11777 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11778 return false;
11779 }
11780
11781 // MemU[address,ebytes] = Elem[D[d],index,esize];
11782 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11783 if (!success)
11784 return false;
11785
11786 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11787
Greg Claytonc07d4512011-04-26 23:48:45 +000011788 RegisterInfo data_reg;
11789 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011790 context.type = eContextRegisterStore;
11791 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11792
11793 if (!MemUWrite (context, address, word, ebytes))
11794 return false;
11795 }
11796 return true;
11797}
11798
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011799// A8.6.309 VLD1 (single element to all lanes)
11800// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011801bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011802EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011803{
11804#if 0
11805 if ConditionPassed() then
11806 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11807 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11808 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11809 replicated_element = Replicate(MemU[address,ebytes], elements);
11810 for r = 0 to regs-1
11811 D[d+r] = replicated_element;
11812#endif
11813
11814 bool success = false;
11815
11816 if (ConditionPassed (opcode))
11817 {
11818 uint32_t ebytes;
11819 uint32_t elements;
11820 uint32_t regs;
11821 uint32_t alignment;
11822 uint32_t d;
11823 uint32_t n;
11824 uint32_t m;
11825 bool wback;
11826 bool register_index;
11827
11828 switch (encoding)
11829 {
11830 case eEncodingT1:
11831 case eEncodingA1:
11832 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011833 //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
Caroline Tice93767b82011-03-31 21:15:29 +000011834 uint32_t size = Bits32 (opcode, 7, 6);
11835 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11836 return false;
11837
Greg Clayton061b79d2011-05-09 20:18:18 +000011838 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
Caroline Tice93767b82011-03-31 21:15:29 +000011839 ebytes = 1 << size;
11840 elements = 8 / ebytes;
11841 if (BitIsClear (opcode, 5))
11842 regs = 1;
11843 else
11844 regs = 2;
11845
Greg Clayton061b79d2011-05-09 20:18:18 +000011846 //alignment = if a == Ô0Õ then 1 else ebytes;
Caroline Tice93767b82011-03-31 21:15:29 +000011847 if (BitIsClear (opcode, 4))
11848 alignment = 1;
11849 else
11850 alignment = ebytes;
11851
11852 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11853 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11854 n = Bits32 (opcode, 19, 16);
11855 m = Bits32 (opcode, 3, 0);
11856
11857 //wback = (m != 15); register_index = (m != 15 && m != 13);
11858 wback = (m != 15);
11859 register_index = ((m != 15) && (m != 13));
11860
11861 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11862 if ((d + regs) > 32)
11863 return false;
11864
11865 if (n == 15)
11866 return false;
11867 }
11868 break;
11869
11870 default:
11871 break;
11872 }
11873
Greg Claytonc07d4512011-04-26 23:48:45 +000011874 RegisterInfo base_reg;
11875 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice93767b82011-03-31 21:15:29 +000011876
11877 uint32_t Rn = ReadCoreReg (n, &success);
11878 if (!success)
11879 return false;
11880
11881 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11882 addr_t address = Rn;
11883 if ((address % alignment) != 0)
11884 return false;
11885
11886 EmulateInstruction::Context context;
11887 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11888 if (wback)
11889 {
11890 uint32_t Rm = ReadCoreReg (m, &success);
11891 if (!success)
11892 return false;
11893
11894 uint32_t offset;
11895 if (register_index)
11896 offset = Rm;
11897 else
11898 offset = ebytes;
11899
11900 context.type = eContextAdjustBaseRegister;
11901 context.SetRegisterPlusOffset (base_reg, offset);
11902
11903 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11904 return false;
11905 }
11906
11907 // replicated_element = Replicate(MemU[address,ebytes], elements);
11908
11909 context.type = eContextRegisterLoad;
11910 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11911 if (!success)
11912 return false;
11913
11914 uint64_t replicated_element;
11915 uint32_t esize = ebytes * 8;
11916 for (int e = 0; e < elements; ++e)
11917 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11918
11919 // for r = 0 to regs-1
11920 for (int r = 0; r < regs; ++r)
11921 {
11922 // D[d+r] = replicated_element;
11923 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11924 return false;
11925 }
11926 }
11927 return true;
11928}
11929
Caroline Tice1f954f52011-04-11 15:51:10 +000011930// B6.2.13 SUBS PC, LR and related instructions
11931//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
11932// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
11933bool
11934EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
11935{
11936#if 0
11937 if ConditionPassed() then
11938 EncodingSpecificOperations();
11939 if CurrentInstrSet() == InstrSet_ThumbEE then
11940 UNPREDICTABLE;
11941 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11942 case opcode of
Greg Clayton061b79d2011-05-09 20:18:18 +000011943 when Ô0000Õ result = R[n] AND operand2; // AND
11944 when Ô0001Õ result = R[n] EOR operand2; // EOR
11945 when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
11946 when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
11947 when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
11948 when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
11949 when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
11950 when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
11951 when Ô1100Õ result = R[n] OR operand2; // ORR
11952 when Ô1101Õ result = operand2; // MOV
11953 when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
11954 when Ô1111Õ result = NOT(operand2); // MVN
11955 CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000011956 BranchWritePC(result);
11957#endif
11958
11959 bool success = false;
11960
11961 if (ConditionPassed (opcode))
11962 {
11963 uint32_t n;
11964 uint32_t m;
11965 uint32_t imm32;
11966 bool register_form;
11967 ARM_ShifterType shift_t;
11968 uint32_t shift_n;
11969 uint32_t code;
11970
11971 switch (encoding)
11972 {
11973 case eEncodingT1:
11974 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
Greg Clayton061b79d2011-05-09 20:18:18 +000011975 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000011976 n = 14;
11977 imm32 = Bits32 (opcode, 7, 0);
11978 register_form = false;
11979 code = 2;
11980
11981 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
11982 if (InITBlock() && !LastInITBlock())
11983 return false;
11984
11985 break;
11986
11987 case eEncodingA1:
11988 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
11989 n = Bits32 (opcode, 19, 16);
11990 imm32 = ARMExpandImm (opcode);
11991 register_form = false;
11992 code = Bits32 (opcode, 24, 21);
11993
11994 break;
11995
11996 case eEncodingA2:
11997 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
11998 n = Bits32 (opcode, 19, 16);
11999 m = Bits32 (opcode, 3, 0);
12000 register_form = true;
12001
12002 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12003 shift_n = DecodeImmShiftARM (opcode, shift_t);
12004
12005 break;
12006
12007 default:
12008 return false;
12009 }
12010
12011 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12012 uint32_t operand2;
12013 if (register_form)
12014 {
12015 uint32_t Rm = ReadCoreReg (m, &success);
12016 if (!success)
12017 return false;
12018
12019 operand2 = Shift (Rm, shift_t, shift_n, APSR_C);
12020
12021 }
12022 else
12023 {
12024 operand2 = imm32;
12025 }
12026
12027 uint32_t Rn = ReadCoreReg (n, &success);
12028 if (!success)
12029 return false;
12030
12031 AddWithCarryResult result;
12032
12033 // case opcode of
12034 switch (code)
12035 {
Greg Clayton061b79d2011-05-09 20:18:18 +000012036 case 0: // when Ô0000Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012037 // result = R[n] AND operand2; // AND
12038 result.result = Rn & operand2;
12039 break;
12040
Greg Clayton061b79d2011-05-09 20:18:18 +000012041 case 1: // when Ô0001Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012042 // result = R[n] EOR operand2; // EOR
12043 result.result = Rn ^ operand2;
12044 break;
12045
Greg Clayton061b79d2011-05-09 20:18:18 +000012046 case 2: // when Ô0010Õ
12047 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012048 result = AddWithCarry (Rn, ~(operand2), 1);
12049 break;
12050
Greg Clayton061b79d2011-05-09 20:18:18 +000012051 case 3: // when Ô0011Õ
12052 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
Caroline Tice1f954f52011-04-11 15:51:10 +000012053 result = AddWithCarry (~(Rn), operand2, 1);
12054 break;
12055
Greg Clayton061b79d2011-05-09 20:18:18 +000012056 case 4: // when Ô0100Õ
12057 // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
Caroline Tice1f954f52011-04-11 15:51:10 +000012058 result = AddWithCarry (Rn, operand2, 0);
12059 break;
12060
Greg Clayton061b79d2011-05-09 20:18:18 +000012061 case 5: // when Ô0101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012062 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12063 result = AddWithCarry (Rn, operand2, APSR_C);
12064 break;
12065
Greg Clayton061b79d2011-05-09 20:18:18 +000012066 case 6: // when Ô0110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012067 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12068 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12069 break;
12070
Greg Clayton061b79d2011-05-09 20:18:18 +000012071 case 7: // when Ô0111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012072 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12073 result = AddWithCarry (~(Rn), operand2, APSR_C);
12074 break;
12075
Greg Clayton061b79d2011-05-09 20:18:18 +000012076 case 10: // when Ô1100Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012077 // result = R[n] OR operand2; // ORR
12078 result.result = Rn | operand2;
12079 break;
12080
Greg Clayton061b79d2011-05-09 20:18:18 +000012081 case 11: // when Ô1101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012082 // result = operand2; // MOV
12083 result.result = operand2;
12084 break;
12085
Greg Clayton061b79d2011-05-09 20:18:18 +000012086 case 12: // when Ô1110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012087 // result = R[n] AND NOT(operand2); // BIC
12088 result.result = Rn & ~(operand2);
12089 break;
12090
Greg Clayton061b79d2011-05-09 20:18:18 +000012091 case 15: // when Ô1111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012092 // result = NOT(operand2); // MVN
12093 result.result = ~(operand2);
12094 break;
12095
12096 default:
12097 return false;
12098 }
Greg Clayton061b79d2011-05-09 20:18:18 +000012099 // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012100
12101 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12102 // the best.
12103 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12104 if (!success)
12105 return false;
12106
12107 CPSRWriteByInstr (spsr, 15, true);
12108
12109 // BranchWritePC(result);
12110 EmulateInstruction::Context context;
12111 context.type = eContextAdjustPC;
12112 context.SetImmediate (result.result);
12113
12114 BranchWritePC (context, result.result);
12115 }
12116 return true;
12117}
12118
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012119EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012120EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012121{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012122 static ARMOpcode
12123 g_arm_opcodes[] =
12124 {
12125 //----------------------------------------------------------------------
12126 // Prologue instructions
12127 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012128
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012129 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012130 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12131 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012132
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012133 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012134 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12135 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012136 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012137 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12138 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12139 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012140
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012141 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012142 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12143 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012144
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012145 // push one register
12146 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012147 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012148
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012149 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012150 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12151 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012152
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012153 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012154 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012155 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012156
Caroline Tice4f605582011-03-31 00:02:51 +000012157 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12158 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12159 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12160 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012161
12162 //----------------------------------------------------------------------
12163 // Supervisor Call (previously Software Interrupt)
12164 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012165 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012166
12167 //----------------------------------------------------------------------
12168 // Branch instructions
12169 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012170 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012171 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012172 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12173 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12174 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012175 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012176 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012177 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012178 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012179
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012180 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012181 // Data-processing instructions
12182 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012183 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012184 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012185 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012186 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012187 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012188 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012189 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012190 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012191 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012192 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012193 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012194 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12195 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012196 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012197 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012198 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012199 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012200 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012201 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012202 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012203 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012204 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012205 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012206 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012207 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012208 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012209 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012210 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012211 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012212 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012213 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012214 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012215 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012216 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012217 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012218 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012219 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012220 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012221 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012222 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012223 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012224 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012225 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012226 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012227 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012228 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012229 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012230 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012231 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012232 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012233 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012234 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012235 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012236 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012237 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012238
Caroline Tice89c6d582011-03-29 19:53:44 +000012239 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012240 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12241 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012242 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012243 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012244 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012245 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012246 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012247 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012248 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012249 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012250 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012251 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012252 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012253 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012254 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012255 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012256 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012257 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012258 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012259 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012260 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012261 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012262 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012263 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012264 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012265 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012266 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012267 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012268 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012269 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012270 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012271 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012272 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012273 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012274 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012275 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012276
12277 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012278 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12279 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012280
12281 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012282 // Load instructions
12283 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012284 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12285 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12286 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12287 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12288 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12289 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12290 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12291 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12292 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12293 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12294 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12295 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12296 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12297 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12298 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12299 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12300 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12301 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012302 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12303 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12304 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12305 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012306 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12307 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012308 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012309
12310 //----------------------------------------------------------------------
12311 // Store instructions
12312 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012313 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12314 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12315 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12316 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12317 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12318 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12319 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12320 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12321 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012322 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012323 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012324 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12325 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12326 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12327 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12328 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012329 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012330
Caroline Tice6bf65162011-03-03 17:42:58 +000012331 //----------------------------------------------------------------------
12332 // Other instructions
12333 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012334 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12335 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12336 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12337 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12338 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012339
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012340 };
12341 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12342
12343 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12344 {
Greg Clayton888a7332011-04-26 04:39:08 +000012345 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12346 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012347 return &g_arm_opcodes[i];
12348 }
12349 return NULL;
12350}
Greg Clayton64c84432011-01-21 22:02:52 +000012351
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012352
12353EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012354EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012355{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012356
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012357 static ARMOpcode
12358 g_thumb_opcodes[] =
12359 {
12360 //----------------------------------------------------------------------
12361 // Prologue instructions
12362 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012363
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012364 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012365 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12366 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12367 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012368
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012369 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012370 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012371 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012372 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012373 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012374 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012375
Johnny Chen864a8e82011-02-18 00:07:39 +000012376 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012377 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012378
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012379 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012380 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12381 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12382 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12383 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12384 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012385
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012386 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012387 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12388 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012389
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012390 //----------------------------------------------------------------------
12391 // Epilogue instructions
12392 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012393
Caroline Tice4f605582011-03-31 00:02:51 +000012394 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12395 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12396 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12397 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12398 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12399 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12400 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012401
12402 //----------------------------------------------------------------------
12403 // Supervisor Call (previously Software Interrupt)
12404 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012405 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012406
12407 //----------------------------------------------------------------------
12408 // If Then makes up to four following instructions conditional.
12409 //----------------------------------------------------------------------
Greg Clayton04d397c2011-05-23 18:04:09 +000012410 // The next 5 opcode _must_ come before the if then instruction
12411 { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"},
12412 { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
12413 { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
12414 { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
12415 { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
12416 { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012417
12418 //----------------------------------------------------------------------
12419 // Branch instructions
12420 //----------------------------------------------------------------------
12421 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012422 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12423 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12424 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12425 { 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 +000012426 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012427 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012428 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012429 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12430 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012431 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012432 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012433 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012434 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012435 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012436 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012437 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012438 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012439 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012440 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012441
12442 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012443 // Data-processing instructions
12444 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012445 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012446 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012447 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012448 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12449 { 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 +000012450 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012451 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012452 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012453 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012454 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012455 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12456 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12457 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012458 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012459 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012460 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012461 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12462 { 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 +000012463 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012464 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012465 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012466 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12467 { 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 +000012468 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012469 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012470 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012471 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12472 { 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 +000012473 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012474 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012475 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012476 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12477 { 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 +000012478 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012479 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12480 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012481 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012482 { 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 +000012483 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012484 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012485 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012486 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12487 { 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 +000012488 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012489 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12490 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12491 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12492 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012493 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012494 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12495 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12496 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12497 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012498 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012499 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12500 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012501 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012502 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12503 { 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 +000012504 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012505 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012506 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012507 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012508 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012509 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012510 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012511 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12512 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012513
Johnny Chen7c5234d2011-02-18 23:41:11 +000012514
Johnny Chen338bf542011-02-10 19:29:03 +000012515 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012516 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012517 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012518 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012519 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012520 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012521 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012522 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12523 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12524 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012525 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012526 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012527 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012528 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12529 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012530 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012531 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012532 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012533 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12534 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012535 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012536 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12537 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012538 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012539 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012540 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012541 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012542 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012543 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12544 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012545 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012546 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12547 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012548 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012549 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12550 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012551 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012552 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12553 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012554 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012555 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12556 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012557 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012558 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12559 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012560 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012561 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012562 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012563 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012564 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012565 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12566 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012567 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012568 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012569 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012570 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012571
12572 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012573 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012574
12575 //----------------------------------------------------------------------
12576 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12577 // otherwise the wrong instructions will be selected.
12578 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012579
Caroline Tice080bf612011-04-05 18:46:00 +000012580 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12581 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12582
Johnny Chen26863dc2011-02-09 23:43:29 +000012583 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012584 // Load instructions
12585 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012586 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12587 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12588 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12589 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12590 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12591 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12592 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012593 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012594 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12595 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12596 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12597 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12598 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012599 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012600 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12601 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12602 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12603 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12604 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12605 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12606 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12607 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12608 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12609 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12610 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12611 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12612 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12613 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12614 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12615 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12616 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12617 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12618 { 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 +000012619 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012620 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12621 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12622 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12623 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012624 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12625 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012626 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012627
12628 //----------------------------------------------------------------------
12629 // Store instructions
12630 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012631 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12632 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12633 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12634 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12635 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12636 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12637 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12638 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12639 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12640 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12641 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12642 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12643 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12644 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12645 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12646 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012647 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12648 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12649 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12650 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12651 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012652 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012653
12654 //----------------------------------------------------------------------
12655 // Other instructions
12656 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012657 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12658 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12659 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12660 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12661 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12662 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12663 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12664 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012665 };
12666
12667 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12668 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12669 {
Greg Clayton888a7332011-04-26 04:39:08 +000012670 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12671 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012672 return &g_thumb_opcodes[i];
12673 }
12674 return NULL;
12675}
Greg Clayton64c84432011-01-21 22:02:52 +000012676
Greg Clayton31e2a382011-01-30 20:03:56 +000012677bool
Greg Clayton395fc332011-02-15 21:59:32 +000012678EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012679{
Caroline Tice080bf612011-04-05 18:46:00 +000012680 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012681 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012682 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012683 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012684 {
Greg Clayton395fc332011-02-15 21:59:32 +000012685 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12686 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12687 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12688 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12689 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12690 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12691 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12692 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12693 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12694 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Johnny Chen1d29a852011-04-26 18:51:57 +000012695 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12696 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
Greg Clayton31e2a382011-01-30 20:03:56 +000012697 }
12698 return m_arm_isa != 0;
12699}
12700
Caroline Tice080bf612011-04-05 18:46:00 +000012701bool
Greg Clayton888a7332011-04-26 04:39:08 +000012702EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012703{
Greg Clayton888a7332011-04-26 04:39:08 +000012704 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12705 {
12706 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12707 m_opcode_mode = eModeThumb;
12708 else
12709 {
12710 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012711
Greg Clayton888a7332011-04-26 04:39:08 +000012712 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12713 m_opcode_mode = eModeARM;
12714 else if (addr_class == eAddressClassCodeAlternateISA)
12715 m_opcode_mode = eModeThumb;
12716 else
12717 return false;
12718 }
12719 if (m_opcode_mode == eModeThumb)
12720 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12721 else
12722 m_opcode_cpsr = CPSR_MODE_USR;
12723 return true;
12724 }
12725 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012726}
Greg Clayton31e2a382011-01-30 20:03:56 +000012727
Greg Clayton64c84432011-01-21 22:02:52 +000012728bool
12729EmulateInstructionARM::ReadInstruction ()
12730{
12731 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012732 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012733 if (success)
12734 {
12735 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12736 if (success)
12737 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012738 Context read_inst_context;
12739 read_inst_context.type = eContextReadOpcode;
12740 read_inst_context.SetNoArgs ();
12741
Greg Claytonb3448432011-03-24 21:19:54 +000012742 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012743 {
Greg Claytonb3448432011-03-24 21:19:54 +000012744 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012745 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012746
12747 if (success)
12748 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012749 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012750 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012751 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012752 }
12753 else
12754 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012755 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012756 }
12757 }
12758 }
12759 else
12760 {
Greg Claytonb3448432011-03-24 21:19:54 +000012761 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012762 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012763 }
12764 }
12765 }
12766 if (!success)
12767 {
Greg Claytonb3448432011-03-24 21:19:54 +000012768 m_opcode_mode = eModeInvalid;
Greg Clayton3063c952011-04-29 22:50:31 +000012769 m_addr = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012770 }
12771 return success;
12772}
12773
Johnny Chenee9b1f72011-02-09 01:00:31 +000012774uint32_t
12775EmulateInstructionARM::ArchVersion ()
12776{
12777 return m_arm_isa;
12778}
12779
Greg Clayton64c84432011-01-21 22:02:52 +000012780bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012781EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012782{
Greg Clayton888a7332011-04-26 04:39:08 +000012783 // If we are ignoring conditions, then always return true.
12784 // this allows us to iterate over disassembly code and still
12785 // emulate an instruction even if we don't have all the right
12786 // bits set in the CPSR register...
12787 if (m_ignore_conditions)
12788 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000012789
Greg Clayton7bc39082011-03-24 23:53:38 +000012790 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012791
12792 if (cond == UINT32_MAX)
12793 return false;
12794
12795 bool result = false;
12796 switch (UnsignedBits(cond, 3, 1))
12797 {
Caroline Tice080bf612011-04-05 18:46:00 +000012798 case 0:
12799 if (m_opcode_cpsr == 0)
12800 return true;
12801 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12802 break;
12803 case 1:
12804 if (m_opcode_cpsr == 0)
12805 return true;
12806 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12807 break;
12808 case 2:
12809 if (m_opcode_cpsr == 0)
12810 return true;
12811 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12812 break;
12813 case 3:
12814 if (m_opcode_cpsr == 0)
12815 return true;
12816 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12817 break;
12818 case 4:
12819 if (m_opcode_cpsr == 0)
12820 return true;
12821 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12822 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012823 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012824 if (m_opcode_cpsr == 0)
12825 return true;
12826 else
12827 {
Greg Claytonb3448432011-03-24 21:19:54 +000012828 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12829 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012830 result = n == v;
12831 }
12832 break;
12833 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012834 if (m_opcode_cpsr == 0)
12835 return true;
12836 else
12837 {
Greg Claytonb3448432011-03-24 21:19:54 +000012838 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12839 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12840 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012841 }
12842 break;
12843 case 7:
12844 result = true;
12845 break;
12846 }
12847
12848 if (cond & 1)
12849 result = !result;
12850 return result;
12851}
12852
Johnny Chen9ee056b2011-02-08 00:06:35 +000012853uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012854EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012855{
Greg Claytonb3448432011-03-24 21:19:54 +000012856 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012857 {
12858 default:
12859 case eModeInvalid:
12860 break;
12861
12862 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012863 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012864
12865 case eModeThumb:
12866 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12867 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012868 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012869 const uint32_t byte_size = m_opcode.GetByteSize();
12870 if (byte_size == 2)
12871 {
12872 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12873 return Bits32(opcode, 11, 7);
12874 }
12875 else
12876 {
12877 assert (byte_size == 4);
12878 if (Bits32(opcode, 31, 27) == 0x1e &&
12879 Bits32(opcode, 15, 14) == 0x02 &&
12880 Bits32(opcode, 12, 12) == 0x00 &&
12881 Bits32(opcode, 25, 22) <= 0x0d)
12882 {
12883 return Bits32(opcode, 25, 22);
12884 }
12885 }
12886
12887 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012888 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012889 }
12890 return UINT32_MAX; // Return invalid value
12891}
12892
Johnny Chen9ee056b2011-02-08 00:06:35 +000012893bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012894EmulateInstructionARM::InITBlock()
12895{
12896 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12897}
12898
12899bool
12900EmulateInstructionARM::LastInITBlock()
12901{
12902 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12903}
12904
Caroline Ticeb27771d2011-03-03 22:37:46 +000012905bool
12906EmulateInstructionARM::BadMode (uint32_t mode)
12907{
12908
12909 switch (mode)
12910 {
12911 case 16: return false; // '10000'
12912 case 17: return false; // '10001'
12913 case 18: return false; // '10010'
12914 case 19: return false; // '10011'
12915 case 22: return false; // '10110'
12916 case 23: return false; // '10111'
12917 case 27: return false; // '11011'
12918 case 31: return false; // '11111'
12919 default: return true;
12920 }
12921 return true;
12922}
12923
12924bool
12925EmulateInstructionARM::CurrentModeIsPrivileged ()
12926{
Greg Claytonb3448432011-03-24 21:19:54 +000012927 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012928
12929 if (BadMode (mode))
12930 return false;
12931
12932 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000012933 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012934
12935 return true;
12936}
12937
12938void
12939EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
12940{
12941 bool privileged = CurrentModeIsPrivileged();
12942
12943 uint32_t tmp_cpsr = 0;
12944
Greg Claytonb3448432011-03-24 21:19:54 +000012945 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012946
12947 if (BitIsSet (bytemask, 3))
12948 {
12949 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
12950 if (affect_execstate)
12951 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
12952 }
12953
12954 if (BitIsSet (bytemask, 2))
12955 {
12956 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
12957 }
12958
12959 if (BitIsSet (bytemask, 1))
12960 {
12961 if (affect_execstate)
12962 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
12963 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
12964 if (privileged)
12965 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
12966 }
12967
12968 if (BitIsSet (bytemask, 0))
12969 {
12970 if (privileged)
12971 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
12972 if (affect_execstate)
12973 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
12974 if (privileged)
12975 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
12976 }
12977
Greg Claytonb3448432011-03-24 21:19:54 +000012978 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012979}
12980
12981
Johnny Chen098ae2d2011-02-12 00:50:05 +000012982bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000012983EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
12984{
12985 addr_t target;
12986
Johnny Chenee9b1f72011-02-09 01:00:31 +000012987 // Check the current instruction set.
12988 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012989 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012990 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000012991 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012992
Johnny Chen9ee056b2011-02-08 00:06:35 +000012993 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012994 return false;
12995
12996 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012997}
12998
12999// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
13000bool
Johnny Chen668b4512011-02-15 21:08:58 +000013001EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013002{
13003 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000013004 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
13005 // we want to record it and issue a WriteRegister callback so the clients
13006 // can track the mode changes accordingly.
13007 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013008
13009 if (BitIsSet(addr, 0))
13010 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013011 if (CurrentInstrSet() != eModeThumb)
13012 {
13013 SelectInstrSet(eModeThumb);
13014 cpsr_changed = true;
13015 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013016 target = addr & 0xfffffffe;
Greg Claytonc07d4512011-04-26 23:48:45 +000013017 context.SetISA (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013018 }
13019 else if (BitIsClear(addr, 1))
13020 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013021 if (CurrentInstrSet() != eModeARM)
13022 {
13023 SelectInstrSet(eModeARM);
13024 cpsr_changed = true;
13025 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013026 target = addr & 0xfffffffc;
Greg Claytonc07d4512011-04-26 23:48:45 +000013027 context.SetISA (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013028 }
13029 else
13030 return false; // address<1:0> == '10' => UNPREDICTABLE
13031
Johnny Chen0f309db2011-02-09 19:11:32 +000013032 if (cpsr_changed)
13033 {
Johnny Chen558133b2011-02-09 23:59:17 +000013034 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000013035 return false;
13036 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013037 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013038 return false;
13039
13040 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013041}
Greg Clayton64c84432011-01-21 22:02:52 +000013042
Johnny Chenee9b1f72011-02-09 01:00:31 +000013043// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13044bool
Johnny Chen668b4512011-02-15 21:08:58 +000013045EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000013046{
13047 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000013048 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000013049 else
13050 return BranchWritePC((const Context)context, addr);
13051}
13052
Johnny Chen26863dc2011-02-09 23:43:29 +000013053// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13054bool
Johnny Chen668b4512011-02-15 21:08:58 +000013055EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000013056{
13057 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013058 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013059 else
13060 return BranchWritePC((const Context)context, addr);
13061}
13062
Johnny Chenee9b1f72011-02-09 01:00:31 +000013063EmulateInstructionARM::Mode
13064EmulateInstructionARM::CurrentInstrSet ()
13065{
Greg Claytonb3448432011-03-24 21:19:54 +000013066 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013067}
13068
Greg Claytonb3448432011-03-24 21:19:54 +000013069// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013070// ReadInstruction() is performed. This function has a side effect of updating
13071// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013072bool
13073EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13074{
Greg Claytonb3448432011-03-24 21:19:54 +000013075 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013076 switch (arm_or_thumb)
13077 {
13078 default:
13079 return false;
13080 eModeARM:
13081 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013082 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013083 break;
13084 eModeThumb:
13085 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013086 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013087 break;
13088 }
13089 return true;
13090}
13091
Johnny Chenef21b592011-02-10 01:52:38 +000013092// This function returns TRUE if the processor currently provides support for
13093// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13094// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13095bool
13096EmulateInstructionARM::UnalignedSupport()
13097{
13098 return (ArchVersion() >= ARMv7);
13099}
13100
Johnny Chenbf6ad172011-02-11 01:29:53 +000013101// The main addition and subtraction instructions can produce status information
13102// about both unsigned carry and signed overflow conditions. This status
13103// information can be used to synthesize multi-word additions and subtractions.
13104EmulateInstructionARM::AddWithCarryResult
13105EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13106{
13107 uint32_t result;
13108 uint8_t carry_out;
13109 uint8_t overflow;
13110
13111 uint64_t unsigned_sum = x + y + carry_in;
13112 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13113
13114 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013115// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013116 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013117
13118 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013119 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013120 else
13121 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013122
13123 AddWithCarryResult res = { result, carry_out, overflow };
13124 return res;
13125}
13126
Johnny Chen157b9592011-02-18 21:13:05 +000013127uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013128EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013129{
Johnny Chene39f22d2011-02-19 01:36:13 +000013130 uint32_t reg_kind, reg_num;
13131 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013132 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013133 case SP_REG:
13134 reg_kind = eRegisterKindGeneric;
13135 reg_num = LLDB_REGNUM_GENERIC_SP;
13136 break;
13137 case LR_REG:
13138 reg_kind = eRegisterKindGeneric;
13139 reg_num = LLDB_REGNUM_GENERIC_RA;
13140 break;
13141 case PC_REG:
13142 reg_kind = eRegisterKindGeneric;
13143 reg_num = LLDB_REGNUM_GENERIC_PC;
13144 break;
13145 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013146 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013147 {
13148 reg_kind = eRegisterKindDWARF;
13149 reg_num = dwarf_r0 + num;
13150 }
Johnny Chen157b9592011-02-18 21:13:05 +000013151 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013152 {
13153 assert(0 && "Invalid register number");
13154 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013155 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013156 }
13157 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013158 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013159
13160 // Read our register.
13161 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13162
13163 // When executing an ARM instruction , PC reads as the address of the current
13164 // instruction plus 8.
13165 // When executing a Thumb instruction , PC reads as the address of the current
13166 // instruction plus 4.
13167 if (num == 15)
13168 {
13169 if (CurrentInstrSet() == eModeARM)
13170 val += 8;
13171 else
13172 val += 4;
13173 }
Johnny Chen157b9592011-02-18 21:13:05 +000013174
13175 return val;
13176}
13177
Johnny Chenca67d1c2011-02-17 01:35:27 +000013178// Write the result to the ARM core register Rd, and optionally update the
13179// condition flags based on the result.
13180//
13181// This helper method tries to encapsulate the following pseudocode from the
13182// ARM Architecture Reference Manual:
13183//
13184// if d == 15 then // Can only occur for encoding A1
13185// ALUWritePC(result); // setflags is always FALSE here
13186// else
13187// R[d] = result;
13188// if setflags then
13189// APSR.N = result<31>;
13190// APSR.Z = IsZeroBit(result);
13191// APSR.C = carry;
13192// // APSR.V unchanged
13193//
13194// In the above case, the API client does not pass in the overflow arg, which
13195// defaults to ~0u.
13196bool
Johnny Chen10530c22011-02-17 22:37:12 +000013197EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13198 const uint32_t result,
13199 const uint32_t Rd,
13200 bool setflags,
13201 const uint32_t carry,
13202 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013203{
13204 if (Rd == 15)
13205 {
13206 if (!ALUWritePC (context, result))
13207 return false;
13208 }
13209 else
13210 {
Johnny Chena695f952011-02-23 21:24:25 +000013211 uint32_t reg_kind, reg_num;
13212 switch (Rd)
13213 {
13214 case SP_REG:
13215 reg_kind = eRegisterKindGeneric;
13216 reg_num = LLDB_REGNUM_GENERIC_SP;
13217 break;
13218 case LR_REG:
13219 reg_kind = eRegisterKindGeneric;
13220 reg_num = LLDB_REGNUM_GENERIC_RA;
13221 break;
13222 default:
13223 reg_kind = eRegisterKindDWARF;
13224 reg_num = dwarf_r0 + Rd;
13225 }
13226 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013227 return false;
13228 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013229 return WriteFlags (context, result, carry, overflow);
13230 }
13231 return true;
13232}
13233
13234// This helper method tries to encapsulate the following pseudocode from the
13235// ARM Architecture Reference Manual:
13236//
13237// APSR.N = result<31>;
13238// APSR.Z = IsZeroBit(result);
13239// APSR.C = carry;
13240// APSR.V = overflow
13241//
13242// Default arguments can be specified for carry and overflow parameters, which means
13243// not to update the respective flags.
13244bool
13245EmulateInstructionARM::WriteFlags (Context &context,
13246 const uint32_t result,
13247 const uint32_t carry,
13248 const uint32_t overflow)
13249{
Greg Claytonb3448432011-03-24 21:19:54 +000013250 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013251 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13252 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013253 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013254 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013255 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013256 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013257 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013258 {
13259 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13260 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013261 }
13262 return true;
13263}
13264
Greg Clayton64c84432011-01-21 22:02:52 +000013265bool
Greg Clayton888a7332011-04-26 04:39:08 +000013266EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013267{
Johnny Chenc315f862011-02-05 00:46:10 +000013268 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013269 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013270 m_it_session.ITAdvance();
13271
Greg Clayton888a7332011-04-26 04:39:08 +000013272 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013273
13274 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013275 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013276 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013277 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13278
13279 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013280 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013281
Greg Clayton888a7332011-04-26 04:39:08 +000013282 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13283 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013284
Greg Clayton888a7332011-04-26 04:39:08 +000013285 bool success = false;
13286 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013287 {
Greg Clayton888a7332011-04-26 04:39:08 +000013288 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
Greg Clayton061b79d2011-05-09 20:18:18 +000013289 dwarf_cpsr,
13290 0,
13291 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013292 }
13293
Greg Clayton888a7332011-04-26 04:39:08 +000013294 // Only return false if we are unable to read the CPSR if we care about conditions
13295 if (success == false && m_ignore_conditions == false)
13296 return false;
13297
13298 uint32_t orig_pc_value = 0;
13299 if (auto_advance_pc)
13300 {
13301 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13302 if (!success)
13303 return false;
13304 }
13305
13306 // Call the Emulate... function.
13307 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13308 if (!success)
13309 return false;
13310
13311 if (auto_advance_pc)
13312 {
13313 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13314 if (!success)
13315 return false;
13316
13317 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13318 {
13319 if (opcode_data->size == eSize32)
13320 after_pc_value += 4;
13321 else if (opcode_data->size == eSize16)
13322 after_pc_value += 2;
13323
13324 EmulateInstruction::Context context;
13325 context.type = eContextAdvancePC;
13326 context.SetNoArgs();
13327 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13328 return false;
13329
13330 }
13331 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013332 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013333}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013334
13335bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013336EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013337{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013338 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013339 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013340 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013341 return false;
13342 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013343
13344 static ConstString opcode_key ("opcode");
13345 static ConstString before_key ("before_state");
13346 static ConstString after_key ("after_state");
13347
13348 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013349
13350 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013351 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013352 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013353 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013354 return false;
13355 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013356 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013357
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013358 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13359 {
13360 m_opcode_mode = eModeARM;
13361 m_opcode.SetOpcode32 (test_opcode);
13362 }
13363 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13364 {
13365 m_opcode_mode = eModeThumb;
13366 if (test_opcode < 0x10000)
13367 m_opcode.SetOpcode16 (test_opcode);
13368 else
13369 m_opcode.SetOpcode32 (test_opcode);
13370
13371 }
13372 else
13373 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013374 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013375 return false;
13376 }
13377
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013378 EmulationStateARM before_state;
13379 EmulationStateARM after_state;
13380
Caroline Ticedfb2e202011-04-22 05:08:45 +000013381 value_sp = test_data->GetValueForKey (before_key);
13382 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013383 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013384 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013385 return false;
13386 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013387
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013388 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013389 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013390 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013391 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013392 return false;
13393 }
13394
Caroline Ticedfb2e202011-04-22 05:08:45 +000013395 value_sp = test_data->GetValueForKey (after_key);
13396 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013397 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013398 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013399 return false;
13400 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013401
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013402 state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013403 if (!after_state.LoadStateFromDictionary (state_dictionary))
13404 {
13405 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13406 return false;
13407 }
13408
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013409 SetBaton ((void *) &before_state);
13410 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13411 &EmulationStateARM::WritePseudoMemory,
13412 &EmulationStateARM::ReadPseudoRegister,
13413 &EmulationStateARM::WritePseudoRegister);
13414
Greg Clayton888a7332011-04-26 04:39:08 +000013415 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013416 if (!success)
13417 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013418 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013419 return false;
13420 }
13421
13422 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013423 if (!success)
13424 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13425
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013426 return success;
13427}
Greg Claytonc07d4512011-04-26 23:48:45 +000013428//
13429//
13430//const char *
13431//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13432//{
13433// if (reg_kind == eRegisterKindGeneric)
13434// {
13435// switch (reg_num)
13436// {
13437// case LLDB_REGNUM_GENERIC_PC: return "pc";
13438// case LLDB_REGNUM_GENERIC_SP: return "sp";
13439// case LLDB_REGNUM_GENERIC_FP: return "fp";
13440// case LLDB_REGNUM_GENERIC_RA: return "lr";
13441// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13442// default: return NULL;
13443// }
13444// }
13445// else if (reg_kind == eRegisterKindDWARF)
13446// {
13447// return GetARMDWARFRegisterName (reg_num);
13448// }
13449// return NULL;
13450//}
13451//
13452bool
13453EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
Greg Clayton888a7332011-04-26 04:39:08 +000013454{
Greg Clayton75906e42011-05-11 18:39:18 +000013455 unwind_plan.Clear();
Greg Claytonc07d4512011-04-26 23:48:45 +000013456 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13457
13458 UnwindPlan::Row row;
Greg Claytonc07d4512011-04-26 23:48:45 +000013459
13460 // Our previous Call Frame Address is the stack pointer
13461 row.SetCFARegister (dwarf_sp);
13462
13463 // Our previous PC is in the LR
Greg Clayton75906e42011-05-11 18:39:18 +000013464 row.SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
Greg Claytonc07d4512011-04-26 23:48:45 +000013465 unwind_plan.AppendRow (row);
13466
13467 // All other registers are the same.
13468
13469 unwind_plan.SetSourceName ("EmulateInstructionARM");
13470 return true;
Greg Clayton888a7332011-04-26 04:39:08 +000013471}
13472
Greg Claytonc07d4512011-04-26 23:48:45 +000013473
13474
13475