blob: f79f7d28e6652d579d32d97d59b8f6ed30dfaab2 [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{
Greg Claytone1f47bb2011-06-02 22:23:35 +000084 //assert(ITCounter);
Johnny Chen93070472011-02-04 23:02:47 +000085 --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
Johnny Chena4438a72011-06-02 22:50:51 +00001124 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1125 if (!success)
1126 return false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001127 uint32_t result = ~shifted;
1128
1129 // The context specifies that an immediate is to be moved into Rd.
1130 EmulateInstruction::Context context;
1131 context.type = EmulateInstruction::eContextImmediate;
1132 context.SetNoArgs ();
1133
1134 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1135 return false;
1136 }
1137 return true;
1138}
1139
Johnny Chen788e0552011-01-27 22:52:23 +00001140// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1141// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001142bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001143EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001144{
1145#if 0
1146 // ARM pseudo code...
1147 if (ConditionPassed())
1148 {
1149 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1150 base = Align(PC,4);
1151 address = if add then (base + imm32) else (base - imm32);
1152 data = MemU[address,4];
1153 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001154 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1155 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001156 R[t] = data;
1157 else // Can only apply before ARMv7
1158 if CurrentInstrSet() == InstrSet_ARM then
1159 R[t] = ROR(data, 8*UInt(address<1:0>));
1160 else
1161 R[t] = bits(32) UNKNOWN;
1162 }
1163#endif
1164
Greg Clayton7bc39082011-03-24 23:53:38 +00001165 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001166 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001167 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001168 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001169 if (!success)
1170 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001171
1172 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001173 EmulateInstruction::Context context;
1174 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001175 RegisterInfo pc_reg;
1176 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001177 context.SetRegisterPlusOffset (pc_reg, 0);
1178
Johnny Chenc9de9102011-02-11 19:12:30 +00001179 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001180 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001181 bool add; // +imm32 or -imm32?
1182 addr_t base; // the base address
1183 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001184 uint32_t data; // the literal data value from the PC relative load
1185 switch (encoding) {
1186 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001187 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001188 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001189 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001190 break;
1191 case eEncodingT2:
1192 Rt = Bits32(opcode, 15, 12);
1193 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1194 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001195 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001196 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001197 break;
1198 default:
1199 return false;
1200 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001201
Johnny Chene39f22d2011-02-19 01:36:13 +00001202 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001203 if (add)
1204 address = base + imm32;
1205 else
1206 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001207
1208 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001209 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001210 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001211 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001212
1213 if (Rt == 15)
1214 {
1215 if (Bits32(address, 1, 0) == 0)
1216 {
1217 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001218 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001219 return false;
1220 }
1221 else
1222 return false;
1223 }
1224 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1225 {
1226 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1227 return false;
1228 }
1229 else // We don't handle ARM for now.
1230 return false;
1231
Johnny Chen788e0552011-01-27 22:52:23 +00001232 }
1233 return true;
1234}
1235
Johnny Chen5b442b72011-01-27 19:34:30 +00001236// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001237// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001238bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001239EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001240{
1241#if 0
1242 // ARM pseudo code...
1243 if (ConditionPassed())
1244 {
1245 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001246 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001247 if d == 15 then // Can only occur for ARM encoding
1248 ALUWritePC(result); // setflags is always FALSE here
1249 else
1250 R[d] = result;
1251 if setflags then
1252 APSR.N = result<31>;
1253 APSR.Z = IsZeroBit(result);
1254 APSR.C = carry;
1255 APSR.V = overflow;
1256 }
1257#endif
1258
1259 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001260
Greg Clayton7bc39082011-03-24 23:53:38 +00001261 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001262 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001263 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001264 if (!success)
1265 return false;
1266 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001267 uint32_t d;
1268 bool setflags;
1269 switch (encoding)
1270 {
1271 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001272 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001273 d = Bits32 (opcode, 10, 8);
1274 setflags = false;
1275 imm32 = (Bits32 (opcode, 7, 0) << 2);
1276
1277 break;
1278
1279 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001280 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001281 d = 13;
1282 setflags = false;
1283 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1284
1285 break;
1286
1287 default:
1288 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001289 }
1290 addr_t sp_offset = imm32;
1291 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1292
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001293 EmulateInstruction::Context context;
1294 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +00001295 RegisterInfo sp_reg;
1296 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001297 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001298
Caroline Ticee2212882011-03-22 22:38:28 +00001299 if (d == 15)
1300 {
1301 if (!ALUWritePC (context, addr))
1302 return false;
1303 }
1304 else
1305 {
1306 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1307 return false;
1308 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001309 }
1310 return true;
1311}
1312
1313// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001314// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001315bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001316EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001317{
1318#if 0
1319 // ARM pseudo code...
1320 if (ConditionPassed())
1321 {
1322 EncodingSpecificOperations();
1323 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001324 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001325 if d == 15 then
1326 ALUWritePC(result); // setflags is always FALSE here
1327 else
1328 R[d] = result;
1329 if setflags then
1330 APSR.N = result<31>;
1331 APSR.Z = IsZeroBit(result);
1332 APSR.C = carry;
1333 APSR.V = overflow;
1334 }
1335#endif
1336
1337 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001338
Greg Clayton7bc39082011-03-24 23:53:38 +00001339 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001340 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001341 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001342 if (!success)
1343 return false;
1344 uint32_t Rm; // the second operand
1345 switch (encoding) {
1346 case eEncodingT2:
1347 Rm = Bits32(opcode, 6, 3);
1348 break;
1349 default:
1350 return false;
1351 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001352 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001353 if (!success)
1354 return false;
1355
1356 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1357
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001358 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00001359 context.type = eContextArithmetic;
1360 RegisterInfo sp_reg;
1361 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1362
1363 RegisterInfo other_reg;
1364 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001365 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001366
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001367 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001368 return false;
1369 }
1370 return true;
1371}
1372
Johnny Chen9b8d7832011-02-02 01:13:56 +00001373// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1374// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1375// from Thumb to ARM.
1376// BLX (immediate)
1377bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001378EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001379{
1380#if 0
1381 // ARM pseudo code...
1382 if (ConditionPassed())
1383 {
1384 EncodingSpecificOperations();
1385 if CurrentInstrSet() == InstrSet_ARM then
1386 LR = PC - 4;
1387 else
1388 LR = PC<31:1> : '1';
1389 if targetInstrSet == InstrSet_ARM then
1390 targetAddress = Align(PC,4) + imm32;
1391 else
1392 targetAddress = PC + imm32;
1393 SelectInstrSet(targetInstrSet);
1394 BranchWritePC(targetAddress);
1395 }
1396#endif
1397
Greg Clayton7bc39082011-03-24 23:53:38 +00001398 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001399
Greg Clayton7bc39082011-03-24 23:53:38 +00001400 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001401 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001402 EmulateInstruction::Context context;
1403 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001404 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001405 if (!success)
1406 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001407 addr_t lr; // next instruction address
1408 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001409 int32_t imm32; // PC-relative offset
1410 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001411 case eEncodingT1:
1412 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001413 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001414 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001415 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001416 uint32_t J1 = Bit32(opcode, 13);
1417 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001418 uint32_t imm11 = Bits32(opcode, 10, 0);
1419 uint32_t I1 = !(J1 ^ S);
1420 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001421 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001422 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001423 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001424 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001425 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001426 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001427 break;
1428 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001429 case eEncodingT2:
1430 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001431 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001432 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001433 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001434 uint32_t J1 = Bit32(opcode, 13);
1435 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001436 uint32_t imm10L = Bits32(opcode, 10, 1);
1437 uint32_t I1 = !(J1 ^ S);
1438 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001439 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001440 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001441 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001442 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001443 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001444 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001445 break;
1446 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001447 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001448 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001449 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001450 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001451 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001452 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001453 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001454 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001455 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001456 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001457 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001458 break;
1459 default:
1460 return false;
1461 }
1462 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1463 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001464 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001465 return false;
1466 }
1467 return true;
1468}
1469
1470// Branch with Link and Exchange (register) calls a subroutine at an address and
1471// instruction set specified by a register.
1472// BLX (register)
1473bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001474EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001475{
1476#if 0
1477 // ARM pseudo code...
1478 if (ConditionPassed())
1479 {
1480 EncodingSpecificOperations();
1481 target = R[m];
1482 if CurrentInstrSet() == InstrSet_ARM then
1483 next_instr_addr = PC - 4;
1484 LR = next_instr_addr;
1485 else
1486 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001487 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001488 BXWritePC(target);
1489 }
1490#endif
1491
1492 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001493
Greg Clayton7bc39082011-03-24 23:53:38 +00001494 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001495 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001496 EmulateInstruction::Context context;
1497 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001498 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001499 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001500 if (!success)
1501 return false;
1502 uint32_t Rm; // the register with the target address
1503 switch (encoding) {
1504 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001505 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001506 Rm = Bits32(opcode, 6, 3);
1507 // if m == 15 then UNPREDICTABLE;
1508 if (Rm == 15)
1509 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001510 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001511 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001512 break;
1513 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001514 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001515 Rm = Bits32(opcode, 3, 0);
1516 // if m == 15 then UNPREDICTABLE;
1517 if (Rm == 15)
1518 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001519 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001520 default:
1521 return false;
1522 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001523 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001524 if (!success)
1525 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001526 RegisterInfo dwarf_reg;
1527 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001528 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001529 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1530 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001531 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001532 return false;
1533 }
1534 return true;
1535}
1536
Johnny Chenab3b3512011-02-12 00:10:51 +00001537// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001538bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001539EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001540{
1541#if 0
1542 // ARM pseudo code...
1543 if (ConditionPassed())
1544 {
1545 EncodingSpecificOperations();
1546 BXWritePC(R[m]);
1547 }
1548#endif
1549
Greg Clayton7bc39082011-03-24 23:53:38 +00001550 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001551 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001552 EmulateInstruction::Context context;
1553 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001554 uint32_t Rm; // the register with the target address
1555 switch (encoding) {
1556 case eEncodingT1:
1557 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001558 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001559 return false;
1560 break;
1561 case eEncodingA1:
1562 Rm = Bits32(opcode, 3, 0);
1563 break;
1564 default:
1565 return false;
1566 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001567 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001568 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001569 if (!success)
1570 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001571
1572 RegisterInfo dwarf_reg;
1573 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen668b4512011-02-15 21:08:58 +00001574 context.SetRegister (dwarf_reg);
1575 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001576 return false;
1577 }
1578 return true;
1579}
1580
Johnny Chen59e6ab72011-02-24 21:01:20 +00001581// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1582// address and instruction set specified by a register as though it were a BX instruction.
1583//
1584// TODO: Emulate Jazelle architecture?
1585// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1586bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001587EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001588{
1589#if 0
1590 // ARM pseudo code...
1591 if (ConditionPassed())
1592 {
1593 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001594 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001595 BXWritePC(R[m]);
1596 else
1597 if JazelleAcceptsExecution() then
1598 SwitchToJazelleExecution();
1599 else
1600 SUBARCHITECTURE_DEFINED handler call;
1601 }
1602#endif
1603
Greg Clayton7bc39082011-03-24 23:53:38 +00001604 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001605 {
1606 EmulateInstruction::Context context;
1607 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1608 uint32_t Rm; // the register with the target address
1609 switch (encoding) {
1610 case eEncodingT1:
1611 Rm = Bits32(opcode, 19, 16);
1612 if (BadReg(Rm))
1613 return false;
1614 if (InITBlock() && !LastInITBlock())
1615 return false;
1616 break;
1617 case eEncodingA1:
1618 Rm = Bits32(opcode, 3, 0);
1619 if (Rm == 15)
1620 return false;
1621 break;
1622 default:
1623 return false;
1624 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001625 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001626 addr_t target = ReadCoreReg (Rm, &success);
1627 if (!success)
1628 return false;
1629
Greg Claytonc07d4512011-04-26 23:48:45 +00001630 RegisterInfo dwarf_reg;
1631 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen59e6ab72011-02-24 21:01:20 +00001632 context.SetRegister (dwarf_reg);
1633 if (!BXWritePC(context, target))
1634 return false;
1635 }
1636 return true;
1637}
1638
Johnny Chen0d0148e2011-01-28 02:26:08 +00001639// Set r7 to point to some ip offset.
1640// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001641bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001642EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001643{
1644#if 0
1645 // ARM pseudo code...
1646 if (ConditionPassed())
1647 {
1648 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001649 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001650 if d == 15 then // Can only occur for ARM encoding
1651 ALUWritePC(result); // setflags is always FALSE here
1652 else
1653 R[d] = result;
1654 if setflags then
1655 APSR.N = result<31>;
1656 APSR.Z = IsZeroBit(result);
1657 APSR.C = carry;
1658 APSR.V = overflow;
1659 }
1660#endif
1661
Greg Clayton7bc39082011-03-24 23:53:38 +00001662 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001663 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001664 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001665 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001666 if (!success)
1667 return false;
1668 uint32_t imm32;
1669 switch (encoding) {
1670 case eEncodingA1:
1671 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1672 break;
1673 default:
1674 return false;
1675 }
1676 addr_t ip_offset = imm32;
1677 addr_t addr = ip - ip_offset; // the adjusted ip value
1678
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001679 EmulateInstruction::Context context;
1680 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001681 RegisterInfo dwarf_reg;
1682 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001683 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001684
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001685 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001686 return false;
1687 }
1688 return true;
1689}
1690
1691// Set ip to point to some stack offset.
1692// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001693bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001694EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001695{
1696#if 0
1697 // ARM pseudo code...
1698 if (ConditionPassed())
1699 {
1700 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001701 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001702 if d == 15 then // Can only occur for ARM encoding
1703 ALUWritePC(result); // setflags is always FALSE here
1704 else
1705 R[d] = result;
1706 if setflags then
1707 APSR.N = result<31>;
1708 APSR.Z = IsZeroBit(result);
1709 APSR.C = carry;
1710 APSR.V = overflow;
1711 }
1712#endif
1713
Greg Clayton7bc39082011-03-24 23:53:38 +00001714 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001715 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001716 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001717 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001718 if (!success)
1719 return false;
1720 uint32_t imm32;
1721 switch (encoding) {
1722 case eEncodingA1:
1723 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1724 break;
1725 default:
1726 return false;
1727 }
1728 addr_t sp_offset = imm32;
1729 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1730
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001731 EmulateInstruction::Context context;
1732 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001733 RegisterInfo dwarf_reg;
1734 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001735 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001736
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001737 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001738 return false;
1739 }
1740 return true;
1741}
1742
Johnny Chenc9e747f2011-02-23 01:55:07 +00001743// This instruction subtracts an immediate value from the SP value, and writes
1744// the result to the destination register.
1745//
1746// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001747bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001748EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001749{
1750#if 0
1751 // ARM pseudo code...
1752 if (ConditionPassed())
1753 {
1754 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001755 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001756 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001757 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001758 else
1759 R[d] = result;
1760 if setflags then
1761 APSR.N = result<31>;
1762 APSR.Z = IsZeroBit(result);
1763 APSR.C = carry;
1764 APSR.V = overflow;
1765 }
1766#endif
1767
1768 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001769 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001770 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001771 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001772 if (!success)
1773 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001774
1775 uint32_t Rd;
1776 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001777 uint32_t imm32;
1778 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001779 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001780 Rd = 13;
1781 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001782 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001783 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001784 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001785 Rd = Bits32(opcode, 11, 8);
1786 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001787 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001788 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001789 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001790 if (Rd == 15 && !setflags)
1791 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001792 break;
1793 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001794 Rd = Bits32(opcode, 11, 8);
1795 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001796 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001797 if (Rd == 15)
1798 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001799 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001800 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001801 Rd = Bits32(opcode, 15, 12);
1802 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001803 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001804
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001805 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001806 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001807 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001808 break;
1809 default:
1810 return false;
1811 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001812 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1813
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001814 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001815 if (Rd == 13)
1816 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001817 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1818 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001819 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001820 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001821 }
1822 else
1823 {
1824 context.type = EmulateInstruction::eContextImmediate;
1825 context.SetNoArgs ();
1826 }
1827
1828 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001829 return false;
1830 }
1831 return true;
1832}
1833
Johnny Chen08c25e82011-01-31 18:02:28 +00001834// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001835bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001836EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001837{
1838#if 0
1839 // ARM pseudo code...
1840 if (ConditionPassed())
1841 {
1842 EncodingSpecificOperations();
1843 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1844 address = if index then offset_addr else R[n];
1845 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1846 if wback then R[n] = offset_addr;
1847 }
1848#endif
1849
1850 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001851
Greg Clayton7bc39082011-03-24 23:53:38 +00001852 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001853 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001854 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001855 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001856 if (!success)
1857 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001858 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001859 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001860 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1861
1862 bool index;
1863 bool add;
1864 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001865 switch (encoding) {
1866 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001867 Rt = Bits32(opcode, 15, 12);
1868 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001869 Rn = Bits32 (opcode, 19, 16);
1870
1871 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1872 return false;
1873
1874 index = BitIsSet (opcode, 24);
1875 add = BitIsSet (opcode, 23);
1876 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1877
1878 if (wback && ((Rn == 15) || (Rn == Rt)))
1879 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001880 break;
1881 default:
1882 return false;
1883 }
Caroline Tice3e407972011-03-18 19:41:00 +00001884 addr_t offset_addr;
1885 if (add)
1886 offset_addr = sp + imm12;
1887 else
1888 offset_addr = sp - imm12;
1889
1890 addr_t addr;
1891 if (index)
1892 addr = offset_addr;
1893 else
1894 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001895
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001896 EmulateInstruction::Context context;
1897 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001898 RegisterInfo sp_reg;
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001899 RegisterInfo dwarf_reg;
1900
Greg Claytonc07d4512011-04-26 23:48:45 +00001901 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001902 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1903 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001904 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001905 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001906 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001907 if (!success)
1908 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001909 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001910 return false;
1911 }
1912 else
1913 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001914 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001915 if (!success)
1916 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001917 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001918 return false;
1919 }
1920
Caroline Tice3e407972011-03-18 19:41:00 +00001921
1922 if (wback)
1923 {
1924 context.type = EmulateInstruction::eContextAdjustStackPointer;
1925 context.SetImmediateSigned (addr - sp);
1926 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1927 return false;
1928 }
Johnny Chence1ca772011-01-25 01:13:00 +00001929 }
1930 return true;
1931}
1932
Johnny Chen08c25e82011-01-31 18:02:28 +00001933// Vector Push stores multiple extension registers to the stack.
1934// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001935bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001936EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001937{
1938#if 0
1939 // ARM pseudo code...
1940 if (ConditionPassed())
1941 {
1942 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1943 address = SP - imm32;
1944 SP = SP - imm32;
1945 if single_regs then
1946 for r = 0 to regs-1
1947 MemA[address,4] = S[d+r]; address = address+4;
1948 else
1949 for r = 0 to regs-1
1950 // Store as two word-aligned words in the correct order for current endianness.
1951 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1952 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1953 address = address+8;
1954 }
1955#endif
1956
1957 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001958
Greg Clayton7bc39082011-03-24 23:53:38 +00001959 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001960 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001961 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001962 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001963 if (!success)
1964 return false;
1965 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001966 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001967 uint32_t imm32; // stack offset
1968 uint32_t regs; // number of registers
1969 switch (encoding) {
1970 case eEncodingT1:
1971 case eEncodingA1:
1972 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001973 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001974 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1975 // If UInt(imm8) is odd, see "FSTMX".
1976 regs = Bits32(opcode, 7, 0) / 2;
1977 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1978 if (regs == 0 || regs > 16 || (d + regs) > 32)
1979 return false;
1980 break;
1981 case eEncodingT2:
1982 case eEncodingA2:
1983 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001984 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001985 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1986 regs = Bits32(opcode, 7, 0);
1987 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1988 if (regs == 0 || regs > 16 || (d + regs) > 32)
1989 return false;
1990 break;
1991 default:
1992 return false;
1993 }
1994 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1995 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1996 addr_t sp_offset = imm32;
1997 addr_t addr = sp - sp_offset;
1998 uint32_t i;
1999
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002000 EmulateInstruction::Context context;
2001 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002002 RegisterInfo dwarf_reg;
2003 RegisterInfo sp_reg;
2004 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002005 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00002006 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002007 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002008 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00002009 // uint64_t to accommodate 64-bit registers.
Greg Clayton061b79d2011-05-09 20:18:18 +00002010 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00002011 if (!success)
2012 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002013 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00002014 return false;
2015 addr += reg_byte_size;
2016 }
2017
2018 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002019 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00002020
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002021 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00002022 return false;
2023 }
2024 return true;
2025}
2026
Johnny Chen587a0a42011-02-01 18:35:28 +00002027// Vector Pop loads multiple extension registers from the stack.
2028// It also updates SP to point just above the loaded data.
2029bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002030EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00002031{
2032#if 0
2033 // ARM pseudo code...
2034 if (ConditionPassed())
2035 {
2036 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2037 address = SP;
2038 SP = SP + imm32;
2039 if single_regs then
2040 for r = 0 to regs-1
2041 S[d+r] = MemA[address,4]; address = address+4;
2042 else
2043 for r = 0 to regs-1
2044 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2045 // Combine the word-aligned words in the correct order for current endianness.
2046 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2047 }
2048#endif
2049
2050 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002051
Greg Clayton7bc39082011-03-24 23:53:38 +00002052 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002053 {
2054 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002055 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002056 if (!success)
2057 return false;
2058 bool single_regs;
2059 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2060 uint32_t imm32; // stack offset
2061 uint32_t regs; // number of registers
2062 switch (encoding) {
2063 case eEncodingT1:
2064 case eEncodingA1:
2065 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002066 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002067 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2068 // If UInt(imm8) is odd, see "FLDMX".
2069 regs = Bits32(opcode, 7, 0) / 2;
2070 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2071 if (regs == 0 || regs > 16 || (d + regs) > 32)
2072 return false;
2073 break;
2074 case eEncodingT2:
2075 case eEncodingA2:
2076 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002077 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002078 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2079 regs = Bits32(opcode, 7, 0);
2080 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2081 if (regs == 0 || regs > 16 || (d + regs) > 32)
2082 return false;
2083 break;
2084 default:
2085 return false;
2086 }
2087 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2088 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2089 addr_t sp_offset = imm32;
2090 addr_t addr = sp;
2091 uint32_t i;
2092 uint64_t data; // uint64_t to accomodate 64-bit registers.
2093
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002094 EmulateInstruction::Context context;
2095 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002096 RegisterInfo dwarf_reg;
2097 RegisterInfo sp_reg;
2098 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002099 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002100 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002101 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002102 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002103 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002104 if (!success)
2105 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +00002106 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002107 return false;
2108 addr += reg_byte_size;
2109 }
2110
2111 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002112 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002113
2114 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2115 return false;
2116 }
2117 return true;
2118}
2119
Johnny Chenb77be412011-02-04 00:40:18 +00002120// SVC (previously SWI)
2121bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002122EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002123{
2124#if 0
2125 // ARM pseudo code...
2126 if (ConditionPassed())
2127 {
2128 EncodingSpecificOperations();
2129 CallSupervisor();
2130 }
2131#endif
2132
2133 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002134
Greg Clayton7bc39082011-03-24 23:53:38 +00002135 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002136 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002137 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002138 addr_t lr; // next instruction address
2139 if (!success)
2140 return false;
2141 uint32_t imm32; // the immediate constant
2142 uint32_t mode; // ARM or Thumb mode
2143 switch (encoding) {
2144 case eEncodingT1:
2145 lr = (pc + 2) | 1u; // return address
2146 imm32 = Bits32(opcode, 7, 0);
2147 mode = eModeThumb;
2148 break;
2149 case eEncodingA1:
2150 lr = pc + 4; // return address
2151 imm32 = Bits32(opcode, 23, 0);
2152 mode = eModeARM;
2153 break;
2154 default:
2155 return false;
2156 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002157
2158 EmulateInstruction::Context context;
2159 context.type = EmulateInstruction::eContextSupervisorCall;
Greg Claytonc07d4512011-04-26 23:48:45 +00002160 context.SetISAAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002161 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2162 return false;
2163 }
2164 return true;
2165}
2166
Johnny Chenc315f862011-02-05 00:46:10 +00002167// If Then makes up to four following instructions (the IT block) conditional.
2168bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002169EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002170{
2171#if 0
2172 // ARM pseudo code...
2173 EncodingSpecificOperations();
2174 ITSTATE.IT<7:0> = firstcond:mask;
2175#endif
2176
Johnny Chenc315f862011-02-05 00:46:10 +00002177 m_it_session.InitIT(Bits32(opcode, 7, 0));
2178 return true;
2179}
2180
Greg Clayton04d397c2011-05-23 18:04:09 +00002181bool
2182EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding)
2183{
2184 // NOP, nothing to do...
2185 return true;
2186}
2187
Johnny Chen3b620b32011-02-07 20:11:47 +00002188// Branch causes a branch to a target address.
2189bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002190EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002191{
2192#if 0
2193 // ARM pseudo code...
2194 if (ConditionPassed())
2195 {
2196 EncodingSpecificOperations();
2197 BranchWritePC(PC + imm32);
2198 }
2199#endif
2200
2201 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002202
Greg Clayton7bc39082011-03-24 23:53:38 +00002203 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002204 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002205 EmulateInstruction::Context context;
2206 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002207 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002208 if (!success)
2209 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002210 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002211 int32_t imm32; // PC-relative offset
2212 switch (encoding) {
2213 case eEncodingT1:
2214 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2215 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002216 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002217 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002218 break;
2219 case eEncodingT2:
2220 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002221 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002222 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002223 break;
2224 case eEncodingT3:
2225 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2226 {
Johnny Chenbd599902011-02-10 21:39:01 +00002227 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002228 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002229 uint32_t J1 = Bit32(opcode, 13);
2230 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002231 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002232 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002233 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002234 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002235 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002236 break;
2237 }
2238 case eEncodingT4:
2239 {
Johnny Chenbd599902011-02-10 21:39:01 +00002240 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002241 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002242 uint32_t J1 = Bit32(opcode, 13);
2243 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002244 uint32_t imm11 = Bits32(opcode, 10, 0);
2245 uint32_t I1 = !(J1 ^ S);
2246 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002247 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002248 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002249 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002250 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002251 break;
2252 }
2253 case eEncodingA1:
2254 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002255 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002256 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002257 break;
2258 default:
2259 return false;
2260 }
2261 if (!BranchWritePC(context, target))
2262 return false;
2263 }
2264 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002265}
2266
Johnny Chen53ebab72011-02-08 23:21:57 +00002267// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2268// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2269// CBNZ, CBZ
2270bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002271EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002272{
2273#if 0
2274 // ARM pseudo code...
2275 EncodingSpecificOperations();
2276 if nonzero ^ IsZero(R[n]) then
2277 BranchWritePC(PC + imm32);
2278#endif
2279
2280 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002281
2282 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002283 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002284 if (!success)
2285 return false;
2286
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002287 EmulateInstruction::Context context;
2288 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002289 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002290 if (!success)
2291 return false;
2292
2293 addr_t target; // target address
2294 uint32_t imm32; // PC-relative offset to branch forward
2295 bool nonzero;
2296 switch (encoding) {
2297 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002298 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002299 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002300 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002301 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002302 break;
2303 default:
2304 return false;
2305 }
2306 if (nonzero ^ (reg_val == 0))
2307 if (!BranchWritePC(context, target))
2308 return false;
2309
2310 return true;
2311}
2312
Johnny Chen60299ec2011-02-17 19:34:27 +00002313// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2314// A base register provides a pointer to the table, and a second register supplies an index into the table.
2315// The branch length is twice the value of the byte returned from the table.
2316//
2317// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2318// A base register provides a pointer to the table, and a second register supplies an index into the table.
2319// The branch length is twice the value of the halfword returned from the table.
2320// TBB, TBH
2321bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002322EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002323{
2324#if 0
2325 // ARM pseudo code...
2326 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2327 if is_tbh then
2328 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2329 else
2330 halfwords = UInt(MemU[R[n]+R[m], 1]);
2331 BranchWritePC(PC + 2*halfwords);
2332#endif
2333
2334 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002335
2336 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2337 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2338 bool is_tbh; // true if table branch halfword
2339 switch (encoding) {
2340 case eEncodingT1:
2341 Rn = Bits32(opcode, 19, 16);
2342 Rm = Bits32(opcode, 3, 0);
2343 is_tbh = BitIsSet(opcode, 4);
2344 if (Rn == 13 || BadReg(Rm))
2345 return false;
2346 if (InITBlock() && !LastInITBlock())
2347 return false;
2348 break;
2349 default:
2350 return false;
2351 }
2352
2353 // Read the address of the table from the operand register Rn.
2354 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002355 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002356 if (!success)
2357 return false;
2358
2359 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002360 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002361 if (!success)
2362 return false;
2363
2364 // the offsetted table address
2365 addr_t addr = base + (is_tbh ? index*2 : index);
2366
2367 // PC-relative offset to branch forward
2368 EmulateInstruction::Context context;
2369 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002370 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002371 if (!success)
2372 return false;
2373
Johnny Chene39f22d2011-02-19 01:36:13 +00002374 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002375 if (!success)
2376 return false;
2377
2378 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002379 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002380 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Greg Claytonc07d4512011-04-26 23:48:45 +00002381 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
Johnny Chen60299ec2011-02-17 19:34:27 +00002382
2383 if (!BranchWritePC(context, target))
2384 return false;
2385
2386 return true;
2387}
2388
Caroline Ticedcc11b32011-03-02 23:57:02 +00002389// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2390// It can optionally update the condition flags based on the result.
2391bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002392EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002393{
2394#if 0
2395 if ConditionPassed() then
2396 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002397 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002398 R[d] = result;
2399 if setflags then
2400 APSR.N = result<31>;
2401 APSR.Z = IsZeroBit(result);
2402 APSR.C = carry;
2403 APSR.V = overflow;
2404#endif
2405
2406 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002407
Greg Clayton7bc39082011-03-24 23:53:38 +00002408 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002409 {
2410 uint32_t d;
2411 uint32_t n;
2412 bool setflags;
2413 uint32_t imm32;
2414 uint32_t carry_out;
2415
2416 //EncodingSpecificOperations();
2417 switch (encoding)
2418 {
2419 case eEncodingT1:
2420 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2421 d = Bits32 (opcode, 2, 0);
2422 n = Bits32 (opcode, 5, 3);
2423 setflags = !InITBlock();
2424 imm32 = Bits32 (opcode, 8,6);
2425
2426 break;
2427
2428 case eEncodingT2:
2429 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2430 d = Bits32 (opcode, 10, 8);
2431 n = Bits32 (opcode, 10, 8);
2432 setflags = !InITBlock();
2433 imm32 = Bits32 (opcode, 7, 0);
2434
2435 break;
2436
2437 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002438 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2439 // if Rn == '1101' then SEE ADD (SP plus immediate);
2440 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002441 d = Bits32 (opcode, 11, 8);
2442 n = Bits32 (opcode, 19, 16);
2443 setflags = BitIsSet (opcode, 20);
2444 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2445
2446 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2447 if (BadReg (d) || (n == 15))
2448 return false;
2449
2450 break;
2451
2452 case eEncodingT4:
2453 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002454 // if Rn == '1111' then SEE ADR;
2455 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002456 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2457 d = Bits32 (opcode, 11, 8);
2458 n = Bits32 (opcode, 19, 16);
2459 setflags = false;
2460 uint32_t i = Bit32 (opcode, 26);
2461 uint32_t imm3 = Bits32 (opcode, 14, 12);
2462 uint32_t imm8 = Bits32 (opcode, 7, 0);
2463 imm32 = (i << 11) | (imm3 << 8) | imm8;
2464
2465 // if BadReg(d) then UNPREDICTABLE;
2466 if (BadReg (d))
2467 return false;
2468
2469 break;
2470 }
2471 default:
2472 return false;
2473 }
2474
2475 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2476 if (!success)
2477 return false;
2478
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002479 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002480 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2481
Greg Claytonc07d4512011-04-26 23:48:45 +00002482 RegisterInfo reg_n;
2483 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002484
2485 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002486 context.type = eContextArithmetic;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002487 context.SetRegisterPlusOffset (reg_n, imm32);
2488
2489 //R[d] = result;
2490 //if setflags then
2491 //APSR.N = result<31>;
2492 //APSR.Z = IsZeroBit(result);
2493 //APSR.C = carry;
2494 //APSR.V = overflow;
2495 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2496 return false;
2497
2498 }
2499 return true;
2500}
2501
Johnny Chen8fa20592011-02-18 01:22:22 +00002502// This instruction adds an immediate value to a register value, and writes the result to the destination
2503// register. It can optionally update the condition flags based on the result.
2504bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002505EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002506{
2507#if 0
2508 // ARM pseudo code...
2509 if ConditionPassed() then
2510 EncodingSpecificOperations();
2511 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2512 if d == 15 then
2513 ALUWritePC(result); // setflags is always FALSE here
2514 else
2515 R[d] = result;
2516 if setflags then
2517 APSR.N = result<31>;
2518 APSR.Z = IsZeroBit(result);
2519 APSR.C = carry;
2520 APSR.V = overflow;
2521#endif
2522
2523 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002524
Greg Clayton7bc39082011-03-24 23:53:38 +00002525 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002526 {
2527 uint32_t Rd, Rn;
2528 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2529 bool setflags;
2530 switch (encoding)
2531 {
2532 case eEncodingA1:
2533 Rd = Bits32(opcode, 15, 12);
2534 Rn = Bits32(opcode, 19, 16);
2535 setflags = BitIsSet(opcode, 20);
2536 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2537 break;
2538 default:
2539 return false;
2540 }
2541
Johnny Chen8fa20592011-02-18 01:22:22 +00002542 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002543 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002544 if (!success)
2545 return false;
2546
2547 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2548
2549 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002550 context.type = eContextArithmetic;
2551 RegisterInfo dwarf_reg;
2552 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00002553 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002554
2555 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2556 return false;
2557 }
2558 return true;
2559}
2560
Johnny Chend761dcf2011-02-17 22:03:29 +00002561// This instruction adds a register value and an optionally-shifted register value, and writes the result
2562// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002563bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002564EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002565{
2566#if 0
2567 // ARM pseudo code...
2568 if ConditionPassed() then
2569 EncodingSpecificOperations();
2570 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2571 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2572 if d == 15 then
2573 ALUWritePC(result); // setflags is always FALSE here
2574 else
2575 R[d] = result;
2576 if setflags then
2577 APSR.N = result<31>;
2578 APSR.Z = IsZeroBit(result);
2579 APSR.C = carry;
2580 APSR.V = overflow;
2581#endif
2582
2583 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002584
Greg Clayton7bc39082011-03-24 23:53:38 +00002585 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002586 {
2587 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002588 ARM_ShifterType shift_t;
2589 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002590 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002591 switch (encoding)
2592 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002593 case eEncodingT1:
2594 Rd = Bits32(opcode, 2, 0);
2595 Rn = Bits32(opcode, 5, 3);
2596 Rm = Bits32(opcode, 8, 6);
2597 setflags = !InITBlock();
2598 shift_t = SRType_LSL;
2599 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002600 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002601 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002602 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002603 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002604 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002605 shift_t = SRType_LSL;
2606 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002607 if (Rn == 15 && Rm == 15)
2608 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002609 if (Rd == 15 && InITBlock() && !LastInITBlock())
2610 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002611 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002612 case eEncodingA1:
2613 Rd = Bits32(opcode, 15, 12);
2614 Rn = Bits32(opcode, 19, 16);
2615 Rm = Bits32(opcode, 3, 0);
2616 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002617 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002618 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002619 default:
2620 return false;
2621 }
2622
Johnny Chen26863dc2011-02-09 23:43:29 +00002623 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002624 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002625 if (!success)
2626 return false;
2627
2628 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002629 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002630 if (!success)
2631 return false;
2632
Johnny Chena4438a72011-06-02 22:50:51 +00002633 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2634 if (!success)
2635 return false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002636 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002637
2638 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002639 context.type = eContextArithmetic;
2640 RegisterInfo op1_reg;
2641 RegisterInfo op2_reg;
2642 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2643 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00002644 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002645
Johnny Chen10530c22011-02-17 22:37:12 +00002646 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002647 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002648 }
2649 return true;
2650}
2651
Johnny Chen34075cb2011-02-22 01:56:31 +00002652// Compare Negative (immediate) adds a register value and an immediate value.
2653// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002654bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002655EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002656{
2657#if 0
2658 // ARM pseudo code...
2659 if ConditionPassed() then
2660 EncodingSpecificOperations();
2661 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2662 APSR.N = result<31>;
2663 APSR.Z = IsZeroBit(result);
2664 APSR.C = carry;
2665 APSR.V = overflow;
2666#endif
2667
2668 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002669
2670 uint32_t Rn; // the first operand
2671 uint32_t imm32; // the immediate value to be compared with
2672 switch (encoding) {
2673 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002674 Rn = Bits32(opcode, 19, 16);
2675 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2676 if (Rn == 15)
2677 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002678 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002679 case eEncodingA1:
2680 Rn = Bits32(opcode, 19, 16);
2681 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2682 break;
2683 default:
2684 return false;
2685 }
2686 // Read the register value from the operand register Rn.
2687 uint32_t reg_val = ReadCoreReg(Rn, &success);
2688 if (!success)
2689 return false;
2690
Johnny Chen078fbc62011-02-22 19:48:22 +00002691 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002692
2693 EmulateInstruction::Context context;
2694 context.type = EmulateInstruction::eContextImmediate;
2695 context.SetNoArgs ();
2696 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2697 return false;
2698
2699 return true;
2700}
2701
2702// Compare Negative (register) adds a register value and an optionally-shifted register value.
2703// It updates the condition flags based on the result, and discards the result.
2704bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002705EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002706{
2707#if 0
2708 // ARM pseudo code...
2709 if ConditionPassed() then
2710 EncodingSpecificOperations();
2711 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2712 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2713 APSR.N = result<31>;
2714 APSR.Z = IsZeroBit(result);
2715 APSR.C = carry;
2716 APSR.V = overflow;
2717#endif
2718
2719 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002720
2721 uint32_t Rn; // the first operand
2722 uint32_t Rm; // the second operand
2723 ARM_ShifterType shift_t;
2724 uint32_t shift_n; // the shift applied to the value read from Rm
2725 switch (encoding) {
2726 case eEncodingT1:
2727 Rn = Bits32(opcode, 2, 0);
2728 Rm = Bits32(opcode, 5, 3);
2729 shift_t = SRType_LSL;
2730 shift_n = 0;
2731 break;
2732 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002733 Rn = Bits32(opcode, 19, 16);
2734 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002735 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002736 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2737 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002738 return false;
2739 break;
2740 case eEncodingA1:
2741 Rn = Bits32(opcode, 19, 16);
2742 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002743 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002744 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002745 default:
2746 return false;
2747 }
2748 // Read the register value from register Rn.
2749 uint32_t val1 = ReadCoreReg(Rn, &success);
2750 if (!success)
2751 return false;
2752
2753 // Read the register value from register Rm.
2754 uint32_t val2 = ReadCoreReg(Rm, &success);
2755 if (!success)
2756 return false;
2757
Johnny Chena4438a72011-06-02 22:50:51 +00002758 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2759 if (!success)
2760 return false;
Johnny Chen078fbc62011-02-22 19:48:22 +00002761 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002762
2763 EmulateInstruction::Context context;
2764 context.type = EmulateInstruction::eContextImmediate;
2765 context.SetNoArgs();
2766 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2767 return false;
2768
2769 return true;
2770}
2771
2772// Compare (immediate) subtracts an immediate value from a register value.
2773// It updates the condition flags based on the result, and discards the result.
2774bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002775EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002776{
2777#if 0
2778 // ARM pseudo code...
2779 if ConditionPassed() then
2780 EncodingSpecificOperations();
2781 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2782 APSR.N = result<31>;
2783 APSR.Z = IsZeroBit(result);
2784 APSR.C = carry;
2785 APSR.V = overflow;
2786#endif
2787
2788 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002789
2790 uint32_t Rn; // the first operand
2791 uint32_t imm32; // the immediate value to be compared with
2792 switch (encoding) {
2793 case eEncodingT1:
2794 Rn = Bits32(opcode, 10, 8);
2795 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002796 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002797 case eEncodingT2:
2798 Rn = Bits32(opcode, 19, 16);
2799 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2800 if (Rn == 15)
2801 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002802 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002803 case eEncodingA1:
2804 Rn = Bits32(opcode, 19, 16);
2805 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002806 break;
2807 default:
2808 return false;
2809 }
2810 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002811 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002812 if (!success)
2813 return false;
2814
Johnny Chen10530c22011-02-17 22:37:12 +00002815 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2816
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002817 EmulateInstruction::Context context;
2818 context.type = EmulateInstruction::eContextImmediate;
2819 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002820 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2821 return false;
2822
Johnny Chend4dc4442011-02-11 02:02:56 +00002823 return true;
2824}
2825
Johnny Chen34075cb2011-02-22 01:56:31 +00002826// Compare (register) subtracts an optionally-shifted register value from a register value.
2827// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002828bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002829EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002830{
2831#if 0
2832 // ARM pseudo code...
2833 if ConditionPassed() then
2834 EncodingSpecificOperations();
2835 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2836 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2837 APSR.N = result<31>;
2838 APSR.Z = IsZeroBit(result);
2839 APSR.C = carry;
2840 APSR.V = overflow;
2841#endif
2842
2843 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002844
2845 uint32_t Rn; // the first operand
2846 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002847 ARM_ShifterType shift_t;
2848 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002849 switch (encoding) {
2850 case eEncodingT1:
2851 Rn = Bits32(opcode, 2, 0);
2852 Rm = Bits32(opcode, 5, 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 break;
2856 case eEncodingT2:
2857 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2858 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002859 shift_t = SRType_LSL;
2860 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002861 if (Rn < 8 && Rm < 8)
2862 return false;
2863 if (Rn == 15 || Rm == 15)
2864 return false;
2865 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002866 case eEncodingA1:
2867 Rn = Bits32(opcode, 19, 16);
2868 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002869 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002870 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002871 default:
2872 return false;
2873 }
2874 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002875 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002876 if (!success)
2877 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002878
Johnny Chene4a4d302011-02-11 21:53:58 +00002879 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002880 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002881 if (!success)
2882 return false;
2883
Johnny Chena4438a72011-06-02 22:50:51 +00002884 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2885 if (!success)
2886 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002887 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002888
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002889 EmulateInstruction::Context context;
2890 context.type = EmulateInstruction::eContextImmediate;
2891 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002892 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2893 return false;
2894
Johnny Chene4a4d302011-02-11 21:53:58 +00002895 return true;
2896}
2897
Johnny Chen82f16aa2011-02-15 20:10:55 +00002898// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2899// shifting in copies of its sign bit, and writes the result to the destination register. It can
2900// optionally update the condition flags based on the result.
2901bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002902EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002903{
2904#if 0
2905 // ARM pseudo code...
2906 if ConditionPassed() then
2907 EncodingSpecificOperations();
2908 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2909 if d == 15 then // Can only occur for ARM encoding
2910 ALUWritePC(result); // setflags is always FALSE here
2911 else
2912 R[d] = result;
2913 if setflags then
2914 APSR.N = result<31>;
2915 APSR.Z = IsZeroBit(result);
2916 APSR.C = carry;
2917 // APSR.V unchanged
2918#endif
2919
Greg Clayton7bc39082011-03-24 23:53:38 +00002920 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002921}
2922
2923// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2924// shifting in copies of its sign bit, and writes the result to the destination register.
2925// The variable number of bits is read from the bottom byte of a register. It can optionally update
2926// the condition flags based on the result.
2927bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002928EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002929{
2930#if 0
2931 // ARM pseudo code...
2932 if ConditionPassed() then
2933 EncodingSpecificOperations();
2934 shift_n = UInt(R[m]<7:0>);
2935 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2936 R[d] = result;
2937 if setflags then
2938 APSR.N = result<31>;
2939 APSR.Z = IsZeroBit(result);
2940 APSR.C = carry;
2941 // APSR.V unchanged
2942#endif
2943
Greg Clayton7bc39082011-03-24 23:53:38 +00002944 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002945}
2946
2947// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2948// shifting in zeros, and writes the result to the destination register. It can optionally
2949// update the condition flags based on the result.
2950bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002951EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002952{
2953#if 0
2954 // ARM pseudo code...
2955 if ConditionPassed() then
2956 EncodingSpecificOperations();
2957 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2958 if d == 15 then // Can only occur for ARM encoding
2959 ALUWritePC(result); // setflags is always FALSE here
2960 else
2961 R[d] = result;
2962 if setflags then
2963 APSR.N = result<31>;
2964 APSR.Z = IsZeroBit(result);
2965 APSR.C = carry;
2966 // APSR.V unchanged
2967#endif
2968
Greg Clayton7bc39082011-03-24 23:53:38 +00002969 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002970}
2971
2972// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2973// shifting in zeros, and writes the result to the destination register. The variable number
2974// of bits is read from the bottom byte of a register. It can optionally update the condition
2975// flags based on the result.
2976bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002977EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002978{
2979#if 0
2980 // ARM pseudo code...
2981 if ConditionPassed() then
2982 EncodingSpecificOperations();
2983 shift_n = UInt(R[m]<7:0>);
2984 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2985 R[d] = result;
2986 if setflags then
2987 APSR.N = result<31>;
2988 APSR.Z = IsZeroBit(result);
2989 APSR.C = carry;
2990 // APSR.V unchanged
2991#endif
2992
Greg Clayton7bc39082011-03-24 23:53:38 +00002993 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002994}
2995
2996// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2997// shifting in zeros, and writes the result to the destination register. It can optionally
2998// update the condition flags based on the result.
2999bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003000EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003001{
3002#if 0
3003 // ARM pseudo code...
3004 if ConditionPassed() then
3005 EncodingSpecificOperations();
3006 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3007 if d == 15 then // Can only occur for ARM encoding
3008 ALUWritePC(result); // setflags is always FALSE here
3009 else
3010 R[d] = result;
3011 if setflags then
3012 APSR.N = result<31>;
3013 APSR.Z = IsZeroBit(result);
3014 APSR.C = carry;
3015 // APSR.V unchanged
3016#endif
3017
Greg Clayton7bc39082011-03-24 23:53:38 +00003018 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003019}
3020
3021// Logical Shift Right (register) shifts a register value right by a variable number of bits,
3022// shifting in zeros, and writes the result to the destination register. The variable number
3023// of bits is read from the bottom byte of a register. It can optionally update the condition
3024// flags based on the result.
3025bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003026EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003027{
3028#if 0
3029 // ARM pseudo code...
3030 if ConditionPassed() then
3031 EncodingSpecificOperations();
3032 shift_n = UInt(R[m]<7:0>);
3033 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3034 R[d] = result;
3035 if setflags then
3036 APSR.N = result<31>;
3037 APSR.Z = IsZeroBit(result);
3038 APSR.C = carry;
3039 // APSR.V unchanged
3040#endif
3041
Greg Clayton7bc39082011-03-24 23:53:38 +00003042 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003043}
3044
Johnny Cheneeab4852011-02-16 22:14:44 +00003045// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3046// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3047// It can optionally update the condition flags based on the result.
3048bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003049EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003050{
3051#if 0
3052 // ARM pseudo code...
3053 if ConditionPassed() then
3054 EncodingSpecificOperations();
3055 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3056 if d == 15 then // Can only occur for ARM encoding
3057 ALUWritePC(result); // setflags is always FALSE here
3058 else
3059 R[d] = result;
3060 if setflags then
3061 APSR.N = result<31>;
3062 APSR.Z = IsZeroBit(result);
3063 APSR.C = carry;
3064 // APSR.V unchanged
3065#endif
3066
Greg Clayton7bc39082011-03-24 23:53:38 +00003067 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003068}
3069
3070// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3071// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3072// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3073// flags based on the result.
3074bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003075EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003076{
3077#if 0
3078 // ARM pseudo code...
3079 if ConditionPassed() then
3080 EncodingSpecificOperations();
3081 shift_n = UInt(R[m]<7:0>);
3082 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3083 R[d] = result;
3084 if setflags then
3085 APSR.N = result<31>;
3086 APSR.Z = IsZeroBit(result);
3087 APSR.C = carry;
3088 // APSR.V unchanged
3089#endif
3090
Greg Clayton7bc39082011-03-24 23:53:38 +00003091 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003092}
3093
3094// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3095// with the carry flag shifted into bit [31].
3096//
3097// RRX can optionally update the condition flags based on the result.
3098// In that case, bit [0] is shifted into the carry flag.
3099bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003100EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003101{
3102#if 0
3103 // ARM pseudo code...
3104 if ConditionPassed() then
3105 EncodingSpecificOperations();
3106 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3107 if d == 15 then // Can only occur for ARM encoding
3108 ALUWritePC(result); // setflags is always FALSE here
3109 else
3110 R[d] = result;
3111 if setflags then
3112 APSR.N = result<31>;
3113 APSR.Z = IsZeroBit(result);
3114 APSR.C = carry;
3115 // APSR.V unchanged
3116#endif
3117
Greg Clayton7bc39082011-03-24 23:53:38 +00003118 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003119}
3120
Johnny Chen41a0a152011-02-16 01:27:54 +00003121bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003122EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003123{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003124// assert(shift_type == SRType_ASR
3125// || shift_type == SRType_LSL
3126// || shift_type == SRType_LSR
3127// || shift_type == SRType_ROR
3128// || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003129
Johnny Chen82f16aa2011-02-15 20:10:55 +00003130 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003131
Greg Clayton7bc39082011-03-24 23:53:38 +00003132 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003133 {
Johnny Chene7f89532011-02-15 23:22:46 +00003134 uint32_t Rd; // the destination register
3135 uint32_t Rm; // the first operand register
3136 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003137 uint32_t carry; // the carry bit after the shift operation
3138 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003139
3140 // Special case handling!
3141 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003142 ARMEncoding use_encoding = encoding;
3143 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003144 {
3145 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3146 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003147 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003148 }
3149
Greg Clayton7bc39082011-03-24 23:53:38 +00003150 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003151 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003152 // Due to the above special case handling!
Johnny Chen6cc60972011-06-02 23:07:03 +00003153 if (shift_type == SRType_ROR)
3154 return false;
Johnny Cheneeab4852011-02-16 22:14:44 +00003155
Johnny Chen82f16aa2011-02-15 20:10:55 +00003156 Rd = Bits32(opcode, 2, 0);
3157 Rm = Bits32(opcode, 5, 3);
3158 setflags = !InITBlock();
3159 imm5 = Bits32(opcode, 10, 6);
3160 break;
3161 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003162 // A8.6.141 RRX
Johnny Chen6cc60972011-06-02 23:07:03 +00003163 // There's no imm form of RRX instructions.
3164 if (shift_type == SRType_RRX)
3165 return false;
Johnny Cheneeab4852011-02-16 22:14:44 +00003166
Johnny Chen82f16aa2011-02-15 20:10:55 +00003167 Rd = Bits32(opcode, 11, 8);
3168 Rm = Bits32(opcode, 3, 0);
3169 setflags = BitIsSet(opcode, 20);
3170 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3171 if (BadReg(Rd) || BadReg(Rm))
3172 return false;
3173 break;
3174 case eEncodingA1:
3175 Rd = Bits32(opcode, 15, 12);
3176 Rm = Bits32(opcode, 3, 0);
3177 setflags = BitIsSet(opcode, 20);
3178 imm5 = Bits32(opcode, 11, 7);
3179 break;
3180 default:
3181 return false;
3182 }
3183
Johnny Cheneeab4852011-02-16 22:14:44 +00003184 // A8.6.139 ROR (immediate)
3185 if (shift_type == SRType_ROR && imm5 == 0)
3186 shift_type = SRType_RRX;
3187
Johnny Chen82f16aa2011-02-15 20:10:55 +00003188 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003189 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003190 if (!success)
3191 return false;
3192
Johnny Cheneeab4852011-02-16 22:14:44 +00003193 // Decode the shift amount if not RRX.
3194 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003195
Johnny Chena4438a72011-06-02 22:50:51 +00003196 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3197 if (!success)
3198 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003199
3200 // The context specifies that an immediate is to be moved into Rd.
3201 EmulateInstruction::Context context;
3202 context.type = EmulateInstruction::eContextImmediate;
3203 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003204
Johnny Chen10530c22011-02-17 22:37:12 +00003205 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003206 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003207 }
3208 return true;
3209}
3210
Johnny Chene7f89532011-02-15 23:22:46 +00003211bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003212EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003213{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003214 // assert(shift_type == SRType_ASR
3215 // || shift_type == SRType_LSL
3216 // || shift_type == SRType_LSR
3217 // || shift_type == SRType_ROR);
Johnny Chene7f89532011-02-15 23:22:46 +00003218
3219 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003220
Greg Clayton7bc39082011-03-24 23:53:38 +00003221 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003222 {
3223 uint32_t Rd; // the destination register
3224 uint32_t Rn; // the first operand register
3225 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3226 uint32_t carry; // the carry bit after the shift operation
3227 bool setflags;
3228 switch (encoding) {
3229 case eEncodingT1:
3230 Rd = Bits32(opcode, 2, 0);
3231 Rn = Rd;
3232 Rm = Bits32(opcode, 5, 3);
3233 setflags = !InITBlock();
3234 break;
3235 case eEncodingT2:
3236 Rd = Bits32(opcode, 11, 8);
3237 Rn = Bits32(opcode, 19, 16);
3238 Rm = Bits32(opcode, 3, 0);
3239 setflags = BitIsSet(opcode, 20);
3240 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3241 return false;
3242 break;
3243 case eEncodingA1:
3244 Rd = Bits32(opcode, 15, 12);
3245 Rn = Bits32(opcode, 3, 0);
3246 Rm = Bits32(opcode, 11, 8);
3247 setflags = BitIsSet(opcode, 20);
3248 if (Rd == 15 || Rn == 15 || Rm == 15)
3249 return false;
3250 break;
3251 default:
3252 return false;
3253 }
3254
3255 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003256 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003257 if (!success)
3258 return false;
3259 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003260 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003261 if (!success)
3262 return false;
3263
3264 // Get the shift amount.
3265 uint32_t amt = Bits32(val, 7, 0);
3266
Johnny Chena4438a72011-06-02 22:50:51 +00003267 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3268 if (!success)
3269 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003270
3271 // The context specifies that an immediate is to be moved into Rd.
3272 EmulateInstruction::Context context;
3273 context.type = EmulateInstruction::eContextImmediate;
3274 context.SetNoArgs ();
3275
Johnny Chen10530c22011-02-17 22:37:12 +00003276 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003277 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003278 }
3279 return true;
3280}
3281
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003282// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003283// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003284// can be written back to the base register.
3285bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003286EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003287{
3288#if 0
3289 // ARM pseudo code...
3290 if ConditionPassed()
3291 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3292 address = R[n];
3293
3294 for i = 0 to 14
3295 if registers<i> == '1' then
3296 R[i] = MemA[address, 4]; address = address + 4;
3297 if registers<15> == '1' then
3298 LoadWritePC (MemA[address, 4]);
3299
3300 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3301 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3302
3303#endif
3304
3305 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003306
Greg Clayton7bc39082011-03-24 23:53:38 +00003307 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003308 {
3309 uint32_t n;
3310 uint32_t registers = 0;
3311 bool wback;
3312 const uint32_t addr_byte_size = GetAddressByteSize();
3313 switch (encoding)
3314 {
3315 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003316 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003317 n = Bits32 (opcode, 10, 8);
3318 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003319 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003320 wback = BitIsClear (registers, n);
3321 // if BitCount(registers) < 1 then UNPREDICTABLE;
3322 if (BitCount(registers) < 1)
3323 return false;
3324 break;
3325 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003326 // if W == '1' && Rn == '1101' then SEE POP;
3327 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003328 n = Bits32 (opcode, 19, 16);
3329 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003330 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003331 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003332
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003333 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003334 if ((n == 15)
3335 || (BitCount (registers) < 2)
3336 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3337 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003338
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003339 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003340 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003341 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003342
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003343 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003344 if (wback
3345 && BitIsSet (registers, n))
3346 return false;
3347 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003348
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003349 case eEncodingA1:
3350 n = Bits32 (opcode, 19, 16);
3351 registers = Bits32 (opcode, 15, 0);
3352 wback = BitIsSet (opcode, 21);
3353 if ((n == 15)
3354 || (BitCount (registers) < 1))
3355 return false;
3356 break;
3357 default:
3358 return false;
3359 }
3360
3361 int32_t offset = 0;
3362 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3363 if (!success)
3364 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003365
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003366 EmulateInstruction::Context context;
3367 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003368 RegisterInfo dwarf_reg;
3369 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003370 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003371
3372 for (int i = 0; i < 14; ++i)
3373 {
3374 if (BitIsSet (registers, i))
3375 {
Caroline Tice85aab332011-02-08 23:56:10 +00003376 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003377 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003378 if (wback && (n == 13)) // Pop Instruction
3379 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3380
3381 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003382 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003383 if (!success)
3384 return false;
3385
3386 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3387 return false;
3388
3389 offset += addr_byte_size;
3390 }
3391 }
3392
3393 if (BitIsSet (registers, 15))
3394 {
3395 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003396 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003397 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003398 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003399 if (!success)
3400 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003401 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003402 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003403 return false;
3404 }
3405
3406 if (wback && BitIsClear (registers, n))
3407 {
Caroline Ticefa172202011-02-11 22:49:54 +00003408 // R[n] = R[n] + 4 * BitCount (registers)
3409 int32_t offset = addr_byte_size * BitCount (registers);
3410 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003411 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003412
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003413 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3414 return false;
3415 }
3416 if (wback && BitIsSet (registers, n))
3417 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003418 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003419 }
3420 return true;
3421}
Caroline Tice713c2662011-02-11 17:59:55 +00003422
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003423// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3424// The consecutive memory locations end at this address and the address just below the lowest of those locations
3425// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003426bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003427EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003428{
3429#if 0
3430 // ARM pseudo code...
3431 if ConditionPassed() then
3432 EncodingSpecificOperations();
3433 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003434
Caroline Tice713c2662011-02-11 17:59:55 +00003435 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003436 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003437 R[i] = MemA[address,4]; address = address + 4;
3438
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003439 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003440 LoadWritePC(MemA[address,4]);
3441
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003442 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3443 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003444#endif
3445
3446 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003447
Greg Clayton7bc39082011-03-24 23:53:38 +00003448 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003449 {
3450 uint32_t n;
3451 uint32_t registers = 0;
3452 bool wback;
3453 const uint32_t addr_byte_size = GetAddressByteSize();
3454
3455 // EncodingSpecificOperations();
3456 switch (encoding)
3457 {
3458 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003459 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003460 n = Bits32 (opcode, 19, 16);
3461 registers = Bits32 (opcode, 15, 0);
3462 wback = BitIsSet (opcode, 21);
3463
3464 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3465 if ((n == 15) || (BitCount (registers) < 1))
3466 return false;
3467
3468 break;
3469
3470 default:
3471 return false;
3472 }
3473 // address = R[n] - 4*BitCount(registers) + 4;
3474
3475 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003476 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003477
3478 if (!success)
3479 return false;
3480
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003481 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003482
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003483 EmulateInstruction::Context context;
3484 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003485 RegisterInfo dwarf_reg;
3486 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003487 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003488
3489 // for i = 0 to 14
3490 for (int i = 0; i < 14; ++i)
3491 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003492 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003493 if (BitIsSet (registers, i))
3494 {
3495 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003496 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003497 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003498 if (!success)
3499 return false;
3500 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3501 return false;
3502 offset += addr_byte_size;
3503 }
3504 }
3505
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003506 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003507 // LoadWritePC(MemA[address,4]);
3508 if (BitIsSet (registers, 15))
3509 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003510 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003511 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003512 if (!success)
3513 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003514 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003515 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003516 return false;
3517 }
3518
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003519 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003520 if (wback && BitIsClear (registers, n))
3521 {
Caroline Tice713c2662011-02-11 17:59:55 +00003522 if (!success)
3523 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003524
3525 offset = (addr_byte_size * BitCount (registers)) * -1;
3526 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003527 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003528 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003529 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3530 return false;
3531 }
3532
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003533 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003534 if (wback && BitIsSet (registers, n))
3535 return WriteBits32Unknown (n);
3536 }
3537 return true;
3538}
3539
3540// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3541// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3542// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003543bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003544EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003545{
3546#if 0
3547 // ARM pseudo code...
3548 if ConditionPassed() then
3549 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3550 address = R[n] - 4*BitCount(registers);
3551
3552 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003553 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003554 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003555 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003556 LoadWritePC(MemA[address,4]);
3557
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003558 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3559 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003560#endif
3561
3562 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003563
Greg Clayton7bc39082011-03-24 23:53:38 +00003564 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003565 {
3566 uint32_t n;
3567 uint32_t registers = 0;
3568 bool wback;
3569 const uint32_t addr_byte_size = GetAddressByteSize();
3570 switch (encoding)
3571 {
3572 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003573 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003574 n = Bits32 (opcode, 19, 16);
3575 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003576 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003577 wback = BitIsSet (opcode, 21);
3578
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003579 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003580 if ((n == 15)
3581 || (BitCount (registers) < 2)
3582 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3583 return false;
3584
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003585 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003586 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003587 return false;
3588
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003589 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003590 if (wback && BitIsSet (registers, n))
3591 return false;
3592
3593 break;
3594
3595 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003596 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003597 n = Bits32 (opcode, 19, 16);
3598 registers = Bits32 (opcode, 15, 0);
3599 wback = BitIsSet (opcode, 21);
3600
3601 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3602 if ((n == 15) || (BitCount (registers) < 1))
3603 return false;
3604
3605 break;
3606
3607 default:
3608 return false;
3609 }
3610
Caroline Tice713c2662011-02-11 17:59:55 +00003611 // address = R[n] - 4*BitCount(registers);
3612
Caroline Tice0b29e242011-02-08 23:16:02 +00003613 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003614 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003615
3616 if (!success)
3617 return false;
3618
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003619 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003620 EmulateInstruction::Context context;
3621 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003622 RegisterInfo dwarf_reg;
3623 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003624 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003625
3626 for (int i = 0; i < 14; ++i)
3627 {
3628 if (BitIsSet (registers, i))
3629 {
3630 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003631 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003632 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003633 if (!success)
3634 return false;
3635
3636 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3637 return false;
3638
3639 offset += addr_byte_size;
3640 }
3641 }
3642
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003643 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003644 // LoadWritePC(MemA[address,4]);
3645 if (BitIsSet (registers, 15))
3646 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003647 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003648 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003649 if (!success)
3650 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003651 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003652 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003653 return false;
3654 }
3655
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003656 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003657 if (wback && BitIsClear (registers, n))
3658 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003659 if (!success)
3660 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003661
3662 offset = (addr_byte_size * BitCount (registers)) * -1;
3663 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003664 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003665 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003666 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3667 return false;
3668 }
3669
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003670 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003671 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003672 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003673 }
3674 return true;
3675}
Caroline Tice85aab332011-02-08 23:56:10 +00003676
Caroline Tice713c2662011-02-11 17:59:55 +00003677// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3678// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3679// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003680bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003681EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003682{
3683#if 0
3684 if ConditionPassed() then
3685 EncodingSpecificOperations();
3686 address = R[n] + 4;
3687
3688 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003689 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003690 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003691 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003692 LoadWritePC(MemA[address,4]);
3693
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003694 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3695 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003696#endif
3697
3698 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003699
Greg Clayton7bc39082011-03-24 23:53:38 +00003700 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003701 {
3702 uint32_t n;
3703 uint32_t registers = 0;
3704 bool wback;
3705 const uint32_t addr_byte_size = GetAddressByteSize();
3706 switch (encoding)
3707 {
3708 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003709 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003710 n = Bits32 (opcode, 19, 16);
3711 registers = Bits32 (opcode, 15, 0);
3712 wback = BitIsSet (opcode, 21);
3713
3714 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3715 if ((n == 15) || (BitCount (registers) < 1))
3716 return false;
3717
3718 break;
3719 default:
3720 return false;
3721 }
3722 // address = R[n] + 4;
3723
3724 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003725 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003726
3727 if (!success)
3728 return false;
3729
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003730 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003731
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003732 EmulateInstruction::Context context;
3733 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003734 RegisterInfo dwarf_reg;
3735 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003736 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003737
3738 for (int i = 0; i < 14; ++i)
3739 {
3740 if (BitIsSet (registers, i))
3741 {
3742 // R[i] = MemA[address,4]; address = address + 4;
3743
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003744 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003745 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003746 if (!success)
3747 return false;
3748
3749 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3750 return false;
3751
3752 offset += addr_byte_size;
3753 }
3754 }
3755
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003756 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003757 // LoadWritePC(MemA[address,4]);
3758 if (BitIsSet (registers, 15))
3759 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003760 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003761 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003762 if (!success)
3763 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003764 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003765 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003766 return false;
3767 }
3768
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003769 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003770 if (wback && BitIsClear (registers, n))
3771 {
Caroline Tice85aab332011-02-08 23:56:10 +00003772 if (!success)
3773 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003774
3775 offset = addr_byte_size * BitCount (registers);
3776 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003777 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003778 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003779 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3780 return false;
3781 }
3782
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003783 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003784 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003785 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003786 }
3787 return true;
3788}
Caroline Tice0b29e242011-02-08 23:16:02 +00003789
Johnny Chenef21b592011-02-10 01:52:38 +00003790// Load Register (immediate) calculates an address from a base register value and
3791// an immediate offset, loads a word from memory, and writes to a register.
3792// LDR (immediate, Thumb)
3793bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003794EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003795{
3796#if 0
3797 // ARM pseudo code...
3798 if (ConditionPassed())
3799 {
3800 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3801 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3802 address = if index then offset_addr else R[n];
3803 data = MemU[address,4];
3804 if wback then R[n] = offset_addr;
3805 if t == 15 then
3806 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3807 elsif UnalignedSupport() || address<1:0> = '00' then
3808 R[t] = data;
3809 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3810 }
3811#endif
3812
3813 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003814
Greg Clayton7bc39082011-03-24 23:53:38 +00003815 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003816 {
3817 uint32_t Rt; // the destination register
3818 uint32_t Rn; // the base register
3819 uint32_t imm32; // the immediate offset used to form the address
3820 addr_t offset_addr; // the offset address
3821 addr_t address; // the calculated address
3822 uint32_t data; // the literal data value from memory load
3823 bool add, index, wback;
3824 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003825 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003826 Rt = Bits32(opcode, 2, 0);
3827 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003828 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3829 // index = TRUE; add = TRUE; wback = FALSE
3830 add = true;
3831 index = true;
3832 wback = false;
3833
3834 break;
3835
3836 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003837 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003838 Rt = Bits32 (opcode, 10, 8);
3839 Rn = 13;
3840 imm32 = Bits32 (opcode, 7, 0) << 2;
3841
3842 // index = TRUE; add = TRUE; wback = FALSE;
3843 index = true;
3844 add = true;
3845 wback = false;
3846
3847 break;
3848
3849 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003850 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003851 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3852 Rt = Bits32 (opcode, 15, 12);
3853 Rn = Bits32 (opcode, 19, 16);
3854 imm32 = Bits32 (opcode, 11, 0);
3855
3856 // index = TRUE; add = TRUE; wback = FALSE;
3857 index = true;
3858 add = true;
3859 wback = false;
3860
3861 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3862 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3863 return false;
3864
3865 break;
3866
3867 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003868 // if Rn == '1111' then SEE LDR (literal);
3869 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3870 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3871 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003872 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3873 return false;
3874
3875 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3876 Rt = Bits32 (opcode, 15, 12);
3877 Rn = Bits32 (opcode, 19, 16);
3878 imm32 = Bits32 (opcode, 7, 0);
3879
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003880 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003881 index = BitIsSet (opcode, 10);
3882 add = BitIsSet (opcode, 9);
3883 wback = BitIsSet (opcode, 8);
3884
3885 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3886 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3887 return false;
3888
3889 break;
3890
3891 default:
3892 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003893 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003894 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003895 if (!success)
3896 return false;
3897 if (add)
3898 offset_addr = base + imm32;
3899 else
3900 offset_addr = base - imm32;
3901
3902 address = (index ? offset_addr : base);
3903
Greg Claytonc07d4512011-04-26 23:48:45 +00003904 RegisterInfo base_reg;
3905 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
Johnny Chenef21b592011-02-10 01:52:38 +00003906 if (wback)
3907 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003908 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003909 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3910 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003911
Johnny Chenef21b592011-02-10 01:52:38 +00003912 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3913 return false;
3914 }
3915
3916 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003917 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003918 context.type = EmulateInstruction::eContextRegisterLoad;
3919 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003920
3921 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003922 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003923 if (!success)
3924 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003925
3926 if (Rt == 15)
3927 {
3928 if (Bits32(address, 1, 0) == 0)
3929 {
Johnny Chen668b4512011-02-15 21:08:58 +00003930 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003931 return false;
3932 }
3933 else
3934 return false;
3935 }
3936 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3937 {
3938 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3939 return false;
3940 }
3941 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003942 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003943 }
3944 return true;
3945}
3946
Caroline Ticeaf556562011-02-15 18:42:15 +00003947// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3948// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3949// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003950bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003951EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003952{
3953#if 0
3954 if ConditionPassed() then
3955 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3956 address = R[n];
3957
3958 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003959 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003960 if i == n && wback && i != LowestSetBit(registers) then
3961 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3962 else
3963 MemA[address,4] = R[i];
3964 address = address + 4;
3965
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003966 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003967 MemA[address,4] = PCStoreValue();
3968 if wback then R[n] = R[n] + 4*BitCount(registers);
3969#endif
3970
3971 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003972
Greg Clayton7bc39082011-03-24 23:53:38 +00003973 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003974 {
3975 uint32_t n;
3976 uint32_t registers = 0;
3977 bool wback;
3978 const uint32_t addr_byte_size = GetAddressByteSize();
3979
3980 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3981 switch (encoding)
3982 {
3983 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003984 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003985 n = Bits32 (opcode, 10, 8);
3986 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003987 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003988 wback = true;
3989
3990 // if BitCount(registers) < 1 then UNPREDICTABLE;
3991 if (BitCount (registers) < 1)
3992 return false;
3993
3994 break;
3995
3996 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003997 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003998 n = Bits32 (opcode, 19, 16);
3999 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004000 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00004001 wback = BitIsSet (opcode, 21);
4002
4003 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4004 if ((n == 15) || (BitCount (registers) < 2))
4005 return false;
4006
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004007 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00004008 if (wback && BitIsSet (registers, n))
4009 return false;
4010
4011 break;
4012
4013 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004014 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00004015 n = Bits32 (opcode, 19, 16);
4016 registers = Bits32 (opcode, 15, 0);
4017 wback = BitIsSet (opcode, 21);
4018
4019 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4020 if ((n == 15) || (BitCount (registers) < 1))
4021 return false;
4022
4023 break;
4024
4025 default:
4026 return false;
4027 }
4028
4029 // address = R[n];
4030 int32_t offset = 0;
4031 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4032 if (!success)
4033 return false;
4034
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004035 EmulateInstruction::Context context;
4036 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004037 RegisterInfo base_reg;
4038 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefa172202011-02-11 22:49:54 +00004039
4040 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004041 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00004042 for (int i = 0; i < 14; ++i)
4043 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004044 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00004045 if (BitIsSet (registers, i))
4046 {
4047 if (i < lowest_set_bit)
4048 lowest_set_bit = i;
4049 // if i == n && wback && i != LowestSetBit(registers) then
4050 if ((i == n) && wback && (i != lowest_set_bit))
4051 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4052 WriteBits32UnknownToMemory (address + offset);
4053 else
4054 {
4055 // MemA[address,4] = R[i];
4056 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4057 if (!success)
4058 return false;
4059
Greg Claytonc07d4512011-04-26 23:48:45 +00004060 RegisterInfo data_reg;
4061 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004062 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004063 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004064 return false;
4065 }
4066
4067 // address = address + 4;
4068 offset += addr_byte_size;
4069 }
4070 }
4071
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004072 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004073 // MemA[address,4] = PCStoreValue();
4074 if (BitIsSet (registers, 15))
4075 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004076 RegisterInfo pc_reg;
4077 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004078 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004079 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004080 if (!success)
4081 return false;
4082
Caroline Tice8d681f52011-03-17 23:50:16 +00004083 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004084 return false;
4085 }
4086
4087 // if wback then R[n] = R[n] + 4*BitCount(registers);
4088 if (wback)
4089 {
4090 offset = addr_byte_size * BitCount (registers);
4091 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004092 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004093 addr_t data = address + offset;
4094 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4095 return false;
4096 }
4097 }
4098 return true;
4099}
4100
Caroline Ticeaf556562011-02-15 18:42:15 +00004101// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4102// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4103// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004104bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004105EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004106{
4107#if 0
4108 if ConditionPassed() then
4109 EncodingSpecificOperations();
4110 address = R[n] - 4*BitCount(registers) + 4;
4111
4112 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004113 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004114 if i == n && wback && i != LowestSetBit(registers) then
4115 MemA[address,4] = bits(32) UNKNOWN;
4116 else
4117 MemA[address,4] = R[i];
4118 address = address + 4;
4119
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004120 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004121 MemA[address,4] = PCStoreValue();
4122
4123 if wback then R[n] = R[n] - 4*BitCount(registers);
4124#endif
4125
4126 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004127
Greg Clayton7bc39082011-03-24 23:53:38 +00004128 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004129 {
4130 uint32_t n;
4131 uint32_t registers = 0;
4132 bool wback;
4133 const uint32_t addr_byte_size = GetAddressByteSize();
4134
4135 // EncodingSpecificOperations();
4136 switch (encoding)
4137 {
4138 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004139 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004140 n = Bits32 (opcode, 19, 16);
4141 registers = Bits32 (opcode, 15, 0);
4142 wback = BitIsSet (opcode, 21);
4143
4144 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4145 if ((n == 15) || (BitCount (registers) < 1))
4146 return false;
4147 break;
4148 default:
4149 return false;
4150 }
4151
4152 // address = R[n] - 4*BitCount(registers) + 4;
4153 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004154 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004155 if (!success)
4156 return false;
4157
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004158 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004159
4160 EmulateInstruction::Context context;
4161 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004162 RegisterInfo base_reg;
4163 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004164
4165 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004166 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004167 for (int i = 0; i < 14; ++i)
4168 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004169 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004170 if (BitIsSet (registers, i))
4171 {
4172 if (i < lowest_bit_set)
4173 lowest_bit_set = i;
4174 //if i == n && wback && i != LowestSetBit(registers) then
4175 if ((i == n) && wback && (i != lowest_bit_set))
4176 // MemA[address,4] = bits(32) UNKNOWN;
4177 WriteBits32UnknownToMemory (address + offset);
4178 else
4179 {
4180 // MemA[address,4] = R[i];
4181 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4182 if (!success)
4183 return false;
4184
Greg Claytonc07d4512011-04-26 23:48:45 +00004185 RegisterInfo data_reg;
4186 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004187 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004188 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004189 return false;
4190 }
4191
4192 // address = address + 4;
4193 offset += addr_byte_size;
4194 }
4195 }
4196
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004197 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004198 // MemA[address,4] = PCStoreValue();
4199 if (BitIsSet (registers, 15))
4200 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004201 RegisterInfo pc_reg;
4202 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004203 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004204 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004205 if (!success)
4206 return false;
4207
Caroline Tice8d681f52011-03-17 23:50:16 +00004208 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004209 return false;
4210 }
4211
4212 // if wback then R[n] = R[n] - 4*BitCount(registers);
4213 if (wback)
4214 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004215 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004216 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4217 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004218 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004219 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4220 return false;
4221 }
4222 }
4223 return true;
4224}
4225
Caroline Ticeaf556562011-02-15 18:42:15 +00004226// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4227// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4228// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004229bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004230EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004231{
4232#if 0
4233 if ConditionPassed() then
4234 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4235 address = R[n] - 4*BitCount(registers);
4236
4237 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004238 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004239 if i == n && wback && i != LowestSetBit(registers) then
4240 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4241 else
4242 MemA[address,4] = R[i];
4243 address = address + 4;
4244
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004245 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004246 MemA[address,4] = PCStoreValue();
4247
4248 if wback then R[n] = R[n] - 4*BitCount(registers);
4249#endif
4250
4251
4252 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004253
Greg Clayton7bc39082011-03-24 23:53:38 +00004254 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004255 {
4256 uint32_t n;
4257 uint32_t registers = 0;
4258 bool wback;
4259 const uint32_t addr_byte_size = GetAddressByteSize();
4260
4261 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4262 switch (encoding)
4263 {
4264 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004265 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004266 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4267 {
4268 // See PUSH
4269 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004270 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004271 n = Bits32 (opcode, 19, 16);
4272 registers = Bits32 (opcode, 15, 0);
4273 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4274 wback = BitIsSet (opcode, 21);
4275 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4276 if ((n == 15) || BitCount (registers) < 2)
4277 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004278 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004279 if (wback && BitIsSet (registers, n))
4280 return false;
4281 break;
4282
4283 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00004284 // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004285 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4286 {
4287 // See Push
4288 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004289 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004290 n = Bits32 (opcode, 19, 16);
4291 registers = Bits32 (opcode, 15, 0);
4292 wback = BitIsSet (opcode, 21);
4293 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4294 if ((n == 15) || BitCount (registers) < 1)
4295 return false;
4296 break;
4297
4298 default:
4299 return false;
4300 }
4301
4302 // address = R[n] - 4*BitCount(registers);
4303
4304 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004305 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004306 if (!success)
4307 return false;
4308
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004309 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004310
4311 EmulateInstruction::Context context;
4312 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004313 RegisterInfo base_reg;
4314 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004315
4316 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004317 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004318 for (int i = 0; i < 14; ++i)
4319 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004320 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004321 if (BitIsSet (registers, i))
4322 {
4323 if (i < lowest_set_bit)
4324 lowest_set_bit = i;
4325 // if i == n && wback && i != LowestSetBit(registers) then
4326 if ((i == n) && wback && (i != lowest_set_bit))
4327 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4328 WriteBits32UnknownToMemory (address + offset);
4329 else
4330 {
4331 // MemA[address,4] = R[i];
4332 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4333 if (!success)
4334 return false;
4335
Greg Claytonc07d4512011-04-26 23:48:45 +00004336 RegisterInfo data_reg;
4337 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004338 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004339 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004340 return false;
4341 }
4342
4343 // address = address + 4;
4344 offset += addr_byte_size;
4345 }
4346 }
4347
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004348 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004349 // MemA[address,4] = PCStoreValue();
4350 if (BitIsSet (registers, 15))
4351 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004352 RegisterInfo pc_reg;
4353 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004354 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004355 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004356 if (!success)
4357 return false;
4358
Caroline Tice8d681f52011-03-17 23:50:16 +00004359 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004360 return false;
4361 }
4362
4363 // if wback then R[n] = R[n] - 4*BitCount(registers);
4364 if (wback)
4365 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004366 offset = (addr_byte_size * BitCount (registers)) * -1;
4367 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4368 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004369 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004370 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4371 return false;
4372 }
4373 }
4374 return true;
4375}
4376
4377// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4378// from a base register. The consecutive memory locations start just above this address, and the address of the last
4379// of those locations can optionally be written back to the base register.
4380bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004381EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004382{
4383#if 0
4384 if ConditionPassed() then
4385 EncodingSpecificOperations();
4386 address = R[n] + 4;
4387
4388 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004389 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004390 if i == n && wback && i != LowestSetBit(registers) then
4391 MemA[address,4] = bits(32) UNKNOWN;
4392 else
4393 MemA[address,4] = R[i];
4394 address = address + 4;
4395
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004396 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004397 MemA[address,4] = PCStoreValue();
4398
4399 if wback then R[n] = R[n] + 4*BitCount(registers);
4400#endif
4401
4402 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004403
Greg Clayton7bc39082011-03-24 23:53:38 +00004404 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004405 {
4406 uint32_t n;
4407 uint32_t registers = 0;
4408 bool wback;
4409 const uint32_t addr_byte_size = GetAddressByteSize();
4410
4411 // EncodingSpecificOperations();
4412 switch (encoding)
4413 {
4414 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004415 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004416 n = Bits32 (opcode, 19, 16);
4417 registers = Bits32 (opcode, 15, 0);
4418 wback = BitIsSet (opcode, 21);
4419
4420 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4421 if ((n == 15) && (BitCount (registers) < 1))
4422 return false;
4423 break;
4424 default:
4425 return false;
4426 }
4427 // address = R[n] + 4;
4428
4429 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004430 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004431 if (!success)
4432 return false;
4433
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004434 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004435
4436 EmulateInstruction::Context context;
4437 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004438 RegisterInfo base_reg;
4439 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004440
4441 uint32_t lowest_set_bit = 14;
4442 // for i = 0 to 14
4443 for (int i = 0; i < 14; ++i)
4444 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004445 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004446 if (BitIsSet (registers, i))
4447 {
4448 if (i < lowest_set_bit)
4449 lowest_set_bit = i;
4450 // if i == n && wback && i != LowestSetBit(registers) then
4451 if ((i == n) && wback && (i != lowest_set_bit))
4452 // MemA[address,4] = bits(32) UNKNOWN;
4453 WriteBits32UnknownToMemory (address + offset);
4454 // else
4455 else
4456 {
4457 // MemA[address,4] = R[i];
4458 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4459 if (!success)
4460 return false;
4461
Greg Claytonc07d4512011-04-26 23:48:45 +00004462 RegisterInfo data_reg;
4463 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004464 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004465 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004466 return false;
4467 }
4468
4469 // address = address + 4;
4470 offset += addr_byte_size;
4471 }
4472 }
4473
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004474 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004475 // MemA[address,4] = PCStoreValue();
4476 if (BitIsSet (registers, 15))
4477 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004478 RegisterInfo pc_reg;
4479 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004480 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004481 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004482 if (!success)
4483 return false;
4484
Caroline Tice8d681f52011-03-17 23:50:16 +00004485 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004486 return false;
4487 }
4488
4489 // if wback then R[n] = R[n] + 4*BitCount(registers);
4490 if (wback)
4491 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004492 offset = addr_byte_size * BitCount (registers);
4493 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4494 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004495 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004496 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4497 return false;
4498 }
4499 }
4500 return true;
4501}
Caroline Tice7fac8572011-02-15 22:53:54 +00004502
4503// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4504// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4505bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004506EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004507{
4508#if 0
4509 if ConditionPassed() then
4510 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4511 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4512 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004513 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004514 MemU[address,4] = R[t];
4515 else // Can only occur before ARMv7
4516 MemU[address,4] = bits(32) UNKNOWN;
4517 if wback then R[n] = offset_addr;
4518#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004519
Caroline Tice7fac8572011-02-15 22:53:54 +00004520 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004521
Greg Clayton7bc39082011-03-24 23:53:38 +00004522 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004523 {
4524 const uint32_t addr_byte_size = GetAddressByteSize();
4525
4526 uint32_t t;
4527 uint32_t n;
4528 uint32_t imm32;
4529 bool index;
4530 bool add;
4531 bool wback;
4532 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4533 switch (encoding)
4534 {
4535 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004536 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004537 t = Bits32 (opcode, 2, 0);
4538 n = Bits32 (opcode, 5, 3);
4539 imm32 = Bits32 (opcode, 10, 6) << 2;
4540
4541 // index = TRUE; add = TRUE; wback = FALSE;
4542 index = true;
4543 add = false;
4544 wback = false;
4545 break;
4546
4547 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004548 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004549 t = Bits32 (opcode, 10, 8);
4550 n = 13;
4551 imm32 = Bits32 (opcode, 7, 0) << 2;
4552
4553 // index = TRUE; add = TRUE; wback = FALSE;
4554 index = true;
4555 add = true;
4556 wback = false;
4557 break;
4558
4559 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004560 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004561 if (Bits32 (opcode, 19, 16) == 15)
4562 return false;
4563
4564 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4565 t = Bits32 (opcode, 15, 12);
4566 n = Bits32 (opcode, 19, 16);
4567 imm32 = Bits32 (opcode, 11, 0);
4568
4569 // index = TRUE; add = TRUE; wback = FALSE;
4570 index = true;
4571 add = true;
4572 wback = false;
4573
4574 // if t == 15 then UNPREDICTABLE;
4575 if (t == 15)
4576 return false;
4577 break;
4578
4579 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004580 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4581 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4582 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004583 if ((Bits32 (opcode, 19, 16) == 15)
4584 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4585 return false;
4586
4587 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4588 t = Bits32 (opcode, 15, 12);
4589 n = Bits32 (opcode, 19, 16);
4590 imm32 = Bits32 (opcode, 7, 0);
4591
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004592 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004593 index = BitIsSet (opcode, 10);
4594 add = BitIsSet (opcode, 9);
4595 wback = BitIsSet (opcode, 8);
4596
4597 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4598 if ((t == 15) || (wback && (n == t)))
4599 return false;
4600 break;
4601
4602 default:
4603 return false;
4604 }
4605
4606 addr_t offset_addr;
4607 addr_t address;
4608
4609 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004610 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004611 if (!success)
4612 return false;
4613
4614 if (add)
4615 offset_addr = base_address + imm32;
4616 else
4617 offset_addr = base_address - imm32;
4618
4619 // address = if index then offset_addr else R[n];
4620 if (index)
4621 address = offset_addr;
4622 else
4623 address = base_address;
4624
4625 EmulateInstruction::Context context;
4626 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004627 RegisterInfo base_reg;
4628 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004629
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004630 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004631 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4632 {
4633 // MemU[address,4] = R[t];
4634 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4635 if (!success)
4636 return false;
4637
Greg Claytonc07d4512011-04-26 23:48:45 +00004638 RegisterInfo data_reg;
4639 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004640 int32_t offset = address - base_address;
4641 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004642 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004643 return false;
4644 }
4645 else
4646 {
4647 // MemU[address,4] = bits(32) UNKNOWN;
4648 WriteBits32UnknownToMemory (address);
4649 }
4650
4651 // if wback then R[n] = offset_addr;
4652 if (wback)
4653 {
4654 context.type = eContextRegisterLoad;
4655 context.SetAddress (offset_addr);
4656 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4657 return false;
4658 }
4659 }
4660 return true;
4661}
Caroline Ticeaf556562011-02-15 18:42:15 +00004662
Caroline Tice3fd63e92011-02-16 00:33:43 +00004663// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4664// word from a register to memory. The offset register value can optionally be shifted.
4665bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004666EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004667{
4668#if 0
4669 if ConditionPassed() then
4670 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4671 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4672 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4673 address = if index then offset_addr else R[n];
4674 if t == 15 then // Only possible for encoding A1
4675 data = PCStoreValue();
4676 else
4677 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004678 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004679 MemU[address,4] = data;
4680 else // Can only occur before ARMv7
4681 MemU[address,4] = bits(32) UNKNOWN;
4682 if wback then R[n] = offset_addr;
4683#endif
4684
4685 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004686
Greg Clayton7bc39082011-03-24 23:53:38 +00004687 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004688 {
4689 const uint32_t addr_byte_size = GetAddressByteSize();
4690
4691 uint32_t t;
4692 uint32_t n;
4693 uint32_t m;
4694 ARM_ShifterType shift_t;
4695 uint32_t shift_n;
4696 bool index;
4697 bool add;
4698 bool wback;
4699
4700 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4701 switch (encoding)
4702 {
4703 case eEncodingT1:
4704 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4705 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4706 t = Bits32 (opcode, 2, 0);
4707 n = Bits32 (opcode, 5, 3);
4708 m = Bits32 (opcode, 8, 6);
4709
4710 // index = TRUE; add = TRUE; wback = FALSE;
4711 index = true;
4712 add = true;
4713 wback = false;
4714
4715 // (shift_t, shift_n) = (SRType_LSL, 0);
4716 shift_t = SRType_LSL;
4717 shift_n = 0;
4718 break;
4719
4720 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004721 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004722 if (Bits32 (opcode, 19, 16) == 15)
4723 return false;
4724
4725 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4726 t = Bits32 (opcode, 15, 12);
4727 n = Bits32 (opcode, 19, 16);
4728 m = Bits32 (opcode, 3, 0);
4729
4730 // index = TRUE; add = TRUE; wback = FALSE;
4731 index = true;
4732 add = true;
4733 wback = false;
4734
4735 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4736 shift_t = SRType_LSL;
4737 shift_n = Bits32 (opcode, 5, 4);
4738
4739 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4740 if ((t == 15) || (BadReg (m)))
4741 return false;
4742 break;
4743
4744 case eEncodingA1:
4745 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004746 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004747 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4748 t = Bits32 (opcode, 15, 12);
4749 n = Bits32 (opcode, 19, 16);
4750 m = Bits32 (opcode, 3, 0);
4751
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004752 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004753 index = BitIsSet (opcode, 24);
4754 add = BitIsSet (opcode, 23);
4755 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4756
4757 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4758 uint32_t typ = Bits32 (opcode, 6, 5);
4759 uint32_t imm5 = Bits32 (opcode, 11, 7);
4760 shift_n = DecodeImmShift(typ, imm5, shift_t);
4761
4762 // if m == 15 then UNPREDICTABLE;
4763 if (m == 15)
4764 return false;
4765
4766 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4767 if (wback && ((n == 15) || (n == t)))
4768 return false;
4769
4770 break;
4771 }
4772 default:
4773 return false;
4774 }
4775
4776 addr_t offset_addr;
4777 addr_t address;
4778 int32_t offset = 0;
4779
4780 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4781 if (!success)
4782 return false;
4783
4784 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4785 if (!success)
4786 return false;
4787
4788 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00004789 offset = Shift (Rm_data, shift_t, shift_n, APSR_C, &success);
4790 if (!success)
4791 return false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004792
4793 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4794 if (add)
4795 offset_addr = base_address + offset;
4796 else
4797 offset_addr = base_address - offset;
4798
4799 // address = if index then offset_addr else R[n];
4800 if (index)
4801 address = offset_addr;
4802 else
4803 address = base_address;
4804
4805 uint32_t data;
4806 // if t == 15 then // Only possible for encoding A1
4807 if (t == 15)
4808 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004809 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004810 else
4811 // data = R[t];
4812 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4813
4814 if (!success)
4815 return false;
4816
4817 EmulateInstruction::Context context;
4818 context.type = eContextRegisterStore;
4819
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004820 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004821 if (UnalignedSupport ()
4822 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4823 || CurrentInstrSet() == eModeARM)
4824 {
4825 // MemU[address,4] = data;
4826
Greg Claytonc07d4512011-04-26 23:48:45 +00004827 RegisterInfo base_reg;
4828 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004829
Greg Claytonc07d4512011-04-26 23:48:45 +00004830 RegisterInfo data_reg;
4831 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004832
4833 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004834 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004835 return false;
4836
4837 }
4838 else
4839 // MemU[address,4] = bits(32) UNKNOWN;
4840 WriteBits32UnknownToMemory (address);
4841
4842 // if wback then R[n] = offset_addr;
4843 if (wback)
4844 {
4845 context.type = eContextRegisterLoad;
4846 context.SetAddress (offset_addr);
4847 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4848 return false;
4849 }
4850
4851 }
4852 return true;
4853}
Caroline Tice73a29de2011-02-16 20:22:22 +00004854
4855bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004856EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004857{
4858#if 0
4859 if ConditionPassed() then
4860 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4861 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4862 address = if index then offset_addr else R[n];
4863 MemU[address,1] = R[t]<7:0>;
4864 if wback then R[n] = offset_addr;
4865#endif
4866
4867
4868 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004869
Greg Clayton7bc39082011-03-24 23:53:38 +00004870 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004871 {
4872 uint32_t t;
4873 uint32_t n;
4874 uint32_t imm32;
4875 bool index;
4876 bool add;
4877 bool wback;
4878 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4879 switch (encoding)
4880 {
4881 case eEncodingT1:
4882 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4883 t = Bits32 (opcode, 2, 0);
4884 n = Bits32 (opcode, 5, 3);
4885 imm32 = Bits32 (opcode, 10, 6);
4886
4887 // index = TRUE; add = TRUE; wback = FALSE;
4888 index = true;
4889 add = true;
4890 wback = false;
4891 break;
4892
4893 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004894 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004895 if (Bits32 (opcode, 19, 16) == 15)
4896 return false;
4897
4898 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4899 t = Bits32 (opcode, 15, 12);
4900 n = Bits32 (opcode, 19, 16);
4901 imm32 = Bits32 (opcode, 11, 0);
4902
4903 // index = TRUE; add = TRUE; wback = FALSE;
4904 index = true;
4905 add = true;
4906 wback = false;
4907
4908 // if BadReg(t) then UNPREDICTABLE;
4909 if (BadReg (t))
4910 return false;
4911 break;
4912
4913 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004914 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4915 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004916 if (Bits32 (opcode, 19, 16) == 15)
4917 return false;
4918
4919 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4920 t = Bits32 (opcode, 15, 12);
4921 n = Bits32 (opcode, 19, 16);
4922 imm32 = Bits32 (opcode, 7, 0);
4923
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004924 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004925 index = BitIsSet (opcode, 10);
4926 add = BitIsSet (opcode, 9);
4927 wback = BitIsSet (opcode, 8);
4928
4929 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4930 if ((BadReg (t)) || (wback && (n == t)))
4931 return false;
4932 break;
4933
4934 default:
4935 return false;
4936 }
4937
4938 addr_t offset_addr;
4939 addr_t address;
4940 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4941 if (!success)
4942 return false;
4943
4944 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4945 if (add)
4946 offset_addr = base_address + imm32;
4947 else
4948 offset_addr = base_address - imm32;
4949
4950 // address = if index then offset_addr else R[n];
4951 if (index)
4952 address = offset_addr;
4953 else
4954 address = base_address;
4955
Caroline Ticecc96eb52011-02-17 19:20:40 +00004956 // MemU[address,1] = R[t]<7:0>
Greg Claytonc07d4512011-04-26 23:48:45 +00004957 RegisterInfo base_reg;
4958 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004959
Greg Claytonc07d4512011-04-26 23:48:45 +00004960 RegisterInfo data_reg;
4961 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004962
4963 EmulateInstruction::Context context;
4964 context.type = eContextRegisterStore;
4965 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4966
4967 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4968 if (!success)
4969 return false;
4970
4971 data = Bits32 (data, 7, 0);
4972
Caroline Ticecc96eb52011-02-17 19:20:40 +00004973 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004974 return false;
4975
4976 // if wback then R[n] = offset_addr;
4977 if (wback)
4978 {
4979 context.type = eContextRegisterLoad;
4980 context.SetAddress (offset_addr);
4981 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4982 return false;
4983 }
4984
4985 }
4986
4987 return true;
4988}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004989
4990// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4991// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4992bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004993EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004994{
4995#if 0
4996 if ConditionPassed() then
4997 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4998 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4999 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5000 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005001 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005002 MemU[address,2] = R[t]<15:0>;
5003 else // Can only occur before ARMv7
5004 MemU[address,2] = bits(16) UNKNOWN;
5005 if wback then R[n] = offset_addr;
5006#endif
5007
5008 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005009
Greg Clayton7bc39082011-03-24 23:53:38 +00005010 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00005011 {
5012 uint32_t t;
5013 uint32_t n;
5014 uint32_t m;
5015 bool index;
5016 bool add;
5017 bool wback;
5018 ARM_ShifterType shift_t;
5019 uint32_t shift_n;
5020
5021 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5022 switch (encoding)
5023 {
5024 case eEncodingT1:
5025 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5026 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5027 t = Bits32 (opcode, 2, 0);
5028 n = Bits32 (opcode, 5, 3);
5029 m = Bits32 (opcode, 8, 6);
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, 0);
5037 shift_t = SRType_LSL;
5038 shift_n = 0;
5039
5040 break;
5041
5042 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005043 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005044 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5045 t = Bits32 (opcode, 15, 12);
5046 n = Bits32 (opcode, 19, 16);
5047 m = Bits32 (opcode, 3, 0);
5048 if (n == 15)
5049 return false;
5050
5051 // index = TRUE; add = TRUE; wback = FALSE;
5052 index = true;
5053 add = true;
5054 wback = false;
5055
5056 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5057 shift_t = SRType_LSL;
5058 shift_n = Bits32 (opcode, 5, 4);
5059
5060 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5061 if (BadReg (t) || BadReg (m))
5062 return false;
5063
5064 break;
5065
5066 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005067 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005068 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5069 t = Bits32 (opcode, 15, 12);
5070 n = Bits32 (opcode, 19, 16);
5071 m = Bits32 (opcode, 3, 0);
5072
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005073 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005074 index = BitIsSet (opcode, 24);
5075 add = BitIsSet (opcode, 23);
5076 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5077
5078 // (shift_t, shift_n) = (SRType_LSL, 0);
5079 shift_t = SRType_LSL;
5080 shift_n = 0;
5081
5082 // if t == 15 || m == 15 then UNPREDICTABLE;
5083 if ((t == 15) || (m == 15))
5084 return false;
5085
5086 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5087 if (wback && ((n == 15) || (n == t)))
5088 return false;
5089
5090 break;
5091
5092 default:
5093 return false;
5094 }
5095
5096 uint32_t Rm = ReadCoreReg (m, &success);
5097 if (!success)
5098 return false;
5099
5100 uint32_t Rn = ReadCoreReg (n, &success);
5101 if (!success)
5102 return false;
5103
5104 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00005105 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
5106 if (!success)
5107 return false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005108
5109 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5110 addr_t offset_addr;
5111 if (add)
5112 offset_addr = Rn + offset;
5113 else
5114 offset_addr = Rn - offset;
5115
5116 // address = if index then offset_addr else R[n];
5117 addr_t address;
5118 if (index)
5119 address = offset_addr;
5120 else
5121 address = Rn;
5122
5123 EmulateInstruction::Context context;
5124 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005125 RegisterInfo base_reg;
5126 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5127 RegisterInfo offset_reg;
5128 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005129
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005130 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005131 if (UnalignedSupport() || BitIsClear (address, 0))
5132 {
5133 // MemU[address,2] = R[t]<15:0>;
5134 uint32_t Rt = ReadCoreReg (t, &success);
5135 if (!success)
5136 return false;
5137
5138 EmulateInstruction::Context context;
5139 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005140 RegisterInfo base_reg;
5141 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5142 RegisterInfo offset_reg;
5143 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5144 RegisterInfo data_reg;
5145 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005146 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5147
5148 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5149 return false;
5150 }
5151 else // Can only occur before ARMv7
5152 {
5153 // MemU[address,2] = bits(16) UNKNOWN;
5154 }
5155
5156 // if wback then R[n] = offset_addr;
5157 if (wback)
5158 {
5159 context.type = eContextAdjustBaseRegister;
5160 context.SetAddress (offset_addr);
5161 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5162 return false;
5163 }
5164 }
5165
5166 return true;
5167}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005168
Johnny Chen157b9592011-02-18 21:13:05 +00005169// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5170// and writes the result to the destination register. It can optionally update the condition flags
5171// based on the result.
5172bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005173EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005174{
5175#if 0
5176 // ARM pseudo code...
5177 if ConditionPassed() then
5178 EncodingSpecificOperations();
5179 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5180 if d == 15 then // Can only occur for ARM encoding
5181 ALUWritePC(result); // setflags is always FALSE here
5182 else
5183 R[d] = result;
5184 if setflags then
5185 APSR.N = result<31>;
5186 APSR.Z = IsZeroBit(result);
5187 APSR.C = carry;
5188 APSR.V = overflow;
5189#endif
5190
5191 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005192
Greg Clayton7bc39082011-03-24 23:53:38 +00005193 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005194 {
5195 uint32_t Rd, Rn;
5196 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5197 bool setflags;
5198 switch (encoding)
5199 {
5200 case eEncodingT1:
5201 Rd = Bits32(opcode, 11, 8);
5202 Rn = Bits32(opcode, 19, 16);
5203 setflags = BitIsSet(opcode, 20);
5204 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5205 if (BadReg(Rd) || BadReg(Rn))
5206 return false;
5207 break;
5208 case eEncodingA1:
5209 Rd = Bits32(opcode, 15, 12);
5210 Rn = Bits32(opcode, 19, 16);
5211 setflags = BitIsSet(opcode, 20);
5212 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005213
Johnny Chen157b9592011-02-18 21:13:05 +00005214 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005215 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005216 break;
5217 default:
5218 return false;
5219 }
5220
5221 // Read the first operand.
5222 int32_t val1 = ReadCoreReg(Rn, &success);
5223 if (!success)
5224 return false;
5225
5226 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5227
5228 EmulateInstruction::Context context;
5229 context.type = EmulateInstruction::eContextImmediate;
5230 context.SetNoArgs ();
5231
5232 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5233 return false;
5234 }
5235 return true;
5236}
5237
5238// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5239// register value, and writes the result to the destination register. It can optionally update the
5240// condition flags based on the result.
5241bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005242EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005243{
5244#if 0
5245 // ARM pseudo code...
5246 if ConditionPassed() then
5247 EncodingSpecificOperations();
5248 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5249 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5250 if d == 15 then // Can only occur for ARM encoding
5251 ALUWritePC(result); // setflags is always FALSE here
5252 else
5253 R[d] = result;
5254 if setflags then
5255 APSR.N = result<31>;
5256 APSR.Z = IsZeroBit(result);
5257 APSR.C = carry;
5258 APSR.V = overflow;
5259#endif
5260
5261 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005262
Greg Clayton7bc39082011-03-24 23:53:38 +00005263 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005264 {
5265 uint32_t Rd, Rn, Rm;
5266 ARM_ShifterType shift_t;
5267 uint32_t shift_n; // the shift applied to the value read from Rm
5268 bool setflags;
5269 switch (encoding)
5270 {
5271 case eEncodingT1:
5272 Rd = Rn = Bits32(opcode, 2, 0);
5273 Rm = Bits32(opcode, 5, 3);
5274 setflags = !InITBlock();
5275 shift_t = SRType_LSL;
5276 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005277 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005278 case eEncodingT2:
5279 Rd = Bits32(opcode, 11, 8);
5280 Rn = Bits32(opcode, 19, 16);
5281 Rm = Bits32(opcode, 3, 0);
5282 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005283 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005284 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5285 return false;
5286 break;
5287 case eEncodingA1:
5288 Rd = Bits32(opcode, 15, 12);
5289 Rn = Bits32(opcode, 19, 16);
5290 Rm = Bits32(opcode, 3, 0);
5291 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005292 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005293
Johnny Chen157b9592011-02-18 21:13:05 +00005294 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005295 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005296 break;
5297 default:
5298 return false;
5299 }
5300
5301 // Read the first operand.
5302 int32_t val1 = ReadCoreReg(Rn, &success);
5303 if (!success)
5304 return false;
5305
5306 // Read the second operand.
5307 int32_t val2 = ReadCoreReg(Rm, &success);
5308 if (!success)
5309 return false;
5310
Johnny Chena4438a72011-06-02 22:50:51 +00005311 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5312 if (!success)
5313 return false;
Johnny Chen157b9592011-02-18 21:13:05 +00005314 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5315
5316 EmulateInstruction::Context context;
5317 context.type = EmulateInstruction::eContextImmediate;
5318 context.SetNoArgs ();
5319
5320 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5321 return false;
5322 }
5323 return true;
5324}
5325
Johnny Chena695f952011-02-23 21:24:25 +00005326// This instruction adds an immediate value to the PC value to form a PC-relative address,
5327// and writes the result to the destination register.
5328bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005329EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005330{
5331#if 0
5332 // ARM pseudo code...
5333 if ConditionPassed() then
5334 EncodingSpecificOperations();
5335 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5336 if d == 15 then // Can only occur for ARM encodings
5337 ALUWritePC(result);
5338 else
5339 R[d] = result;
5340#endif
5341
5342 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005343
Greg Clayton7bc39082011-03-24 23:53:38 +00005344 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005345 {
5346 uint32_t Rd;
5347 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5348 bool add;
5349 switch (encoding)
5350 {
5351 case eEncodingT1:
5352 Rd = Bits32(opcode, 10, 8);
5353 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5354 break;
5355 case eEncodingT2:
5356 case eEncodingT3:
5357 Rd = Bits32(opcode, 11, 8);
5358 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5359 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5360 if (BadReg(Rd))
5361 return false;
5362 break;
5363 case eEncodingA1:
5364 case eEncodingA2:
5365 Rd = Bits32(opcode, 15, 12);
5366 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5367 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5368 break;
5369 default:
5370 return false;
5371 }
5372
5373 // Read the PC value.
5374 uint32_t pc = ReadCoreReg(PC_REG, &success);
5375 if (!success)
5376 return false;
5377
5378 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5379
5380 EmulateInstruction::Context context;
5381 context.type = EmulateInstruction::eContextImmediate;
5382 context.SetNoArgs ();
5383
5384 if (!WriteCoreReg(context, result, Rd))
5385 return false;
5386 }
5387 return true;
5388}
5389
Johnny Chene97c0d52011-02-18 19:32:20 +00005390// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5391// to the destination register. It can optionally update the condition flags based on the result.
5392bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005393EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005394{
5395#if 0
5396 // ARM pseudo code...
5397 if ConditionPassed() then
5398 EncodingSpecificOperations();
5399 result = R[n] AND imm32;
5400 if d == 15 then // Can only occur for ARM encoding
5401 ALUWritePC(result); // setflags is always FALSE here
5402 else
5403 R[d] = result;
5404 if setflags then
5405 APSR.N = result<31>;
5406 APSR.Z = IsZeroBit(result);
5407 APSR.C = carry;
5408 // APSR.V unchanged
5409#endif
5410
5411 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005412
Greg Clayton7bc39082011-03-24 23:53:38 +00005413 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005414 {
5415 uint32_t Rd, Rn;
5416 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5417 bool setflags;
5418 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5419 switch (encoding)
5420 {
5421 case eEncodingT1:
5422 Rd = Bits32(opcode, 11, 8);
5423 Rn = Bits32(opcode, 19, 16);
5424 setflags = BitIsSet(opcode, 20);
5425 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005426 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005427 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005428 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005429 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5430 return false;
5431 break;
5432 case eEncodingA1:
5433 Rd = Bits32(opcode, 15, 12);
5434 Rn = Bits32(opcode, 19, 16);
5435 setflags = BitIsSet(opcode, 20);
5436 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005437
Johnny Chene97c0d52011-02-18 19:32:20 +00005438 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005439 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005440 break;
5441 default:
5442 return false;
5443 }
5444
Johnny Chene97c0d52011-02-18 19:32:20 +00005445 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005446 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005447 if (!success)
5448 return false;
5449
5450 uint32_t result = val1 & imm32;
5451
5452 EmulateInstruction::Context context;
5453 context.type = EmulateInstruction::eContextImmediate;
5454 context.SetNoArgs ();
5455
5456 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5457 return false;
5458 }
5459 return true;
5460}
5461
5462// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5463// and writes the result to the destination register. It can optionally update the condition flags
5464// based on the result.
5465bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005466EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005467{
5468#if 0
5469 // ARM pseudo code...
5470 if ConditionPassed() then
5471 EncodingSpecificOperations();
5472 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5473 result = R[n] AND shifted;
5474 if d == 15 then // Can only occur for ARM encoding
5475 ALUWritePC(result); // setflags is always FALSE here
5476 else
5477 R[d] = result;
5478 if setflags then
5479 APSR.N = result<31>;
5480 APSR.Z = IsZeroBit(result);
5481 APSR.C = carry;
5482 // APSR.V unchanged
5483#endif
5484
5485 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005486
Greg Clayton7bc39082011-03-24 23:53:38 +00005487 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005488 {
5489 uint32_t Rd, Rn, Rm;
5490 ARM_ShifterType shift_t;
5491 uint32_t shift_n; // the shift applied to the value read from Rm
5492 bool setflags;
5493 uint32_t carry;
5494 switch (encoding)
5495 {
5496 case eEncodingT1:
5497 Rd = Rn = Bits32(opcode, 2, 0);
5498 Rm = Bits32(opcode, 5, 3);
5499 setflags = !InITBlock();
5500 shift_t = SRType_LSL;
5501 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005502 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005503 case eEncodingT2:
5504 Rd = Bits32(opcode, 11, 8);
5505 Rn = Bits32(opcode, 19, 16);
5506 Rm = Bits32(opcode, 3, 0);
5507 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005508 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005509 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005510 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005511 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005512 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5513 return false;
5514 break;
5515 case eEncodingA1:
5516 Rd = Bits32(opcode, 15, 12);
5517 Rn = Bits32(opcode, 19, 16);
5518 Rm = Bits32(opcode, 3, 0);
5519 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005520 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005521
Johnny Chene97c0d52011-02-18 19:32:20 +00005522 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005523 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005524 break;
5525 default:
5526 return false;
5527 }
5528
Johnny Chene97c0d52011-02-18 19:32:20 +00005529 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005530 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005531 if (!success)
5532 return false;
5533
5534 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005535 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005536 if (!success)
5537 return false;
5538
Johnny Chena4438a72011-06-02 22:50:51 +00005539 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5540 if (!success)
5541 return false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005542 uint32_t result = val1 & shifted;
5543
5544 EmulateInstruction::Context context;
5545 context.type = EmulateInstruction::eContextImmediate;
5546 context.SetNoArgs ();
5547
5548 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5549 return false;
5550 }
5551 return true;
5552}
5553
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005554// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5555// immediate value, and writes the result to the destination register. It can optionally update the
5556// condition flags based on the result.
5557bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005558EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005559{
5560#if 0
5561 // ARM pseudo code...
5562 if ConditionPassed() then
5563 EncodingSpecificOperations();
5564 result = R[n] AND NOT(imm32);
5565 if d == 15 then // Can only occur for ARM encoding
5566 ALUWritePC(result); // setflags is always FALSE here
5567 else
5568 R[d] = result;
5569 if setflags then
5570 APSR.N = result<31>;
5571 APSR.Z = IsZeroBit(result);
5572 APSR.C = carry;
5573 // APSR.V unchanged
5574#endif
5575
5576 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005577
Greg Clayton7bc39082011-03-24 23:53:38 +00005578 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005579 {
5580 uint32_t Rd, Rn;
5581 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5582 bool setflags;
5583 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5584 switch (encoding)
5585 {
5586 case eEncodingT1:
5587 Rd = Bits32(opcode, 11, 8);
5588 Rn = Bits32(opcode, 19, 16);
5589 setflags = BitIsSet(opcode, 20);
5590 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5591 if (BadReg(Rd) || BadReg(Rn))
5592 return false;
5593 break;
5594 case eEncodingA1:
5595 Rd = Bits32(opcode, 15, 12);
5596 Rn = Bits32(opcode, 19, 16);
5597 setflags = BitIsSet(opcode, 20);
5598 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005599
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005600 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005601 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005602 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005603 break;
5604 default:
5605 return false;
5606 }
5607
5608 // Read the first operand.
5609 uint32_t val1 = ReadCoreReg(Rn, &success);
5610 if (!success)
5611 return false;
5612
5613 uint32_t result = val1 & ~imm32;
5614
5615 EmulateInstruction::Context context;
5616 context.type = EmulateInstruction::eContextImmediate;
5617 context.SetNoArgs ();
5618
5619 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5620 return false;
5621 }
5622 return true;
5623}
5624
5625// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5626// optionally-shifted register value, and writes the result to the destination register.
5627// It can optionally update the condition flags based on the result.
5628bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005629EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005630{
5631#if 0
5632 // ARM pseudo code...
5633 if ConditionPassed() then
5634 EncodingSpecificOperations();
5635 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5636 result = R[n] AND NOT(shifted);
5637 if d == 15 then // Can only occur for ARM encoding
5638 ALUWritePC(result); // setflags is always FALSE here
5639 else
5640 R[d] = result;
5641 if setflags then
5642 APSR.N = result<31>;
5643 APSR.Z = IsZeroBit(result);
5644 APSR.C = carry;
5645 // APSR.V unchanged
5646#endif
5647
5648 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005649
Greg Clayton7bc39082011-03-24 23:53:38 +00005650 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005651 {
5652 uint32_t Rd, Rn, Rm;
5653 ARM_ShifterType shift_t;
5654 uint32_t shift_n; // the shift applied to the value read from Rm
5655 bool setflags;
5656 uint32_t carry;
5657 switch (encoding)
5658 {
5659 case eEncodingT1:
5660 Rd = Rn = Bits32(opcode, 2, 0);
5661 Rm = Bits32(opcode, 5, 3);
5662 setflags = !InITBlock();
5663 shift_t = SRType_LSL;
5664 shift_n = 0;
5665 break;
5666 case eEncodingT2:
5667 Rd = Bits32(opcode, 11, 8);
5668 Rn = Bits32(opcode, 19, 16);
5669 Rm = Bits32(opcode, 3, 0);
5670 setflags = BitIsSet(opcode, 20);
5671 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5672 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5673 return false;
5674 break;
5675 case eEncodingA1:
5676 Rd = Bits32(opcode, 15, 12);
5677 Rn = Bits32(opcode, 19, 16);
5678 Rm = Bits32(opcode, 3, 0);
5679 setflags = BitIsSet(opcode, 20);
5680 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005681
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005682 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005683 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005684 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005685 break;
5686 default:
5687 return false;
5688 }
5689
5690 // Read the first operand.
5691 uint32_t val1 = ReadCoreReg(Rn, &success);
5692 if (!success)
5693 return false;
5694
5695 // Read the second operand.
5696 uint32_t val2 = ReadCoreReg(Rm, &success);
5697 if (!success)
5698 return false;
5699
Johnny Chena4438a72011-06-02 22:50:51 +00005700 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5701 if (!success)
5702 return false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005703 uint32_t result = val1 & ~shifted;
5704
5705 EmulateInstruction::Context context;
5706 context.type = EmulateInstruction::eContextImmediate;
5707 context.SetNoArgs ();
5708
5709 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5710 return false;
5711 }
5712 return true;
5713}
5714
Caroline Tice4d729c52011-02-18 00:55:53 +00005715// 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 +00005716// 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 +00005717bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005718EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005719{
5720#if 0
5721 if ConditionPassed() then
5722 EncodingSpecificOperations();
5723 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5724 address = if index then offset_addr else R[n];
5725 data = MemU[address,4];
5726 if wback then R[n] = offset_addr;
5727 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005728 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5729 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005730 R[t] = data;
5731 else // Can only apply before ARMv7
5732 R[t] = ROR(data, 8*UInt(address<1:0>));
5733#endif
5734
5735 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005736
Greg Clayton7bc39082011-03-24 23:53:38 +00005737 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005738 {
5739 const uint32_t addr_byte_size = GetAddressByteSize();
5740
5741 uint32_t t;
5742 uint32_t n;
5743 uint32_t imm32;
5744 bool index;
5745 bool add;
5746 bool wback;
5747
5748 switch (encoding)
5749 {
5750 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005751 // if Rn == '1111' then SEE LDR (literal);
5752 // if P == '0' && W == '1' then SEE LDRT;
5753 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005754 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5755 t = Bits32 (opcode, 15, 12);
5756 n = Bits32 (opcode, 19, 16);
5757 imm32 = Bits32 (opcode, 11, 0);
5758
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005759 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5760 index = BitIsSet (opcode, 24);
5761 add = BitIsSet (opcode, 23);
5762 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005763
5764 // if wback && n == t then UNPREDICTABLE;
5765 if (wback && (n == t))
5766 return false;
5767
5768 break;
5769
5770 default:
5771 return false;
5772 }
5773
5774 addr_t address;
5775 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005776 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005777 if (!success)
5778 return false;
5779
5780 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5781 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005782 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005783 else
5784 offset_addr = base_address - imm32;
5785
5786 // address = if index then offset_addr else R[n];
5787 if (index)
5788 address = offset_addr;
5789 else
5790 address = base_address;
5791
5792 // data = MemU[address,4];
5793
Greg Claytonc07d4512011-04-26 23:48:45 +00005794 RegisterInfo base_reg;
5795 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4d729c52011-02-18 00:55:53 +00005796
5797 EmulateInstruction::Context context;
5798 context.type = eContextRegisterLoad;
5799 context.SetRegisterPlusOffset (base_reg, address - base_address);
5800
5801 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5802 if (!success)
5803 return false;
5804
5805 // if wback then R[n] = offset_addr;
5806 if (wback)
5807 {
5808 context.type = eContextAdjustBaseRegister;
5809 context.SetAddress (offset_addr);
5810 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5811 return false;
5812 }
5813
5814 // if t == 15 then
5815 if (t == 15)
5816 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005817 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005818 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5819 {
5820 // LoadWritePC (data);
5821 context.type = eContextRegisterLoad;
5822 context.SetRegisterPlusOffset (base_reg, address - base_address);
5823 LoadWritePC (context, data);
5824 }
5825 else
5826 return false;
5827 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005828 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005829 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5830 {
5831 // R[t] = data;
5832 context.type = eContextRegisterLoad;
5833 context.SetRegisterPlusOffset (base_reg, address - base_address);
5834 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5835 return false;
5836 }
5837 // else // Can only apply before ARMv7
5838 else
5839 {
5840 // R[t] = ROR(data, 8*UInt(address<1:0>));
Johnny Chena4438a72011-06-02 22:50:51 +00005841 data = ROR (data, Bits32 (address, 1, 0), &success);
5842 if (!success)
5843 return false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005844 context.type = eContextRegisterLoad;
5845 context.SetImmediate (data);
5846 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5847 return false;
5848 }
5849
5850 }
5851 return true;
5852}
5853
Caroline Ticefe479112011-02-18 18:52:37 +00005854// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5855// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5856bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005857EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005858{
5859#if 0
5860 if ConditionPassed() then
5861 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5862 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5863 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5864 address = if index then offset_addr else R[n];
5865 data = MemU[address,4];
5866 if wback then R[n] = offset_addr;
5867 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005868 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5869 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005870 R[t] = data;
5871 else // Can only apply before ARMv7
5872 if CurrentInstrSet() == InstrSet_ARM then
5873 R[t] = ROR(data, 8*UInt(address<1:0>));
5874 else
5875 R[t] = bits(32) UNKNOWN;
5876#endif
5877
5878 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005879
Greg Clayton7bc39082011-03-24 23:53:38 +00005880 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005881 {
5882 const uint32_t addr_byte_size = GetAddressByteSize();
5883
5884 uint32_t t;
5885 uint32_t n;
5886 uint32_t m;
5887 bool index;
5888 bool add;
5889 bool wback;
5890 ARM_ShifterType shift_t;
5891 uint32_t shift_n;
5892
5893 switch (encoding)
5894 {
5895 case eEncodingT1:
5896 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5897 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5898 t = Bits32 (opcode, 2, 0);
5899 n = Bits32 (opcode, 5, 3);
5900 m = Bits32 (opcode, 8, 6);
5901
5902 // index = TRUE; add = TRUE; wback = FALSE;
5903 index = true;
5904 add = true;
5905 wback = false;
5906
5907 // (shift_t, shift_n) = (SRType_LSL, 0);
5908 shift_t = SRType_LSL;
5909 shift_n = 0;
5910
5911 break;
5912
5913 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005914 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005915 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5916 t = Bits32 (opcode, 15, 12);
5917 n = Bits32 (opcode, 19, 16);
5918 m = Bits32 (opcode, 3, 0);
5919
5920 // index = TRUE; add = TRUE; wback = FALSE;
5921 index = true;
5922 add = true;
5923 wback = false;
5924
5925 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5926 shift_t = SRType_LSL;
5927 shift_n = Bits32 (opcode, 5, 4);
5928
5929 // if BadReg(m) then UNPREDICTABLE;
5930 if (BadReg (m))
5931 return false;
5932
5933 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5934 if ((t == 15) && InITBlock() && !LastInITBlock())
5935 return false;
5936
5937 break;
5938
5939 case eEncodingA1:
5940 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005941 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005942 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5943 t = Bits32 (opcode, 15, 12);
5944 n = Bits32 (opcode, 19, 16);
5945 m = Bits32 (opcode, 3, 0);
5946
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005947 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005948 index = BitIsSet (opcode, 24);
5949 add = BitIsSet (opcode, 23);
5950 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5951
5952 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5953 uint32_t type = Bits32 (opcode, 6, 5);
5954 uint32_t imm5 = Bits32 (opcode, 11, 7);
5955 shift_n = DecodeImmShift (type, imm5, shift_t);
5956
5957 // if m == 15 then UNPREDICTABLE;
5958 if (m == 15)
5959 return false;
5960
5961 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5962 if (wback && ((n == 15) || (n == t)))
5963 return false;
5964 }
5965 break;
5966
5967
5968 default:
5969 return false;
5970 }
5971
5972 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5973 if (!success)
5974 return false;
5975
5976 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5977 if (!success)
5978 return false;
5979
5980 addr_t offset_addr;
5981 addr_t address;
5982
5983 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Johnny Chena4438a72011-06-02 22:50:51 +00005984 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C), &success);
5985 if (!success)
5986 return false;
Caroline Ticefe479112011-02-18 18:52:37 +00005987
5988 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5989 if (add)
5990 offset_addr = Rn + offset;
5991 else
5992 offset_addr = Rn - offset;
5993
5994 // address = if index then offset_addr else R[n];
5995 if (index)
5996 address = offset_addr;
5997 else
5998 address = Rn;
5999
6000 // data = MemU[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +00006001 RegisterInfo base_reg;
6002 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefe479112011-02-18 18:52:37 +00006003
6004 EmulateInstruction::Context context;
6005 context.type = eContextRegisterLoad;
6006 context.SetRegisterPlusOffset (base_reg, address - Rn);
6007
6008 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
6009 if (!success)
6010 return false;
6011
6012 // if wback then R[n] = offset_addr;
6013 if (wback)
6014 {
6015 context.type = eContextAdjustBaseRegister;
6016 context.SetAddress (offset_addr);
6017 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6018 return false;
6019 }
6020
6021 // if t == 15 then
6022 if (t == 15)
6023 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006024 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00006025 if (BitIsClear (address, 1) && BitIsClear (address, 0))
6026 {
6027 context.type = eContextRegisterLoad;
6028 context.SetRegisterPlusOffset (base_reg, address - Rn);
6029 LoadWritePC (context, data);
6030 }
6031 else
6032 return false;
6033 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006034 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00006035 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
6036 {
6037 // R[t] = data;
6038 context.type = eContextRegisterLoad;
6039 context.SetRegisterPlusOffset (base_reg, address - Rn);
6040 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6041 return false;
6042 }
6043 else // Can only apply before ARMv7
6044 {
6045 // if CurrentInstrSet() == InstrSet_ARM then
6046 if (CurrentInstrSet () == eModeARM)
6047 {
6048 // R[t] = ROR(data, 8*UInt(address<1:0>));
Johnny Chena4438a72011-06-02 22:50:51 +00006049 data = ROR (data, Bits32 (address, 1, 0), &success);
6050 if (!success)
6051 return false;
Caroline Ticefe479112011-02-18 18:52:37 +00006052 context.type = eContextRegisterLoad;
6053 context.SetImmediate (data);
6054 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6055 return false;
6056 }
6057 else
6058 {
6059 // R[t] = bits(32) UNKNOWN;
6060 WriteBits32Unknown (t);
6061 }
6062 }
6063 }
6064 return true;
6065}
Caroline Tice21b604b2011-02-18 21:06:04 +00006066
6067// LDRB (immediate, Thumb)
6068bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006069EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00006070{
6071#if 0
6072 if ConditionPassed() then
6073 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6074 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6075 address = if index then offset_addr else R[n];
6076 R[t] = ZeroExtend(MemU[address,1], 32);
6077 if wback then R[n] = offset_addr;
6078#endif
6079
6080 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00006081
Greg Clayton7bc39082011-03-24 23:53:38 +00006082 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00006083 {
6084 uint32_t t;
6085 uint32_t n;
6086 uint32_t imm32;
6087 bool index;
6088 bool add;
6089 bool wback;
6090
6091 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6092 switch (encoding)
6093 {
6094 case eEncodingT1:
6095 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6096 t = Bits32 (opcode, 2, 0);
6097 n = Bits32 (opcode, 5, 3);
6098 imm32 = Bits32 (opcode, 10, 6);
6099
6100 // index = TRUE; add = TRUE; wback = FALSE;
6101 index = true;
6102 add = true;
6103 wback= false;
6104
6105 break;
6106
6107 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006108 // if Rt == '1111' then SEE PLD;
6109 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006110 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6111 t = Bits32 (opcode, 15, 12);
6112 n = Bits32 (opcode, 19, 16);
6113 imm32 = Bits32 (opcode, 11, 0);
6114
6115 // index = TRUE; add = TRUE; wback = FALSE;
6116 index = true;
6117 add = true;
6118 wback = false;
6119
6120 // if t == 13 then UNPREDICTABLE;
6121 if (t == 13)
6122 return false;
6123
6124 break;
6125
6126 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006127 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6128 // if Rn == '1111' then SEE LDRB (literal);
6129 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6130 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006131 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6132 return false;
6133
6134 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6135 t = Bits32 (opcode, 15, 12);
6136 n = Bits32 (opcode, 19, 16);
6137 imm32 = Bits32 (opcode, 7, 0);
6138
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006139 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006140 index = BitIsSet (opcode, 10);
6141 add = BitIsSet (opcode, 9);
6142 wback = BitIsSet (opcode, 8);
6143
6144 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6145 if (BadReg (t) || (wback && (n == t)))
6146 return false;
6147
6148 break;
6149
6150 default:
6151 return false;
6152 }
6153
6154 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6155 if (!success)
6156 return false;
6157
6158 addr_t address;
6159 addr_t offset_addr;
6160
6161 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6162 if (add)
6163 offset_addr = Rn + imm32;
6164 else
6165 offset_addr = Rn - imm32;
6166
6167 // address = if index then offset_addr else R[n];
6168 if (index)
6169 address = offset_addr;
6170 else
6171 address = Rn;
6172
6173 // R[t] = ZeroExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006174 RegisterInfo base_reg;
6175 RegisterInfo data_reg;
6176 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6177 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice21b604b2011-02-18 21:06:04 +00006178
6179 EmulateInstruction::Context context;
6180 context.type = eContextRegisterLoad;
6181 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6182
6183 uint64_t data = MemURead (context, address, 1, 0, &success);
6184 if (!success)
6185 return false;
6186
6187 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6188 return false;
6189
6190 // if wback then R[n] = offset_addr;
6191 if (wback)
6192 {
6193 context.type = eContextAdjustBaseRegister;
6194 context.SetAddress (offset_addr);
6195 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6196 return false;
6197 }
6198 }
6199 return true;
6200}
Caroline Ticef55261f2011-02-18 22:24:22 +00006201
6202// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6203// zero-extends it to form a 32-bit word and writes it to a register.
6204bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006205EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006206{
6207#if 0
6208 if ConditionPassed() then
6209 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6210 base = Align(PC,4);
6211 address = if add then (base + imm32) else (base - imm32);
6212 R[t] = ZeroExtend(MemU[address,1], 32);
6213#endif
6214
6215 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006216
Greg Clayton7bc39082011-03-24 23:53:38 +00006217 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006218 {
6219 uint32_t t;
6220 uint32_t imm32;
6221 bool add;
6222 switch (encoding)
6223 {
6224 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006225 // if Rt == '1111' then SEE PLD;
6226 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006227 t = Bits32 (opcode, 15, 12);
6228 imm32 = Bits32 (opcode, 11, 0);
6229 add = BitIsSet (opcode, 23);
6230
6231 // if t == 13 then UNPREDICTABLE;
6232 if (t == 13)
6233 return false;
6234
6235 break;
6236
6237 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006238 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006239 t = Bits32 (opcode, 15, 12);
6240 imm32 = Bits32 (opcode, 11, 0);
6241 add = BitIsSet (opcode, 23);
6242
6243 // if t == 15 then UNPREDICTABLE;
6244 if (t == 15)
6245 return false;
6246 break;
6247
6248 default:
6249 return false;
6250 }
6251
6252 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006253 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006254 if (!success)
6255 return false;
6256
6257 uint32_t base = AlignPC (pc_val);
6258
6259 addr_t address;
6260 // address = if add then (base + imm32) else (base - imm32);
6261 if (add)
6262 address = base + imm32;
6263 else
6264 address = base - imm32;
6265
6266 // R[t] = ZeroExtend(MemU[address,1], 32);
6267 EmulateInstruction::Context context;
6268 context.type = eContextRelativeBranchImmediate;
6269 context.SetImmediate (address - base);
6270
6271 uint64_t data = MemURead (context, address, 1, 0, &success);
6272 if (!success)
6273 return false;
6274
6275 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6276 return false;
6277 }
6278 return true;
6279}
Caroline Tice30fec122011-02-18 23:52:21 +00006280
6281// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6282// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6283// optionally be shifted.
6284bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006285EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006286{
6287#if 0
6288 if ConditionPassed() then
6289 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6290 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6291 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6292 address = if index then offset_addr else R[n];
6293 R[t] = ZeroExtend(MemU[address,1],32);
6294 if wback then R[n] = offset_addr;
6295#endif
6296
6297 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006298
Greg Clayton7bc39082011-03-24 23:53:38 +00006299 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006300 {
6301 uint32_t t;
6302 uint32_t n;
6303 uint32_t m;
6304 bool index;
6305 bool add;
6306 bool wback;
6307 ARM_ShifterType shift_t;
6308 uint32_t shift_n;
6309
6310 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6311 switch (encoding)
6312 {
6313 case eEncodingT1:
6314 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6315 t = Bits32 (opcode, 2, 0);
6316 n = Bits32 (opcode, 5, 3);
6317 m = Bits32 (opcode, 8, 6);
6318
6319 // index = TRUE; add = TRUE; wback = FALSE;
6320 index = true;
6321 add = true;
6322 wback = false;
6323
6324 // (shift_t, shift_n) = (SRType_LSL, 0);
6325 shift_t = SRType_LSL;
6326 shift_n = 0;
6327 break;
6328
6329 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006330 // if Rt == '1111' then SEE PLD;
6331 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006332 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6333 t = Bits32 (opcode, 15, 12);
6334 n = Bits32 (opcode, 19, 16);
6335 m = Bits32 (opcode, 3, 0);
6336
6337 // index = TRUE; add = TRUE; wback = FALSE;
6338 index = true;
6339 add = true;
6340 wback = false;
6341
6342 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6343 shift_t = SRType_LSL;
6344 shift_n = Bits32 (opcode, 5, 4);
6345
6346 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6347 if ((t == 13) || BadReg (m))
6348 return false;
6349 break;
6350
6351 case eEncodingA1:
6352 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006353 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006354 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6355 t = Bits32 (opcode, 15, 12);
6356 n = Bits32 (opcode, 19, 16);
6357 m = Bits32 (opcode, 3, 0);
6358
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006359 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006360 index = BitIsSet (opcode, 24);
6361 add = BitIsSet (opcode, 23);
6362 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6363
6364 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6365 uint32_t type = Bits32 (opcode, 6, 5);
6366 uint32_t imm5 = Bits32 (opcode, 11, 7);
6367 shift_n = DecodeImmShift (type, imm5, shift_t);
6368
6369 // if t == 15 || m == 15 then UNPREDICTABLE;
6370 if ((t == 15) || (m == 15))
6371 return false;
6372
6373 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6374 if (wback && ((n == 15) || (n == t)))
6375 return false;
6376 }
6377 break;
6378
6379 default:
6380 return false;
6381 }
6382
6383 addr_t offset_addr;
6384 addr_t address;
6385
6386 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6387 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6388 if (!success)
6389 return false;
6390
Johnny Chena4438a72011-06-02 22:50:51 +00006391 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6392 if (!success)
6393 return false;
Caroline Tice30fec122011-02-18 23:52:21 +00006394
6395 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6396 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6397 if (!success)
6398 return false;
6399
6400 if (add)
6401 offset_addr = Rn + offset;
6402 else
6403 offset_addr = Rn - offset;
6404
6405 // address = if index then offset_addr else R[n];
6406 if (index)
6407 address = offset_addr;
6408 else
6409 address = Rn;
6410
6411 // R[t] = ZeroExtend(MemU[address,1],32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006412 RegisterInfo base_reg;
6413 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice30fec122011-02-18 23:52:21 +00006414
6415 EmulateInstruction::Context context;
6416 context.type = eContextRegisterLoad;
6417 context.SetRegisterPlusOffset (base_reg, address - Rn);
6418
6419 uint64_t data = MemURead (context, address, 1, 0, &success);
6420 if (!success)
6421 return false;
6422
6423 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6424 return false;
6425
6426 // if wback then R[n] = offset_addr;
6427 if (wback)
6428 {
6429 context.type = eContextAdjustBaseRegister;
6430 context.SetAddress (offset_addr);
6431 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6432 return false;
6433 }
6434 }
6435 return true;
6436}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006437
6438// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6439// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6440// post-indexed, or pre-indexed addressing.
6441bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006442EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006443{
6444#if 0
6445 if ConditionPassed() then
6446 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6447 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6448 address = if index then offset_addr else R[n];
6449 data = MemU[address,2];
6450 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006451 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006452 R[t] = ZeroExtend(data, 32);
6453 else // Can only apply before ARMv7
6454 R[t] = bits(32) UNKNOWN;
6455#endif
6456
6457
6458 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006459
Greg Clayton7bc39082011-03-24 23:53:38 +00006460 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006461 {
6462 uint32_t t;
6463 uint32_t n;
6464 uint32_t imm32;
6465 bool index;
6466 bool add;
6467 bool wback;
6468
6469 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6470 switch (encoding)
6471 {
6472 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006473 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006474 t = Bits32 (opcode, 2, 0);
6475 n = Bits32 (opcode, 5, 3);
6476 imm32 = Bits32 (opcode, 10, 6) << 1;
6477
6478 // index = TRUE; add = TRUE; wback = FALSE;
6479 index = true;
6480 add = true;
6481 wback = false;
6482
6483 break;
6484
6485 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006486 // if Rt == '1111' then SEE "Unallocated memory hints";
6487 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006488 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6489 t = Bits32 (opcode, 15, 12);
6490 n = Bits32 (opcode, 19, 16);
6491 imm32 = Bits32 (opcode, 11, 0);
6492
6493 // index = TRUE; add = TRUE; wback = FALSE;
6494 index = true;
6495 add = true;
6496 wback = false;
6497
6498 // if t == 13 then UNPREDICTABLE;
6499 if (t == 13)
6500 return false;
6501 break;
6502
6503 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006504 // if Rn == '1111' then SEE LDRH (literal);
6505 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6506 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6507 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006508 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6509 return false;
6510
6511 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6512 t = Bits32 (opcode, 15, 12);
6513 n = Bits32 (opcode, 19, 16);
6514 imm32 = Bits32 (opcode, 7, 0);
6515
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006516 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006517 index = BitIsSet (opcode, 10);
6518 add = BitIsSet (opcode, 9);
6519 wback = BitIsSet (opcode, 8);
6520
6521 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6522 if (BadReg (t) || (wback && (n == t)))
6523 return false;
6524 break;
6525
6526 default:
6527 return false;
6528 }
6529
6530 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6531 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6532 if (!success)
6533 return false;
6534
6535 addr_t offset_addr;
6536 addr_t address;
6537
6538 if (add)
6539 offset_addr = Rn + imm32;
6540 else
6541 offset_addr = Rn - imm32;
6542
6543 // address = if index then offset_addr else R[n];
6544 if (index)
6545 address = offset_addr;
6546 else
6547 address = Rn;
6548
6549 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006550 RegisterInfo base_reg;
6551 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006552
6553 EmulateInstruction::Context context;
6554 context.type = eContextRegisterLoad;
6555 context.SetRegisterPlusOffset (base_reg, address - Rn);
6556
6557 uint64_t data = MemURead (context, address, 2, 0, &success);
6558 if (!success)
6559 return false;
6560
6561 // if wback then R[n] = offset_addr;
6562 if (wback)
6563 {
6564 context.type = eContextAdjustBaseRegister;
6565 context.SetAddress (offset_addr);
6566 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6567 return false;
6568 }
6569
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006570 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006571 if (UnalignedSupport () || BitIsClear (address, 0))
6572 {
6573 // R[t] = ZeroExtend(data, 32);
6574 context.type = eContextRegisterLoad;
6575 context.SetRegisterPlusOffset (base_reg, address - Rn);
6576 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6577 return false;
6578 }
6579 else // Can only apply before ARMv7
6580 {
6581 // R[t] = bits(32) UNKNOWN;
6582 WriteBits32Unknown (t);
6583 }
6584 }
6585 return true;
6586}
Caroline Ticefe479112011-02-18 18:52:37 +00006587
Caroline Tice952b5382011-02-28 23:15:24 +00006588// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6589// zero-extends it to form a 32-bit word, and writes it to a register.
6590bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006591EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006592{
6593#if 0
6594 if ConditionPassed() then
6595 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6596 base = Align(PC,4);
6597 address = if add then (base + imm32) else (base - imm32);
6598 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006599 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006600 R[t] = ZeroExtend(data, 32);
6601 else // Can only apply before ARMv7
6602 R[t] = bits(32) UNKNOWN;
6603#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006604
Caroline Tice952b5382011-02-28 23:15:24 +00006605 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006606
Greg Clayton7bc39082011-03-24 23:53:38 +00006607 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006608 {
6609 uint32_t t;
6610 uint32_t imm32;
6611 bool add;
6612
6613 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6614 switch (encoding)
6615 {
6616 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006617 // if Rt == '1111' then SEE "Unallocated memory hints";
6618 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006619 t = Bits32 (opcode, 15, 12);
6620 imm32 = Bits32 (opcode, 11, 0);
6621 add = BitIsSet (opcode, 23);
6622
6623 // if t == 13 then UNPREDICTABLE;
6624 if (t == 13)
6625 return false;
6626
6627 break;
6628
6629 case eEncodingA1:
6630 {
6631 uint32_t imm4H = Bits32 (opcode, 11, 8);
6632 uint32_t imm4L = Bits32 (opcode, 3, 0);
6633
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006634 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006635 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006636 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006637 add = BitIsSet (opcode, 23);
6638
6639 // if t == 15 then UNPREDICTABLE;
6640 if (t == 15)
6641 return false;
6642 break;
6643 }
6644
6645 default:
6646 return false;
6647 }
6648
6649 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006650 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006651 if (!success)
6652 return false;
6653
6654 addr_t base = AlignPC (pc_value);
6655 addr_t address;
6656
6657 // address = if add then (base + imm32) else (base - imm32);
6658 if (add)
6659 address = base + imm32;
6660 else
6661 address = base - imm32;
6662
6663 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006664 RegisterInfo base_reg;
6665 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice952b5382011-02-28 23:15:24 +00006666
6667 EmulateInstruction::Context context;
6668 context.type = eContextRegisterLoad;
6669 context.SetRegisterPlusOffset (base_reg, address - base);
6670
6671 uint64_t data = MemURead (context, address, 2, 0, &success);
6672 if (!success)
6673 return false;
6674
6675
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006676 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006677 if (UnalignedSupport () || BitIsClear (address, 0))
6678 {
6679 // R[t] = ZeroExtend(data, 32);
6680 context.type = eContextRegisterLoad;
6681 context.SetRegisterPlusOffset (base_reg, address - base);
6682 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6683 return false;
6684
6685 }
6686 else // Can only apply before ARMv7
6687 {
6688 // R[t] = bits(32) UNKNOWN;
6689 WriteBits32Unknown (t);
6690 }
6691 }
6692 return true;
6693}
6694
Caroline Tice0e6bc952011-03-01 18:00:42 +00006695// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6696// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6697// be shifted left by 0, 1, 2, or 3 bits.
6698bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006699EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006700{
6701#if 0
6702 if ConditionPassed() then
6703 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6704 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6705 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6706 address = if index then offset_addr else R[n];
6707 data = MemU[address,2];
6708 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006709 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006710 R[t] = ZeroExtend(data, 32);
6711 else // Can only apply before ARMv7
6712 R[t] = bits(32) UNKNOWN;
6713#endif
6714
6715 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006716
Greg Clayton7bc39082011-03-24 23:53:38 +00006717 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006718 {
6719 uint32_t t;
6720 uint32_t n;
6721 uint32_t m;
6722 bool index;
6723 bool add;
6724 bool wback;
6725 ARM_ShifterType shift_t;
6726 uint32_t shift_n;
6727
6728 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6729 switch (encoding)
6730 {
6731 case eEncodingT1:
6732 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6733 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6734 t = Bits32 (opcode, 2, 0);
6735 n = Bits32 (opcode, 5, 3);
6736 m = Bits32 (opcode, 8, 6);
6737
6738 // index = TRUE; add = TRUE; wback = FALSE;
6739 index = true;
6740 add = true;
6741 wback = false;
6742
6743 // (shift_t, shift_n) = (SRType_LSL, 0);
6744 shift_t = SRType_LSL;
6745 shift_n = 0;
6746
6747 break;
6748
6749 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006750 // if Rn == '1111' then SEE LDRH (literal);
6751 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006752 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6753 t = Bits32 (opcode, 15, 12);
6754 n = Bits32 (opcode, 19, 16);
6755 m = Bits32 (opcode, 3, 0);
6756
6757 // index = TRUE; add = TRUE; wback = FALSE;
6758 index = true;
6759 add = true;
6760 wback = false;
6761
6762 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6763 shift_t = SRType_LSL;
6764 shift_n = Bits32 (opcode, 5, 4);
6765
6766 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6767 if ((t == 13) || BadReg (m))
6768 return false;
6769 break;
6770
6771 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006772 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006773 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6774 t = Bits32 (opcode, 15, 12);
6775 n = Bits32 (opcode, 19, 16);
6776 m = Bits32 (opcode, 3, 0);
6777
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006778 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006779 index = BitIsSet (opcode, 24);
6780 add = BitIsSet (opcode, 23);
6781 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6782
6783 // (shift_t, shift_n) = (SRType_LSL, 0);
6784 shift_t = SRType_LSL;
6785 shift_n = 0;
6786
6787 // if t == 15 || m == 15 then UNPREDICTABLE;
6788 if ((t == 15) || (m == 15))
6789 return false;
6790
6791 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6792 if (wback && ((n == 15) || (n == t)))
6793 return false;
6794
6795 break;
6796
6797 default:
6798 return false;
6799 }
6800
6801 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6802
6803 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6804 if (!success)
6805 return false;
6806
Johnny Chena4438a72011-06-02 22:50:51 +00006807 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6808 if (!success)
6809 return false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006810
6811 addr_t offset_addr;
6812 addr_t address;
6813
6814 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6815 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6816 if (!success)
6817 return false;
6818
6819 if (add)
6820 offset_addr = Rn + offset;
6821 else
6822 offset_addr = Rn - offset;
6823
6824 // address = if index then offset_addr else R[n];
6825 if (index)
6826 address = offset_addr;
6827 else
6828 address = Rn;
6829
6830 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006831 RegisterInfo base_reg;
6832 RegisterInfo offset_reg;
6833 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6834 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice0e6bc952011-03-01 18:00:42 +00006835
6836 EmulateInstruction::Context context;
6837 context.type = eContextRegisterLoad;
6838 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6839 uint64_t data = MemURead (context, address, 2, 0, &success);
6840 if (!success)
6841 return false;
6842
6843 // if wback then R[n] = offset_addr;
6844 if (wback)
6845 {
6846 context.type = eContextAdjustBaseRegister;
6847 context.SetAddress (offset_addr);
6848 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6849 return false;
6850 }
6851
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006852 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006853 if (UnalignedSupport() || BitIsClear (address, 0))
6854 {
6855 // R[t] = ZeroExtend(data, 32);
6856 context.type = eContextRegisterLoad;
6857 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6858 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6859 return false;
6860 }
6861 else // Can only apply before ARMv7
6862 {
6863 // R[t] = bits(32) UNKNOWN;
6864 WriteBits32Unknown (t);
6865 }
6866 }
6867 return true;
6868}
6869
Caroline Ticea5e28af2011-03-01 21:53:03 +00006870// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6871// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6872// or pre-indexed addressing.
6873bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006874EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006875{
6876#if 0
6877 if ConditionPassed() then
6878 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6879 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6880 address = if index then offset_addr else R[n];
6881 R[t] = SignExtend(MemU[address,1], 32);
6882 if wback then R[n] = offset_addr;
6883#endif
6884
6885 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006886
Greg Clayton7bc39082011-03-24 23:53:38 +00006887 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006888 {
6889 uint32_t t;
6890 uint32_t n;
6891 uint32_t imm32;
6892 bool index;
6893 bool add;
6894 bool wback;
6895
6896 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6897 switch (encoding)
6898 {
6899 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006900 // if Rt == '1111' then SEE PLI;
6901 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006902 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6903 t = Bits32 (opcode, 15, 12);
6904 n = Bits32 (opcode, 19, 16);
6905 imm32 = Bits32 (opcode, 11, 0);
6906
6907 // index = TRUE; add = TRUE; wback = FALSE;
6908 index = true;
6909 add = true;
6910 wback = false;
6911
6912 // if t == 13 then UNPREDICTABLE;
6913 if (t == 13)
6914 return false;
6915
6916 break;
6917
6918 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006919 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6920 // if Rn == '1111' then SEE LDRSB (literal);
6921 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6922 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006923 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6924 return false;
6925
6926 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6927 t = Bits32 (opcode, 15, 12);
6928 n = Bits32 (opcode, 19, 16);
6929 imm32 = Bits32 (opcode, 7, 0);
6930
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006931 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006932 index = BitIsSet (opcode, 10);
6933 add = BitIsSet (opcode, 9);
6934 wback = BitIsSet (opcode, 8);
6935
6936 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006937 if (((t == 13) || ((t == 15)
6938 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6939 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006940 return false;
6941
6942 break;
6943
6944 case eEncodingA1:
6945 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006946 // if Rn == '1111' then SEE LDRSB (literal);
6947 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006948 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6949 t = Bits32 (opcode, 15, 12);
6950 n = Bits32 (opcode, 19, 16);
6951
6952 uint32_t imm4H = Bits32 (opcode, 11, 8);
6953 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006954 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006955
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006956 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006957 index = BitIsSet (opcode, 24);
6958 add = BitIsSet (opcode, 23);
6959 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6960
6961 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6962 if ((t == 15) || (wback && (n == t)))
6963 return false;
6964
6965 break;
6966 }
6967
6968 default:
6969 return false;
6970 }
6971
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006972 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006973 if (!success)
6974 return false;
6975
6976 addr_t offset_addr;
6977 addr_t address;
6978
6979 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6980 if (add)
6981 offset_addr = Rn + imm32;
6982 else
6983 offset_addr = Rn - imm32;
6984
6985 // address = if index then offset_addr else R[n];
6986 if (index)
6987 address = offset_addr;
6988 else
6989 address = Rn;
6990
6991 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006992 RegisterInfo base_reg;
6993 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006994
6995 EmulateInstruction::Context context;
6996 context.type = eContextRegisterLoad;
6997 context.SetRegisterPlusOffset (base_reg, address - Rn);
6998
6999 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7000 if (!success)
7001 return false;
7002
7003 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7004 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7005 return false;
7006
7007 // if wback then R[n] = offset_addr;
7008 if (wback)
7009 {
7010 context.type = eContextAdjustBaseRegister;
7011 context.SetAddress (offset_addr);
7012 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7013 return false;
7014 }
7015 }
7016
7017 return true;
7018}
Caroline Tice0e6bc952011-03-01 18:00:42 +00007019
Caroline Tice5f593912011-03-01 22:25:17 +00007020// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
7021// sign-extends it to form a 32-bit word, and writes tit to a register.
7022bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007023EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00007024{
7025#if 0
7026 if ConditionPassed() then
7027 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7028 base = Align(PC,4);
7029 address = if add then (base + imm32) else (base - imm32);
7030 R[t] = SignExtend(MemU[address,1], 32);
7031#endif
7032
7033 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00007034
Greg Clayton7bc39082011-03-24 23:53:38 +00007035 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00007036 {
7037 uint32_t t;
7038 uint32_t imm32;
7039 bool add;
7040
7041 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7042 switch (encoding)
7043 {
7044 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007045 // if Rt == '1111' then SEE PLI;
7046 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007047 t = Bits32 (opcode, 15, 12);
7048 imm32 = Bits32 (opcode, 11, 0);
7049 add = BitIsSet (opcode, 23);
7050
7051 // if t == 13 then UNPREDICTABLE;
7052 if (t == 13)
7053 return false;
7054
7055 break;
7056
7057 case eEncodingA1:
7058 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007059 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007060 t = Bits32 (opcode, 15, 12);
7061 uint32_t imm4H = Bits32 (opcode, 11, 8);
7062 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007063 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00007064 add = BitIsSet (opcode, 23);
7065
7066 // if t == 15 then UNPREDICTABLE;
7067 if (t == 15)
7068 return false;
7069
7070 break;
7071 }
7072
7073 default:
7074 return false;
7075 }
7076
7077 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007078 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007079 if (!success)
7080 return false;
7081 uint64_t base = AlignPC (pc_value);
7082
7083 // address = if add then (base + imm32) else (base - imm32);
7084 addr_t address;
7085 if (add)
7086 address = base + imm32;
7087 else
7088 address = base - imm32;
7089
7090 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007091 RegisterInfo base_reg;
7092 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice5f593912011-03-01 22:25:17 +00007093
7094 EmulateInstruction::Context context;
7095 context.type = eContextRegisterLoad;
7096 context.SetRegisterPlusOffset (base_reg, address - base);
7097
7098 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7099 if (!success)
7100 return false;
7101
7102 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7103 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7104 return false;
7105 }
7106 return true;
7107}
7108
Caroline Tice672f3112011-03-01 23:55:59 +00007109// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7110// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7111// shifted left by 0, 1, 2, or 3 bits.
7112bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007113EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007114{
7115#if 0
7116 if ConditionPassed() then
7117 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7118 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7119 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7120 address = if index then offset_addr else R[n];
7121 R[t] = SignExtend(MemU[address,1], 32);
7122 if wback then R[n] = offset_addr;
7123#endif
7124
7125 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007126
Greg Clayton7bc39082011-03-24 23:53:38 +00007127 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007128 {
7129 uint32_t t;
7130 uint32_t n;
7131 uint32_t m;
7132 bool index;
7133 bool add;
7134 bool wback;
7135 ARM_ShifterType shift_t;
7136 uint32_t shift_n;
7137
7138 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7139 switch (encoding)
7140 {
7141 case eEncodingT1:
7142 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7143 t = Bits32 (opcode, 2, 0);
7144 n = Bits32 (opcode, 5, 3);
7145 m = Bits32 (opcode, 8, 6);
7146
7147 // index = TRUE; add = TRUE; wback = FALSE;
7148 index = true;
7149 add = true;
7150 wback = false;
7151
7152 // (shift_t, shift_n) = (SRType_LSL, 0);
7153 shift_t = SRType_LSL;
7154 shift_n = 0;
7155
7156 break;
7157
7158 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007159 // if Rt == '1111' then SEE PLI;
7160 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007161 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7162 t = Bits32 (opcode, 15, 12);
7163 n = Bits32 (opcode, 19, 16);
7164 m = Bits32 (opcode, 3, 0);
7165
7166 // index = TRUE; add = TRUE; wback = FALSE;
7167 index = true;
7168 add = true;
7169 wback = false;
7170
7171 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7172 shift_t = SRType_LSL;
7173 shift_n = Bits32 (opcode, 5, 4);
7174
7175 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7176 if ((t == 13) || BadReg (m))
7177 return false;
7178 break;
7179
7180 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007181 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007182 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7183 t = Bits32 (opcode, 15, 12);
7184 n = Bits32 (opcode, 19, 16);
7185 m = Bits32 (opcode, 3, 0);
7186
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007187 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007188 index = BitIsSet (opcode, 24);
7189 add = BitIsSet (opcode, 23);
7190 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7191
7192 // (shift_t, shift_n) = (SRType_LSL, 0);
7193 shift_t = SRType_LSL;
7194 shift_n = 0;
7195
7196 // if t == 15 || m == 15 then UNPREDICTABLE;
7197 if ((t == 15) || (m == 15))
7198 return false;
7199
7200 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7201 if (wback && ((n == 15) || (n == t)))
7202 return false;
7203 break;
7204
7205 default:
7206 return false;
7207 }
7208
7209 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7210 if (!success)
7211 return false;
7212
7213 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00007214 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7215 if (!success)
7216 return false;
Caroline Tice672f3112011-03-01 23:55:59 +00007217
7218 addr_t offset_addr;
7219 addr_t address;
7220
7221 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7222 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7223 if (!success)
7224 return false;
7225
7226 if (add)
7227 offset_addr = Rn + offset;
7228 else
7229 offset_addr = Rn - offset;
7230
7231 // address = if index then offset_addr else R[n];
7232 if (index)
7233 address = offset_addr;
7234 else
7235 address = Rn;
7236
7237 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007238 RegisterInfo base_reg;
7239 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7240 RegisterInfo offset_reg;
7241 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice672f3112011-03-01 23:55:59 +00007242
7243 EmulateInstruction::Context context;
7244 context.type = eContextRegisterLoad;
7245 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7246
7247 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7248 if (!success)
7249 return false;
7250
7251 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7252 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7253 return false;
7254
7255 // if wback then R[n] = offset_addr;
7256 if (wback)
7257 {
7258 context.type = eContextAdjustBaseRegister;
7259 context.SetAddress (offset_addr);
7260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7261 return false;
7262 }
7263 }
7264 return true;
7265}
7266
Caroline Tice78fb5632011-03-02 00:39:42 +00007267// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7268// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7269// pre-indexed addressing.
7270bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007271EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007272{
7273#if 0
7274 if ConditionPassed() then
7275 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7276 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7277 address = if index then offset_addr else R[n];
7278 data = MemU[address,2];
7279 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007280 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007281 R[t] = SignExtend(data, 32);
7282 else // Can only apply before ARMv7
7283 R[t] = bits(32) UNKNOWN;
7284#endif
7285
7286 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007287
Greg Clayton7bc39082011-03-24 23:53:38 +00007288 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007289 {
7290 uint32_t t;
7291 uint32_t n;
7292 uint32_t imm32;
7293 bool index;
7294 bool add;
7295 bool wback;
7296
7297 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7298 switch (encoding)
7299 {
7300 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007301 // if Rn == '1111' then SEE LDRSH (literal);
7302 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007303 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7304 t = Bits32 (opcode, 15, 12);
7305 n = Bits32 (opcode, 19, 16);
7306 imm32 = Bits32 (opcode, 11, 0);
7307
7308 // index = TRUE; add = TRUE; wback = FALSE;
7309 index = true;
7310 add = true;
7311 wback = false;
7312
7313 // if t == 13 then UNPREDICTABLE;
7314 if (t == 13)
7315 return false;
7316
7317 break;
7318
7319 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007320 // if Rn == '1111' then SEE LDRSH (literal);
7321 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7322 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7323 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007324 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7325 return false;
7326
7327 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7328 t = Bits32 (opcode, 15, 12);
7329 n = Bits32 (opcode, 19, 16);
7330 imm32 = Bits32 (opcode, 7, 0);
7331
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007332 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007333 index = BitIsSet (opcode, 10);
7334 add = BitIsSet (opcode, 9);
7335 wback = BitIsSet (opcode, 8);
7336
7337 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7338 if (BadReg (t) || (wback && (n == t)))
7339 return false;
7340
7341 break;
7342
7343 case eEncodingA1:
7344 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007345 // if Rn == '1111' then SEE LDRSH (literal);
7346 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007347 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7348 t = Bits32 (opcode, 15, 12);
7349 n = Bits32 (opcode, 19, 16);
7350 uint32_t imm4H = Bits32 (opcode, 11,8);
7351 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007352 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007353
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007354 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007355 index = BitIsSet (opcode, 24);
7356 add = BitIsSet (opcode, 23);
7357 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7358
7359 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7360 if ((t == 15) || (wback && (n == t)))
7361 return false;
7362
7363 break;
7364 }
7365
7366 default:
7367 return false;
7368 }
7369
7370 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7371 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7372 if (!success)
7373 return false;
7374
7375 addr_t offset_addr;
7376 if (add)
7377 offset_addr = Rn + imm32;
7378 else
7379 offset_addr = Rn - imm32;
7380
7381 // address = if index then offset_addr else R[n];
7382 addr_t address;
7383 if (index)
7384 address = offset_addr;
7385 else
7386 address = Rn;
7387
7388 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007389 RegisterInfo base_reg;
7390 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice78fb5632011-03-02 00:39:42 +00007391
7392 EmulateInstruction::Context context;
7393 context.type = eContextRegisterLoad;
7394 context.SetRegisterPlusOffset (base_reg, address - Rn);
7395
7396 uint64_t data = MemURead (context, address, 2, 0, &success);
7397 if (!success)
7398 return false;
7399
7400 // if wback then R[n] = offset_addr;
7401 if (wback)
7402 {
7403 context.type = eContextAdjustBaseRegister;
7404 context.SetAddress (offset_addr);
7405 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7406 return false;
7407 }
7408
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007409 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007410 if (UnalignedSupport() || BitIsClear (address, 0))
7411 {
7412 // R[t] = SignExtend(data, 32);
7413 int64_t signed_data = llvm::SignExtend64<16>(data);
7414 context.type = eContextRegisterLoad;
7415 context.SetRegisterPlusOffset (base_reg, address - Rn);
7416 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7417 return false;
7418 }
7419 else // Can only apply before ARMv7
7420 {
7421 // R[t] = bits(32) UNKNOWN;
7422 WriteBits32Unknown (t);
7423 }
7424 }
7425 return true;
7426}
7427
Caroline Ticed2fac092011-03-02 19:45:34 +00007428// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7429// sign-extends it to from a 32-bit word, and writes it to a register.
7430bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007431EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007432{
7433#if 0
7434 if ConditionPassed() then
7435 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7436 base = Align(PC,4);
7437 address = if add then (base + imm32) else (base - imm32);
7438 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007439 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007440 R[t] = SignExtend(data, 32);
7441 else // Can only apply before ARMv7
7442 R[t] = bits(32) UNKNOWN;
7443#endif
7444
7445 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007446
Greg Clayton7bc39082011-03-24 23:53:38 +00007447 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007448 {
7449 uint32_t t;
7450 uint32_t imm32;
7451 bool add;
7452
7453 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7454 switch (encoding)
7455 {
7456 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007457 // if Rt == '1111' then SEE "Unallocated memory hints";
7458 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007459 t = Bits32 (opcode, 15, 12);
7460 imm32 = Bits32 (opcode, 11, 0);
7461 add = BitIsSet (opcode, 23);
7462
7463 // if t == 13 then UNPREDICTABLE;
7464 if (t == 13)
7465 return false;
7466
7467 break;
7468
7469 case eEncodingA1:
7470 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007471 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007472 t = Bits32 (opcode, 15, 12);
7473 uint32_t imm4H = Bits32 (opcode, 11, 8);
7474 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007475 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007476 add = BitIsSet (opcode, 23);
7477
7478 // if t == 15 then UNPREDICTABLE;
7479 if (t == 15)
7480 return false;
7481
7482 break;
7483 }
7484 default:
7485 return false;
7486 }
7487
7488 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007489 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007490 if (!success)
7491 return false;
7492
7493 uint64_t base = AlignPC (pc_value);
7494
7495 addr_t address;
7496 // address = if add then (base + imm32) else (base - imm32);
7497 if (add)
7498 address = base + imm32;
7499 else
7500 address = base - imm32;
7501
7502 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007503 RegisterInfo base_reg;
7504 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Ticed2fac092011-03-02 19:45:34 +00007505
7506 EmulateInstruction::Context context;
7507 context.type = eContextRegisterLoad;
7508 context.SetRegisterPlusOffset (base_reg, imm32);
7509
7510 uint64_t data = MemURead (context, address, 2, 0, &success);
7511 if (!success)
7512 return false;
7513
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007514 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007515 if (UnalignedSupport() || BitIsClear (address, 0))
7516 {
7517 // R[t] = SignExtend(data, 32);
7518 int64_t signed_data = llvm::SignExtend64<16>(data);
7519 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7520 return false;
7521 }
7522 else // Can only apply before ARMv7
7523 {
7524 // R[t] = bits(32) UNKNOWN;
7525 WriteBits32Unknown (t);
7526 }
7527 }
7528 return true;
7529}
7530
Caroline Tice291a3e92011-03-02 21:13:44 +00007531// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7532// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7533// shifted left by 0, 1, 2, or 3 bits.
7534bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007535EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007536{
7537#if 0
7538 if ConditionPassed() then
7539 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7540 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7541 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7542 address = if index then offset_addr else R[n];
7543 data = MemU[address,2];
7544 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007545 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007546 R[t] = SignExtend(data, 32);
7547 else // Can only apply before ARMv7
7548 R[t] = bits(32) UNKNOWN;
7549#endif
7550
7551 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007552
Greg Clayton7bc39082011-03-24 23:53:38 +00007553 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007554 {
7555 uint32_t t;
7556 uint32_t n;
7557 uint32_t m;
7558 bool index;
7559 bool add;
7560 bool wback;
7561 ARM_ShifterType shift_t;
7562 uint32_t shift_n;
7563
7564 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7565 switch (encoding)
7566 {
7567 case eEncodingT1:
7568 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7569 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7570 t = Bits32 (opcode, 2, 0);
7571 n = Bits32 (opcode, 5, 3);
7572 m = Bits32 (opcode, 8, 6);
7573
7574 // index = TRUE; add = TRUE; wback = FALSE;
7575 index = true;
7576 add = true;
7577 wback = false;
7578
7579 // (shift_t, shift_n) = (SRType_LSL, 0);
7580 shift_t = SRType_LSL;
7581 shift_n = 0;
7582
7583 break;
7584
7585 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007586 // if Rn == '1111' then SEE LDRSH (literal);
7587 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007588 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7589 t = Bits32 (opcode, 15, 12);
7590 n = Bits32 (opcode, 19, 16);
7591 m = Bits32 (opcode, 3, 0);
7592
7593 // index = TRUE; add = TRUE; wback = FALSE;
7594 index = true;
7595 add = true;
7596 wback = false;
7597
7598 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7599 shift_t = SRType_LSL;
7600 shift_n = Bits32 (opcode, 5, 4);
7601
7602 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7603 if ((t == 13) || BadReg (m))
7604 return false;
7605
7606 break;
7607
7608 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007609 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007610 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7611 t = Bits32 (opcode, 15, 12);
7612 n = Bits32 (opcode, 19, 16);
7613 m = Bits32 (opcode, 3, 0);
7614
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007615 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007616 index = BitIsSet (opcode, 24);
7617 add = BitIsSet (opcode, 23);
7618 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7619
7620 // (shift_t, shift_n) = (SRType_LSL, 0);
7621 shift_t = SRType_LSL;
7622 shift_n = 0;
7623
7624 // if t == 15 || m == 15 then UNPREDICTABLE;
7625 if ((t == 15) || (m == 15))
7626 return false;
7627
7628 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7629 if (wback && ((n == 15) || (n == t)))
7630 return false;
7631
7632 break;
7633
7634 default:
7635 break;
7636 }
7637
7638 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7639 if (!success)
7640 return false;
7641
7642 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7643 if (!success)
7644 return false;
7645
7646 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00007647 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7648 if (!success)
7649 return false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007650
7651 addr_t offset_addr;
7652 addr_t address;
7653
7654 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7655 if (add)
7656 offset_addr = Rn + offset;
7657 else
7658 offset_addr = Rn - offset;
7659
7660 // address = if index then offset_addr else R[n];
7661 if (index)
7662 address = offset_addr;
7663 else
7664 address = Rn;
7665
7666 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007667 RegisterInfo base_reg;
7668 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007669
Greg Claytonc07d4512011-04-26 23:48:45 +00007670 RegisterInfo offset_reg;
7671 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007672
7673 EmulateInstruction::Context context;
7674 context.type = eContextRegisterLoad;
7675 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7676
7677 uint64_t data = MemURead (context, address, 2, 0, &success);
7678 if (!success)
7679 return false;
7680
7681 // if wback then R[n] = offset_addr;
7682 if (wback)
7683 {
7684 context.type = eContextAdjustBaseRegister;
7685 context.SetAddress (offset_addr);
7686 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7687 return false;
7688 }
7689
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007690 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007691 if (UnalignedSupport() || BitIsClear (address, 0))
7692 {
7693 // R[t] = SignExtend(data, 32);
7694 context.type = eContextRegisterLoad;
7695 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7696
7697 int64_t signed_data = llvm::SignExtend64<16>(data);
7698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7699 return false;
7700 }
7701 else // Can only apply before ARMv7
7702 {
7703 // R[t] = bits(32) UNKNOWN;
7704 WriteBits32Unknown (t);
7705 }
7706 }
7707 return true;
7708}
Caroline Tice6bf65162011-03-03 17:42:58 +00007709
7710// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7711// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7712bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007713EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007714{
7715#if 0
7716 if ConditionPassed() then
7717 EncodingSpecificOperations();
7718 rotated = ROR(R[m], rotation);
7719 R[d] = SignExtend(rotated<7:0>, 32);
7720#endif
7721
7722 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007723
Greg Clayton7bc39082011-03-24 23:53:38 +00007724 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007725 {
7726 uint32_t d;
7727 uint32_t m;
7728 uint32_t rotation;
7729
7730 // EncodingSpecificOperations();
7731 switch (encoding)
7732 {
7733 case eEncodingT1:
7734 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7735 d = Bits32 (opcode, 2, 0);
7736 m = Bits32 (opcode, 5, 3);
7737 rotation = 0;
7738
7739 break;
7740
7741 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007742 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007743 d = Bits32 (opcode, 11, 8);
7744 m = Bits32 (opcode, 3, 0);
7745 rotation = Bits32 (opcode, 5, 4) << 3;
7746
7747 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7748 if (BadReg (d) || BadReg (m))
7749 return false;
7750
7751 break;
7752
7753 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007754 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007755 d = Bits32 (opcode, 15, 12);
7756 m = Bits32 (opcode, 3, 0);
7757 rotation = Bits32 (opcode, 11, 10) << 3;
7758
7759 // if d == 15 || m == 15 then UNPREDICTABLE;
7760 if ((d == 15) || (m == 15))
7761 return false;
7762
7763 break;
7764
7765 default:
7766 return false;
7767 }
7768
Caroline Tice868198b2011-03-03 18:04:49 +00007769 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7770 if (!success)
7771 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007772
7773 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007774 uint64_t rotated = ROR (Rm, rotation, &success);
7775 if (!success)
7776 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007777
7778 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007779 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007780
Greg Claytonc07d4512011-04-26 23:48:45 +00007781 RegisterInfo source_reg;
7782 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice6bf65162011-03-03 17:42:58 +00007783
7784 EmulateInstruction::Context context;
7785 context.type = eContextRegisterLoad;
7786 context.SetRegister (source_reg);
7787
Caroline Tice8ce96d92011-03-03 18:27:17 +00007788 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007789 return false;
7790 }
7791 return true;
7792}
Caroline Tice291a3e92011-03-02 21:13:44 +00007793
Caroline Tice868198b2011-03-03 18:04:49 +00007794// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7795// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7796bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007797EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007798{
7799#if 0
7800 if ConditionPassed() then
7801 EncodingSpecificOperations();
7802 rotated = ROR(R[m], rotation);
7803 R[d] = SignExtend(rotated<15:0>, 32);
7804#endif
7805
7806 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007807
Greg Clayton7bc39082011-03-24 23:53:38 +00007808 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007809 {
7810 uint32_t d;
7811 uint32_t m;
7812 uint32_t rotation;
7813
7814 // EncodingSpecificOperations();
7815 switch (encoding)
7816 {
7817 case eEncodingT1:
7818 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7819 d = Bits32 (opcode, 2, 0);
7820 m = Bits32 (opcode, 5, 3);
7821 rotation = 0;
7822
7823 break;
7824
7825 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007826 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007827 d = Bits32 (opcode, 11, 8);
7828 m = Bits32 (opcode, 3, 0);
7829 rotation = Bits32 (opcode, 5, 4) << 3;
7830
7831 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7832 if (BadReg (d) || BadReg (m))
7833 return false;
7834
7835 break;
7836
7837 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007838 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007839 d = Bits32 (opcode, 15, 12);
7840 m = Bits32 (opcode, 3, 0);
7841 rotation = Bits32 (opcode, 11, 10) << 3;
7842
7843 // if d == 15 || m == 15 then UNPREDICTABLE;
7844 if ((d == 15) || (m == 15))
7845 return false;
7846
7847 break;
7848
7849 default:
7850 return false;
7851 }
7852
7853 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7854 if (!success)
7855 return false;
7856
7857 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007858 uint64_t rotated = ROR (Rm, rotation, &success);
7859 if (!success)
7860 return false;
Caroline Tice868198b2011-03-03 18:04:49 +00007861
7862 // R[d] = SignExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007863 RegisterInfo source_reg;
7864 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice868198b2011-03-03 18:04:49 +00007865
7866 EmulateInstruction::Context context;
7867 context.type = eContextRegisterLoad;
7868 context.SetRegister (source_reg);
7869
Caroline Tice8ce96d92011-03-03 18:27:17 +00007870 int64_t data = llvm::SignExtend64<16> (rotated);
7871 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007872 return false;
7873 }
7874
7875 return true;
7876}
7877
Caroline Tice8ce96d92011-03-03 18:27:17 +00007878// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7879// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7880bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007881EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007882{
7883#if 0
7884 if ConditionPassed() then
7885 EncodingSpecificOperations();
7886 rotated = ROR(R[m], rotation);
7887 R[d] = ZeroExtend(rotated<7:0>, 32);
7888#endif
7889
7890 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007891
Greg Clayton7bc39082011-03-24 23:53:38 +00007892 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007893 {
7894 uint32_t d;
7895 uint32_t m;
7896 uint32_t rotation;
7897
7898 // EncodingSpecificOperations();
7899 switch (encoding)
7900 {
7901 case eEncodingT1:
7902 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7903 d = Bits32 (opcode, 2, 0);
7904 m = Bits32 (opcode, 5, 3);
7905 rotation = 0;
7906
7907 break;
7908
7909 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007910 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007911 d = Bits32 (opcode, 11, 8);
7912 m = Bits32 (opcode, 3, 0);
7913 rotation = Bits32 (opcode, 5, 4) << 3;
7914
7915 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7916 if (BadReg (d) || BadReg (m))
7917 return false;
7918
7919 break;
7920
7921 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007922 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007923 d = Bits32 (opcode, 15, 12);
7924 m = Bits32 (opcode, 3, 0);
7925 rotation = Bits32 (opcode, 11, 10) << 3;
7926
7927 // if d == 15 || m == 15 then UNPREDICTABLE;
7928 if ((d == 15) || (m == 15))
7929 return false;
7930
7931 break;
7932
7933 default:
7934 return false;
7935 }
7936
7937 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7938 if (!success)
7939 return false;
7940
7941 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007942 uint64_t rotated = ROR (Rm, rotation, &success);
7943 if (!success)
7944 return false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007945
7946 // R[d] = ZeroExtend(rotated<7:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007947 RegisterInfo source_reg;
7948 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007949
7950 EmulateInstruction::Context context;
7951 context.type = eContextRegisterLoad;
7952 context.SetRegister (source_reg);
7953
7954 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7955 return false;
7956 }
7957 return true;
7958}
7959
Caroline Tice11555f22011-03-03 18:48:58 +00007960// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7961// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7962bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007963EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007964{
7965#if 0
7966 if ConditionPassed() then
7967 EncodingSpecificOperations();
7968 rotated = ROR(R[m], rotation);
7969 R[d] = ZeroExtend(rotated<15:0>, 32);
7970#endif
7971
7972 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007973
Greg Clayton7bc39082011-03-24 23:53:38 +00007974 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007975 {
7976 uint32_t d;
7977 uint32_t m;
7978 uint32_t rotation;
7979
7980 switch (encoding)
7981 {
7982 case eEncodingT1:
7983 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7984 d = Bits32 (opcode, 2, 0);
7985 m = Bits32 (opcode, 5, 3);
7986 rotation = 0;
7987
7988 break;
7989
7990 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007991 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007992 d = Bits32 (opcode, 11, 8);
7993 m = Bits32 (opcode, 3, 0);
7994 rotation = Bits32 (opcode, 5, 4) << 3;
7995
7996 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7997 if (BadReg (d) || BadReg (m))
7998 return false;
7999
8000 break;
8001
8002 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008003 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00008004 d = Bits32 (opcode, 15, 12);
8005 m = Bits32 (opcode, 3, 0);
8006 rotation = Bits32 (opcode, 11, 10) << 3;
8007
8008 // if d == 15 || m == 15 then UNPREDICTABLE;
8009 if ((d == 15) || (m == 15))
8010 return false;
8011
8012 break;
8013
8014 default:
8015 return false;
8016 }
8017
8018 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8019 if (!success)
8020 return false;
8021
8022 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00008023 uint64_t rotated = ROR (Rm, rotation, &success);
8024 if (!success)
8025 return false;
Caroline Tice11555f22011-03-03 18:48:58 +00008026
8027 // R[d] = ZeroExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00008028 RegisterInfo source_reg;
8029 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice11555f22011-03-03 18:48:58 +00008030
8031 EmulateInstruction::Context context;
8032 context.type = eContextRegisterLoad;
8033 context.SetRegister (source_reg);
8034
8035 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
8036 return false;
8037 }
8038 return true;
8039}
Caroline Ticeb27771d2011-03-03 22:37:46 +00008040
8041// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
8042// word respectively.
8043bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008044EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00008045{
8046#if 0
8047 if ConditionPassed() then
8048 EncodingSpecificOperations();
8049 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8050 UNPREDICTABLE;
8051 else
8052 address = if increment then R[n] else R[n]-8;
8053 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008054 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008055 BranchWritePC(MemA[address,4]);
8056 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8057#endif
8058
8059 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008060
Greg Clayton7bc39082011-03-24 23:53:38 +00008061 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00008062 {
8063 uint32_t n;
8064 bool wback;
8065 bool increment;
8066 bool wordhigher;
8067
8068 // EncodingSpecificOperations();
8069 switch (encoding)
8070 {
8071 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008072 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008073 n = Bits32 (opcode, 19, 16);
8074 wback = BitIsSet (opcode, 21);
8075 increment = false;
8076 wordhigher = false;
8077
8078 // if n == 15 then UNPREDICTABLE;
8079 if (n == 15)
8080 return false;
8081
8082 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8083 if (InITBlock() && !LastInITBlock())
8084 return false;
8085
8086 break;
8087
8088 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008089 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008090 n = Bits32 (opcode, 19, 16);
8091 wback = BitIsSet (opcode, 21);
8092 increment = true;
8093 wordhigher = false;
8094
8095 // if n == 15 then UNPREDICTABLE;
8096 if (n == 15)
8097 return false;
8098
8099 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8100 if (InITBlock() && !LastInITBlock())
8101 return false;
8102
8103 break;
8104
8105 case eEncodingA1:
8106 // n = UInt(Rn);
8107 n = Bits32 (opcode, 19, 16);
8108
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008109 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008110 wback = BitIsSet (opcode, 21);
8111 increment = BitIsSet (opcode, 23);
8112 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8113
8114 // if n == 15 then UNPREDICTABLE;
8115 if (n == 15)
8116 return false;
8117
8118 break;
8119
8120 default:
8121 return false;
8122 }
8123
8124 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8125 if (!CurrentModeIsPrivileged ())
8126 // UNPREDICTABLE;
8127 return false;
8128 else
8129 {
8130 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8131 if (!success)
8132 return false;
8133
8134 addr_t address;
8135 // address = if increment then R[n] else R[n]-8;
8136 if (increment)
8137 address = Rn;
8138 else
8139 address = Rn - 8;
8140
8141 // if wordhigher then address = address+4;
8142 if (wordhigher)
8143 address = address + 4;
8144
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008145 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Greg Claytonc07d4512011-04-26 23:48:45 +00008146 RegisterInfo base_reg;
8147 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008148
8149 EmulateInstruction::Context context;
8150 context.type = eContextReturnFromException;
8151 context.SetRegisterPlusOffset (base_reg, address - Rn);
8152
8153 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8154 if (!success)
8155 return false;
8156
8157 CPSRWriteByInstr (data, 15, true);
8158
8159 // BranchWritePC(MemA[address,4]);
8160 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8161 if (!success)
8162 return false;
8163
8164 BranchWritePC (context, data2);
8165
8166 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8167 if (wback)
8168 {
8169 context.type = eContextAdjustBaseRegister;
8170 if (increment)
8171 {
8172 context.SetOffset (8);
8173 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8174 return false;
8175 }
8176 else
8177 {
8178 context.SetOffset (-8);
8179 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8180 return false;
8181 }
8182 } // if wback
8183 }
8184 } // if ConditionPassed()
8185 return true;
8186}
Caroline Tice11555f22011-03-03 18:48:58 +00008187
Johnny Chen2115b412011-02-21 23:42:44 +00008188// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8189// and writes the result to the destination register. It can optionally update the condition flags based on
8190// the result.
8191bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008192EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008193{
8194#if 0
8195 // ARM pseudo code...
8196 if ConditionPassed() then
8197 EncodingSpecificOperations();
8198 result = R[n] EOR imm32;
8199 if d == 15 then // Can only occur for ARM encoding
8200 ALUWritePC(result); // setflags is always FALSE here
8201 else
8202 R[d] = result;
8203 if setflags then
8204 APSR.N = result<31>;
8205 APSR.Z = IsZeroBit(result);
8206 APSR.C = carry;
8207 // APSR.V unchanged
8208#endif
8209
8210 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008211
Greg Clayton7bc39082011-03-24 23:53:38 +00008212 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008213 {
8214 uint32_t Rd, Rn;
8215 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8216 bool setflags;
8217 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8218 switch (encoding)
8219 {
8220 case eEncodingT1:
8221 Rd = Bits32(opcode, 11, 8);
8222 Rn = Bits32(opcode, 19, 16);
8223 setflags = BitIsSet(opcode, 20);
8224 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8225 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8226 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008227 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008228 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8229 return false;
8230 break;
8231 case eEncodingA1:
8232 Rd = Bits32(opcode, 15, 12);
8233 Rn = Bits32(opcode, 19, 16);
8234 setflags = BitIsSet(opcode, 20);
8235 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008236
Johnny Chen2115b412011-02-21 23:42:44 +00008237 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008238 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008239 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008240 break;
8241 default:
8242 return false;
8243 }
8244
8245 // Read the first operand.
8246 uint32_t val1 = ReadCoreReg(Rn, &success);
8247 if (!success)
8248 return false;
8249
8250 uint32_t result = val1 ^ imm32;
8251
8252 EmulateInstruction::Context context;
8253 context.type = EmulateInstruction::eContextImmediate;
8254 context.SetNoArgs ();
8255
8256 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8257 return false;
8258 }
8259 return true;
8260}
8261
8262// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8263// optionally-shifted register value, and writes the result to the destination register.
8264// It can optionally update the condition flags based on the result.
8265bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008266EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008267{
8268#if 0
8269 // ARM pseudo code...
8270 if ConditionPassed() then
8271 EncodingSpecificOperations();
8272 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8273 result = R[n] EOR shifted;
8274 if d == 15 then // Can only occur for ARM encoding
8275 ALUWritePC(result); // setflags is always FALSE here
8276 else
8277 R[d] = result;
8278 if setflags then
8279 APSR.N = result<31>;
8280 APSR.Z = IsZeroBit(result);
8281 APSR.C = carry;
8282 // APSR.V unchanged
8283#endif
8284
8285 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008286
Greg Clayton7bc39082011-03-24 23:53:38 +00008287 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008288 {
8289 uint32_t Rd, Rn, Rm;
8290 ARM_ShifterType shift_t;
8291 uint32_t shift_n; // the shift applied to the value read from Rm
8292 bool setflags;
8293 uint32_t carry;
8294 switch (encoding)
8295 {
8296 case eEncodingT1:
8297 Rd = Rn = Bits32(opcode, 2, 0);
8298 Rm = Bits32(opcode, 5, 3);
8299 setflags = !InITBlock();
8300 shift_t = SRType_LSL;
8301 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008302 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008303 case eEncodingT2:
8304 Rd = Bits32(opcode, 11, 8);
8305 Rn = Bits32(opcode, 19, 16);
8306 Rm = Bits32(opcode, 3, 0);
8307 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008308 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8309 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008310 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008311 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008312 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8313 return false;
8314 break;
8315 case eEncodingA1:
8316 Rd = Bits32(opcode, 15, 12);
8317 Rn = Bits32(opcode, 19, 16);
8318 Rm = Bits32(opcode, 3, 0);
8319 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008320 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008321
Johnny Chen2115b412011-02-21 23:42:44 +00008322 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008323 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008324 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008325 break;
8326 default:
8327 return false;
8328 }
8329
8330 // Read the first operand.
8331 uint32_t val1 = ReadCoreReg(Rn, &success);
8332 if (!success)
8333 return false;
8334
8335 // Read the second operand.
8336 uint32_t val2 = ReadCoreReg(Rm, &success);
8337 if (!success)
8338 return false;
8339
Johnny Chena4438a72011-06-02 22:50:51 +00008340 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8341 if (!success)
8342 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00008343 uint32_t result = val1 ^ shifted;
8344
8345 EmulateInstruction::Context context;
8346 context.type = EmulateInstruction::eContextImmediate;
8347 context.SetNoArgs ();
8348
8349 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8350 return false;
8351 }
8352 return true;
8353}
8354
Johnny Chen7c5234d2011-02-18 23:41:11 +00008355// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8356// writes the result to the destination register. It can optionally update the condition flags based
8357// on the result.
8358bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008359EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008360{
8361#if 0
8362 // ARM pseudo code...
8363 if ConditionPassed() then
8364 EncodingSpecificOperations();
8365 result = R[n] OR imm32;
8366 if d == 15 then // Can only occur for ARM encoding
8367 ALUWritePC(result); // setflags is always FALSE here
8368 else
8369 R[d] = result;
8370 if setflags then
8371 APSR.N = result<31>;
8372 APSR.Z = IsZeroBit(result);
8373 APSR.C = carry;
8374 // APSR.V unchanged
8375#endif
8376
8377 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008378
Greg Clayton7bc39082011-03-24 23:53:38 +00008379 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008380 {
8381 uint32_t Rd, Rn;
8382 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8383 bool setflags;
8384 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8385 switch (encoding)
8386 {
8387 case eEncodingT1:
8388 Rd = Bits32(opcode, 11, 8);
8389 Rn = Bits32(opcode, 19, 16);
8390 setflags = BitIsSet(opcode, 20);
8391 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008392 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008393 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008394 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008395 if (BadReg(Rd) || Rn == 13)
8396 return false;
8397 break;
8398 case eEncodingA1:
8399 Rd = Bits32(opcode, 15, 12);
8400 Rn = Bits32(opcode, 19, 16);
8401 setflags = BitIsSet(opcode, 20);
8402 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008403
Johnny Chen7c5234d2011-02-18 23:41:11 +00008404 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008405 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008406 break;
8407 default:
8408 return false;
8409 }
8410
8411 // Read the first operand.
8412 uint32_t val1 = ReadCoreReg(Rn, &success);
8413 if (!success)
8414 return false;
8415
8416 uint32_t result = val1 | imm32;
8417
8418 EmulateInstruction::Context context;
8419 context.type = EmulateInstruction::eContextImmediate;
8420 context.SetNoArgs ();
8421
8422 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8423 return false;
8424 }
8425 return true;
8426}
8427
8428// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8429// value, and writes the result to the destination register. It can optionally update the condition flags based
8430// on the result.
8431bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008432EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008433{
8434#if 0
8435 // ARM pseudo code...
8436 if ConditionPassed() then
8437 EncodingSpecificOperations();
8438 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8439 result = R[n] OR shifted;
8440 if d == 15 then // Can only occur for ARM encoding
8441 ALUWritePC(result); // setflags is always FALSE here
8442 else
8443 R[d] = result;
8444 if setflags then
8445 APSR.N = result<31>;
8446 APSR.Z = IsZeroBit(result);
8447 APSR.C = carry;
8448 // APSR.V unchanged
8449#endif
8450
8451 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008452
Greg Clayton7bc39082011-03-24 23:53:38 +00008453 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008454 {
8455 uint32_t Rd, Rn, Rm;
8456 ARM_ShifterType shift_t;
8457 uint32_t shift_n; // the shift applied to the value read from Rm
8458 bool setflags;
8459 uint32_t carry;
8460 switch (encoding)
8461 {
8462 case eEncodingT1:
8463 Rd = Rn = Bits32(opcode, 2, 0);
8464 Rm = Bits32(opcode, 5, 3);
8465 setflags = !InITBlock();
8466 shift_t = SRType_LSL;
8467 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008468 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008469 case eEncodingT2:
8470 Rd = Bits32(opcode, 11, 8);
8471 Rn = Bits32(opcode, 19, 16);
8472 Rm = Bits32(opcode, 3, 0);
8473 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008474 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8475 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008476 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008477 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008478 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8479 return false;
8480 break;
8481 case eEncodingA1:
8482 Rd = Bits32(opcode, 15, 12);
8483 Rn = Bits32(opcode, 19, 16);
8484 Rm = Bits32(opcode, 3, 0);
8485 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008486 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008487
Johnny Chen7c5234d2011-02-18 23:41:11 +00008488 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008489 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008490 break;
8491 default:
8492 return false;
8493 }
8494
8495 // Read the first operand.
8496 uint32_t val1 = ReadCoreReg(Rn, &success);
8497 if (!success)
8498 return false;
8499
8500 // Read the second operand.
8501 uint32_t val2 = ReadCoreReg(Rm, &success);
8502 if (!success)
8503 return false;
8504
Johnny Chena4438a72011-06-02 22:50:51 +00008505 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8506 if (!success)
8507 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00008508 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008509
8510 EmulateInstruction::Context context;
8511 context.type = EmulateInstruction::eContextImmediate;
8512 context.SetNoArgs ();
8513
8514 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8515 return false;
8516 }
8517 return true;
8518}
8519
Johnny Chened32e7c2011-02-22 23:42:58 +00008520// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8521// the destination register. It can optionally update the condition flags based on the result.
8522bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008523EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008524{
8525#if 0
8526 // ARM pseudo code...
8527 if ConditionPassed() then
8528 EncodingSpecificOperations();
8529 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8530 if d == 15 then // Can only occur for ARM encoding
8531 ALUWritePC(result); // setflags is always FALSE here
8532 else
8533 R[d] = result;
8534 if setflags then
8535 APSR.N = result<31>;
8536 APSR.Z = IsZeroBit(result);
8537 APSR.C = carry;
8538 APSR.V = overflow;
8539#endif
8540
8541 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008542
8543 uint32_t Rd; // the destination register
8544 uint32_t Rn; // the first operand
8545 bool setflags;
8546 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8547 switch (encoding) {
8548 case eEncodingT1:
8549 Rd = Bits32(opcode, 2, 0);
8550 Rn = Bits32(opcode, 5, 3);
8551 setflags = !InITBlock();
8552 imm32 = 0;
8553 break;
8554 case eEncodingT2:
8555 Rd = Bits32(opcode, 11, 8);
8556 Rn = Bits32(opcode, 19, 16);
8557 setflags = BitIsSet(opcode, 20);
8558 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8559 if (BadReg(Rd) || BadReg(Rn))
8560 return false;
8561 break;
8562 case eEncodingA1:
8563 Rd = Bits32(opcode, 15, 12);
8564 Rn = Bits32(opcode, 19, 16);
8565 setflags = BitIsSet(opcode, 20);
8566 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008567
Johnny Chened32e7c2011-02-22 23:42:58 +00008568 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008569 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008570 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008571 break;
8572 default:
8573 return false;
8574 }
8575 // Read the register value from the operand register Rn.
8576 uint32_t reg_val = ReadCoreReg(Rn, &success);
8577 if (!success)
8578 return false;
8579
8580 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8581
8582 EmulateInstruction::Context context;
8583 context.type = EmulateInstruction::eContextImmediate;
8584 context.SetNoArgs ();
8585
8586 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8587 return false;
8588
8589 return true;
8590}
8591
8592// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8593// result to the destination register. It can optionally update the condition flags based on the result.
8594bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008595EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008596{
8597#if 0
8598 // ARM pseudo code...
8599 if ConditionPassed() then
8600 EncodingSpecificOperations();
8601 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8602 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8603 if d == 15 then // Can only occur for ARM encoding
8604 ALUWritePC(result); // setflags is always FALSE here
8605 else
8606 R[d] = result;
8607 if setflags then
8608 APSR.N = result<31>;
8609 APSR.Z = IsZeroBit(result);
8610 APSR.C = carry;
8611 APSR.V = overflow;
8612#endif
8613
8614 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008615
8616 uint32_t Rd; // the destination register
8617 uint32_t Rn; // the first operand
8618 uint32_t Rm; // the second operand
8619 bool setflags;
8620 ARM_ShifterType shift_t;
8621 uint32_t shift_n; // the shift applied to the value read from Rm
8622 switch (encoding) {
8623 case eEncodingT1:
8624 Rd = Bits32(opcode, 11, 8);
8625 Rn = Bits32(opcode, 19, 16);
8626 Rm = Bits32(opcode, 3, 0);
8627 setflags = BitIsSet(opcode, 20);
8628 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8629 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8630 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8631 return false;
8632 break;
8633 case eEncodingA1:
8634 Rd = Bits32(opcode, 15, 12);
8635 Rn = Bits32(opcode, 19, 16);
8636 Rm = Bits32(opcode, 3, 0);
8637 setflags = BitIsSet(opcode, 20);
8638 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008639
Johnny Chened32e7c2011-02-22 23:42:58 +00008640 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008641 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008642 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008643 break;
8644 default:
8645 return false;
8646 }
8647 // Read the register value from register Rn.
8648 uint32_t val1 = ReadCoreReg(Rn, &success);
8649 if (!success)
8650 return false;
8651
8652 // Read the register value from register Rm.
8653 uint32_t val2 = ReadCoreReg(Rm, &success);
8654 if (!success)
8655 return false;
8656
Johnny Chena4438a72011-06-02 22:50:51 +00008657 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8658 if (!success)
8659 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008660 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8661
8662 EmulateInstruction::Context context;
8663 context.type = EmulateInstruction::eContextImmediate;
8664 context.SetNoArgs();
8665 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8666 return false;
8667
8668 return true;
8669}
8670
Johnny Chen90e607b2011-02-23 00:07:09 +00008671// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8672// an immediate value, and writes the result to the destination register. It can optionally update the condition
8673// flags based on the result.
8674bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008675EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008676{
8677#if 0
8678 // ARM pseudo code...
8679 if ConditionPassed() then
8680 EncodingSpecificOperations();
8681 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8682 if d == 15 then
8683 ALUWritePC(result); // setflags is always FALSE here
8684 else
8685 R[d] = result;
8686 if setflags then
8687 APSR.N = result<31>;
8688 APSR.Z = IsZeroBit(result);
8689 APSR.C = carry;
8690 APSR.V = overflow;
8691#endif
8692
8693 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008694
8695 uint32_t Rd; // the destination register
8696 uint32_t Rn; // the first operand
8697 bool setflags;
8698 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8699 switch (encoding) {
8700 case eEncodingA1:
8701 Rd = Bits32(opcode, 15, 12);
8702 Rn = Bits32(opcode, 19, 16);
8703 setflags = BitIsSet(opcode, 20);
8704 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008705
Johnny Chen90e607b2011-02-23 00:07:09 +00008706 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008707 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008708 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008709 break;
8710 default:
8711 return false;
8712 }
8713 // Read the register value from the operand register Rn.
8714 uint32_t reg_val = ReadCoreReg(Rn, &success);
8715 if (!success)
8716 return false;
8717
8718 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8719
8720 EmulateInstruction::Context context;
8721 context.type = EmulateInstruction::eContextImmediate;
8722 context.SetNoArgs ();
8723
8724 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8725 return false;
8726
8727 return true;
8728}
8729
8730// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8731// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8732// condition flags based on the result.
8733bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008734EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008735{
8736#if 0
8737 // ARM pseudo code...
8738 if ConditionPassed() then
8739 EncodingSpecificOperations();
8740 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8741 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8742 if d == 15 then
8743 ALUWritePC(result); // setflags is always FALSE here
8744 else
8745 R[d] = result;
8746 if setflags then
8747 APSR.N = result<31>;
8748 APSR.Z = IsZeroBit(result);
8749 APSR.C = carry;
8750 APSR.V = overflow;
8751#endif
8752
8753 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008754
8755 uint32_t Rd; // the destination register
8756 uint32_t Rn; // the first operand
8757 uint32_t Rm; // the second operand
8758 bool setflags;
8759 ARM_ShifterType shift_t;
8760 uint32_t shift_n; // the shift applied to the value read from Rm
8761 switch (encoding) {
8762 case eEncodingA1:
8763 Rd = Bits32(opcode, 15, 12);
8764 Rn = Bits32(opcode, 19, 16);
8765 Rm = Bits32(opcode, 3, 0);
8766 setflags = BitIsSet(opcode, 20);
8767 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008768
Johnny Chen90e607b2011-02-23 00:07:09 +00008769 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008770 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008771 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008772 break;
8773 default:
8774 return false;
8775 }
8776 // Read the register value from register Rn.
8777 uint32_t val1 = ReadCoreReg(Rn, &success);
8778 if (!success)
8779 return false;
8780
8781 // Read the register value from register Rm.
8782 uint32_t val2 = ReadCoreReg(Rm, &success);
8783 if (!success)
8784 return false;
8785
Johnny Chena4438a72011-06-02 22:50:51 +00008786 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8787 if (!success)
8788 return false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008789 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8790
8791 EmulateInstruction::Context context;
8792 context.type = EmulateInstruction::eContextImmediate;
8793 context.SetNoArgs();
8794 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8795 return false;
8796
8797 return true;
8798}
8799
Johnny Chen9b381772011-02-23 01:01:21 +00008800// Subtract with Carry (immediate) subtracts an immediate value and the value of
8801// NOT (Carry flag) from a register value, and writes the result to the destination register.
8802// It can optionally update the condition flags based on the result.
8803bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008804EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008805{
8806#if 0
8807 // ARM pseudo code...
8808 if ConditionPassed() then
8809 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008810 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008811 if d == 15 then // Can only occur for ARM encoding
8812 ALUWritePC(result); // setflags is always FALSE here
8813 else
8814 R[d] = result;
8815 if setflags then
8816 APSR.N = result<31>;
8817 APSR.Z = IsZeroBit(result);
8818 APSR.C = carry;
8819 APSR.V = overflow;
8820#endif
8821
8822 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008823
8824 uint32_t Rd; // the destination register
8825 uint32_t Rn; // the first operand
8826 bool setflags;
8827 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8828 switch (encoding) {
8829 case eEncodingT1:
8830 Rd = Bits32(opcode, 11, 8);
8831 Rn = Bits32(opcode, 19, 16);
8832 setflags = BitIsSet(opcode, 20);
8833 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8834 if (BadReg(Rd) || BadReg(Rn))
8835 return false;
8836 break;
8837 case eEncodingA1:
8838 Rd = Bits32(opcode, 15, 12);
8839 Rn = Bits32(opcode, 19, 16);
8840 setflags = BitIsSet(opcode, 20);
8841 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008842
Johnny Chen9b381772011-02-23 01:01:21 +00008843 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008844 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008845 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008846 break;
8847 default:
8848 return false;
8849 }
8850 // Read the register value from the operand register Rn.
8851 uint32_t reg_val = ReadCoreReg(Rn, &success);
8852 if (!success)
8853 return false;
8854
8855 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8856
8857 EmulateInstruction::Context context;
8858 context.type = EmulateInstruction::eContextImmediate;
8859 context.SetNoArgs ();
8860
8861 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8862 return false;
8863
8864 return true;
8865}
8866
8867// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8868// NOT (Carry flag) from a register value, and writes the result to the destination register.
8869// It can optionally update the condition flags based on the result.
8870bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008871EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008872{
8873#if 0
8874 // ARM pseudo code...
8875 if ConditionPassed() then
8876 EncodingSpecificOperations();
8877 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8878 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8879 if d == 15 then // Can only occur for ARM encoding
8880 ALUWritePC(result); // setflags is always FALSE here
8881 else
8882 R[d] = result;
8883 if setflags then
8884 APSR.N = result<31>;
8885 APSR.Z = IsZeroBit(result);
8886 APSR.C = carry;
8887 APSR.V = overflow;
8888#endif
8889
8890 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008891
8892 uint32_t Rd; // the destination register
8893 uint32_t Rn; // the first operand
8894 uint32_t Rm; // the second operand
8895 bool setflags;
8896 ARM_ShifterType shift_t;
8897 uint32_t shift_n; // the shift applied to the value read from Rm
8898 switch (encoding) {
8899 case eEncodingT1:
8900 Rd = Rn = Bits32(opcode, 2, 0);
8901 Rm = Bits32(opcode, 5, 3);
8902 setflags = !InITBlock();
8903 shift_t = SRType_LSL;
8904 shift_n = 0;
8905 break;
8906 case eEncodingT2:
8907 Rd = Bits32(opcode, 11, 8);
8908 Rn = Bits32(opcode, 19, 16);
8909 Rm = Bits32(opcode, 3, 0);
8910 setflags = BitIsSet(opcode, 20);
8911 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8912 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8913 return false;
8914 break;
8915 case eEncodingA1:
8916 Rd = Bits32(opcode, 15, 12);
8917 Rn = Bits32(opcode, 19, 16);
8918 Rm = Bits32(opcode, 3, 0);
8919 setflags = BitIsSet(opcode, 20);
8920 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008921
Johnny Chen9b381772011-02-23 01:01:21 +00008922 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008923 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008924 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008925 break;
8926 default:
8927 return false;
8928 }
8929 // Read the register value from register Rn.
8930 uint32_t val1 = ReadCoreReg(Rn, &success);
8931 if (!success)
8932 return false;
8933
8934 // Read the register value from register Rm.
8935 uint32_t val2 = ReadCoreReg(Rm, &success);
8936 if (!success)
8937 return false;
8938
Johnny Chena4438a72011-06-02 22:50:51 +00008939 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8940 if (!success)
8941 return false;
Johnny Chen9b381772011-02-23 01:01:21 +00008942 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8943
8944 EmulateInstruction::Context context;
8945 context.type = EmulateInstruction::eContextImmediate;
8946 context.SetNoArgs();
8947 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8948 return false;
8949
8950 return true;
8951}
8952
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008953// This instruction subtracts an immediate value from a register value, and writes the result
8954// to the destination register. It can optionally update the condition flags based on the result.
8955bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008956EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008957{
8958#if 0
8959 // ARM pseudo code...
8960 if ConditionPassed() then
8961 EncodingSpecificOperations();
8962 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8963 R[d] = result;
8964 if setflags then
8965 APSR.N = result<31>;
8966 APSR.Z = IsZeroBit(result);
8967 APSR.C = carry;
8968 APSR.V = overflow;
8969#endif
8970
8971 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008972
8973 uint32_t Rd; // the destination register
8974 uint32_t Rn; // the first operand
8975 bool setflags;
8976 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8977 switch (encoding) {
8978 case eEncodingT1:
8979 Rd = Bits32(opcode, 2, 0);
8980 Rn = Bits32(opcode, 5, 3);
8981 setflags = !InITBlock();
8982 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8983 break;
8984 case eEncodingT2:
8985 Rd = Rn = Bits32(opcode, 10, 8);
8986 setflags = !InITBlock();
8987 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8988 break;
8989 case eEncodingT3:
8990 Rd = Bits32(opcode, 11, 8);
8991 Rn = Bits32(opcode, 19, 16);
8992 setflags = BitIsSet(opcode, 20);
8993 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8994
8995 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8996 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008997 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008998
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008999 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009000 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009001 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009002
9003 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9004 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9005 return false;
9006 break;
9007 case eEncodingT4:
9008 Rd = Bits32(opcode, 11, 8);
9009 Rn = Bits32(opcode, 19, 16);
9010 setflags = BitIsSet(opcode, 20);
9011 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9012
9013 // if Rn == '1111' then SEE ADR;
9014 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00009015 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009016
9017 // if Rn == '1101' then SEE SUB (SP minus immediate);
9018 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009019 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009020
9021 if (BadReg(Rd))
9022 return false;
9023 break;
9024 default:
9025 return false;
9026 }
9027 // Read the register value from the operand register Rn.
9028 uint32_t reg_val = ReadCoreReg(Rn, &success);
9029 if (!success)
9030 return false;
9031
9032 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9033
9034 EmulateInstruction::Context context;
9035 context.type = EmulateInstruction::eContextImmediate;
9036 context.SetNoArgs ();
9037
9038 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9039 return false;
9040
9041 return true;
9042}
9043
9044// This instruction subtracts an immediate value from a register value, and writes the result
9045// to the destination register. It can optionally update the condition flags based on the result.
9046bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009047EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009048{
9049#if 0
9050 // ARM pseudo code...
9051 if ConditionPassed() then
9052 EncodingSpecificOperations();
9053 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9054 if d == 15 then
9055 ALUWritePC(result); // setflags is always FALSE here
9056 else
9057 R[d] = result;
9058 if setflags then
9059 APSR.N = result<31>;
9060 APSR.Z = IsZeroBit(result);
9061 APSR.C = carry;
9062 APSR.V = overflow;
9063#endif
9064
9065 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009066
9067 uint32_t Rd; // the destination register
9068 uint32_t Rn; // the first operand
9069 bool setflags;
9070 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9071 switch (encoding) {
9072 case eEncodingA1:
9073 Rd = Bits32(opcode, 15, 12);
9074 Rn = Bits32(opcode, 19, 16);
9075 setflags = BitIsSet(opcode, 20);
9076 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9077
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009078 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009079 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00009080 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009081
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009082 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009083 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009084 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009085
9086 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009087 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00009088 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009089 break;
9090 default:
9091 return false;
9092 }
9093 // Read the register value from the operand register Rn.
9094 uint32_t reg_val = ReadCoreReg(Rn, &success);
9095 if (!success)
9096 return false;
9097
9098 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9099
9100 EmulateInstruction::Context context;
9101 context.type = EmulateInstruction::eContextImmediate;
9102 context.SetNoArgs ();
9103
9104 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9105 return false;
9106
9107 return true;
9108}
9109
Johnny Chen2115b412011-02-21 23:42:44 +00009110// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9111// immediate value. It updates the condition flags based on the result, and discards the result.
9112bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009113EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009114{
9115#if 0
9116 // ARM pseudo code...
9117 if ConditionPassed() then
9118 EncodingSpecificOperations();
9119 result = R[n] EOR imm32;
9120 APSR.N = result<31>;
9121 APSR.Z = IsZeroBit(result);
9122 APSR.C = carry;
9123 // APSR.V unchanged
9124#endif
9125
9126 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009127
Greg Clayton7bc39082011-03-24 23:53:38 +00009128 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009129 {
9130 uint32_t Rn;
9131 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9132 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9133 switch (encoding)
9134 {
9135 case eEncodingT1:
9136 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009137 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009138 if (BadReg(Rn))
9139 return false;
9140 break;
9141 case eEncodingA1:
9142 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009143 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009144 break;
9145 default:
9146 return false;
9147 }
9148
9149 // Read the first operand.
9150 uint32_t val1 = ReadCoreReg(Rn, &success);
9151 if (!success)
9152 return false;
9153
9154 uint32_t result = val1 ^ imm32;
9155
9156 EmulateInstruction::Context context;
9157 context.type = EmulateInstruction::eContextImmediate;
9158 context.SetNoArgs ();
9159
9160 if (!WriteFlags(context, result, carry))
9161 return false;
9162 }
9163 return true;
9164}
9165
9166// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9167// optionally-shifted register value. It updates the condition flags based on the result, and discards
9168// the result.
9169bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009170EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009171{
9172#if 0
9173 // ARM pseudo code...
9174 if ConditionPassed() then
9175 EncodingSpecificOperations();
9176 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9177 result = R[n] EOR shifted;
9178 APSR.N = result<31>;
9179 APSR.Z = IsZeroBit(result);
9180 APSR.C = carry;
9181 // APSR.V unchanged
9182#endif
9183
9184 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009185
Greg Clayton7bc39082011-03-24 23:53:38 +00009186 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009187 {
9188 uint32_t Rn, Rm;
9189 ARM_ShifterType shift_t;
9190 uint32_t shift_n; // the shift applied to the value read from Rm
9191 uint32_t carry;
9192 switch (encoding)
9193 {
9194 case eEncodingT1:
9195 Rn = Bits32(opcode, 19, 16);
9196 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009197 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009198 if (BadReg(Rn) || BadReg(Rm))
9199 return false;
9200 break;
9201 case eEncodingA1:
9202 Rn = Bits32(opcode, 19, 16);
9203 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009204 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009205 break;
9206 default:
9207 return false;
9208 }
9209
9210 // Read the first operand.
9211 uint32_t val1 = ReadCoreReg(Rn, &success);
9212 if (!success)
9213 return false;
9214
9215 // Read the second operand.
9216 uint32_t val2 = ReadCoreReg(Rm, &success);
9217 if (!success)
9218 return false;
9219
Johnny Chena4438a72011-06-02 22:50:51 +00009220 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9221 if (!success)
9222 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00009223 uint32_t result = val1 ^ shifted;
9224
9225 EmulateInstruction::Context context;
9226 context.type = EmulateInstruction::eContextImmediate;
9227 context.SetNoArgs ();
9228
9229 if (!WriteFlags(context, result, carry))
9230 return false;
9231 }
9232 return true;
9233}
9234
Johnny Chende3cce32011-02-21 21:24:49 +00009235// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9236// It updates the condition flags based on the result, and discards the result.
9237bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009238EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009239{
9240#if 0
9241 // ARM pseudo code...
9242 if ConditionPassed() then
9243 EncodingSpecificOperations();
9244 result = R[n] AND imm32;
9245 APSR.N = result<31>;
9246 APSR.Z = IsZeroBit(result);
9247 APSR.C = carry;
9248 // APSR.V unchanged
9249#endif
9250
9251 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009252
Greg Clayton7bc39082011-03-24 23:53:38 +00009253 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009254 {
9255 uint32_t Rn;
9256 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9257 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9258 switch (encoding)
9259 {
9260 case eEncodingT1:
9261 Rn = Bits32(opcode, 19, 16);
9262 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9263 if (BadReg(Rn))
9264 return false;
9265 break;
9266 case eEncodingA1:
9267 Rn = Bits32(opcode, 19, 16);
9268 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9269 break;
9270 default:
9271 return false;
9272 }
9273
9274 // Read the first operand.
9275 uint32_t val1 = ReadCoreReg(Rn, &success);
9276 if (!success)
9277 return false;
9278
9279 uint32_t result = val1 & imm32;
9280
9281 EmulateInstruction::Context context;
9282 context.type = EmulateInstruction::eContextImmediate;
9283 context.SetNoArgs ();
9284
9285 if (!WriteFlags(context, result, carry))
9286 return false;
9287 }
9288 return true;
9289}
9290
9291// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9292// It updates the condition flags based on the result, and discards the result.
9293bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009294EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009295{
9296#if 0
9297 // ARM pseudo code...
9298 if ConditionPassed() then
9299 EncodingSpecificOperations();
9300 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9301 result = R[n] AND shifted;
9302 APSR.N = result<31>;
9303 APSR.Z = IsZeroBit(result);
9304 APSR.C = carry;
9305 // APSR.V unchanged
9306#endif
9307
9308 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009309
Greg Clayton7bc39082011-03-24 23:53:38 +00009310 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009311 {
9312 uint32_t Rn, Rm;
9313 ARM_ShifterType shift_t;
9314 uint32_t shift_n; // the shift applied to the value read from Rm
9315 uint32_t carry;
9316 switch (encoding)
9317 {
9318 case eEncodingT1:
9319 Rn = Bits32(opcode, 2, 0);
9320 Rm = Bits32(opcode, 5, 3);
9321 shift_t = SRType_LSL;
9322 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009323 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009324 case eEncodingT2:
9325 Rn = Bits32(opcode, 19, 16);
9326 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009327 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009328 if (BadReg(Rn) || BadReg(Rm))
9329 return false;
9330 break;
9331 case eEncodingA1:
9332 Rn = Bits32(opcode, 19, 16);
9333 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009334 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009335 break;
9336 default:
9337 return false;
9338 }
9339
9340 // Read the first operand.
9341 uint32_t val1 = ReadCoreReg(Rn, &success);
9342 if (!success)
9343 return false;
9344
9345 // Read the second operand.
9346 uint32_t val2 = ReadCoreReg(Rm, &success);
9347 if (!success)
9348 return false;
9349
Johnny Chena4438a72011-06-02 22:50:51 +00009350 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9351 if (!success)
9352 return false;
Johnny Chende3cce32011-02-21 21:24:49 +00009353 uint32_t result = val1 & shifted;
9354
9355 EmulateInstruction::Context context;
9356 context.type = EmulateInstruction::eContextImmediate;
9357 context.SetNoArgs ();
9358
9359 if (!WriteFlags(context, result, carry))
9360 return false;
9361 }
9362 return true;
9363}
Caroline Ticed05b4902011-03-29 21:24:06 +00009364
9365// A8.6.216 SUB (SP minus register)
9366bool
9367EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9368{
9369#if 0
9370 if ConditionPassed() then
9371 EncodingSpecificOperations();
9372 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009373 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009374 if d == 15 then // Can only occur for ARM encoding
9375 ALUWritePC(result); // setflags is always FALSE here
9376 else
9377 R[d] = result;
9378 if setflags then
9379 APSR.N = result<31>;
9380 APSR.Z = IsZeroBit(result);
9381 APSR.C = carry;
9382 APSR.V = overflow;
9383#endif
9384
9385 bool success = false;
9386
9387 if (ConditionPassed(opcode))
9388 {
9389 uint32_t d;
9390 uint32_t m;
9391 bool setflags;
9392 ARM_ShifterType shift_t;
9393 uint32_t shift_n;
9394
9395 switch (encoding)
9396 {
9397 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009398 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009399 d = Bits32 (opcode, 11, 8);
9400 m = Bits32 (opcode, 3, 0);
9401 setflags = BitIsSet (opcode, 20);
9402
9403 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9404 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9405
9406 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9407 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9408 return false;
9409
9410 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9411 if ((d == 15) || BadReg (m))
9412 return false;
9413 break;
9414
9415 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009416 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009417 d = Bits32 (opcode, 15, 12);
9418 m = Bits32 (opcode, 3, 0);
9419 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009420
Greg Clayton061b79d2011-05-09 20:18:18 +00009421 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009422 if (d == 15 && setflags)
9423 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009424
9425 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9426 shift_n = DecodeImmShiftARM (opcode, shift_t);
9427 break;
9428
9429 default:
9430 return false;
9431 }
9432
9433 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9434 uint32_t Rm = ReadCoreReg (m, &success);
9435 if (!success)
9436 return false;
9437
Johnny Chena4438a72011-06-02 22:50:51 +00009438 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9439 if (!success)
9440 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009441
Greg Clayton061b79d2011-05-09 20:18:18 +00009442 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009443 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9444 if (!success)
9445 return false;
9446
9447 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9448
9449 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009450 context.type = eContextArithmetic;
9451 RegisterInfo sp_reg;
9452 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9453 RegisterInfo dwarf_reg;
9454 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +00009455 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9456
Caroline Ticeef440002011-03-30 05:40:56 +00009457 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009458 return false;
9459 }
9460 return true;
9461}
9462
9463
9464// A8.6.7 ADD (register-shifted register)
9465bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009466EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009467{
9468#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009469 if ConditionPassed() then
9470 EncodingSpecificOperations();
9471 shift_n = UInt(R[s]<7:0>);
9472 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009473 (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009474 R[d] = result;
9475 if setflags then
9476 APSR.N = result<31>;
9477 APSR.Z = IsZeroBit(result);
9478 APSR.C = carry;
9479 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009480#endif
9481
Caroline Ticec08ed382011-03-29 23:03:16 +00009482 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009483
9484 if (ConditionPassed(opcode))
9485 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009486 uint32_t d;
9487 uint32_t n;
9488 uint32_t m;
9489 uint32_t s;
9490 bool setflags;
9491 ARM_ShifterType shift_t;
9492
Caroline Ticed05b4902011-03-29 21:24:06 +00009493 switch (encoding)
9494 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009495 case eEncodingA1:
9496 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9497 d = Bits32 (opcode, 15, 12);
9498 n = Bits32 (opcode, 19, 16);
9499 m = Bits32 (opcode, 3, 0);
9500 s = Bits32 (opcode, 11, 8);
9501
Greg Clayton061b79d2011-05-09 20:18:18 +00009502 // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
Caroline Ticec08ed382011-03-29 23:03:16 +00009503 setflags = BitIsSet (opcode, 20);
9504 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9505
9506 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9507 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9508 return false;
9509 break;
9510
9511 default:
9512 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009513 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009514
9515 // shift_n = UInt(R[s]<7:0>);
9516 uint32_t Rs = ReadCoreReg (s, &success);
9517 if (!success)
9518 return false;
9519
9520 uint32_t shift_n = Bits32 (Rs, 7, 0);
9521
9522 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9523 uint32_t Rm = ReadCoreReg (m, &success);
9524 if (!success)
9525 return false;
9526
Johnny Chena4438a72011-06-02 22:50:51 +00009527 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9528 if (!success)
9529 return false;
9530
Greg Clayton061b79d2011-05-09 20:18:18 +00009531 // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009532 uint32_t Rn = ReadCoreReg (n, &success);
9533 if (!success)
9534 return false;
9535
9536 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9537
9538 // R[d] = result;
9539 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009540 context.type = eContextArithmetic;
9541 RegisterInfo reg_n;
9542 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9543 RegisterInfo reg_m;
9544 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009545
9546 context.SetRegisterRegisterOperands (reg_n, reg_m);
9547
9548 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9549 return false;
9550
9551 // if setflags then
9552 // APSR.N = result<31>;
9553 // APSR.Z = IsZeroBit(result);
9554 // APSR.C = carry;
9555 // APSR.V = overflow;
9556 if (setflags)
9557 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009558 }
9559 return true;
9560}
9561
9562// A8.6.213 SUB (register)
9563bool
9564EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9565{
9566#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009567 if ConditionPassed() then
9568 EncodingSpecificOperations();
9569 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009570 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009571 if d == 15 then // Can only occur for ARM encoding
9572 ALUWritePC(result); // setflags is always FALSE here
9573 else
9574 R[d] = result;
9575 if setflags then
9576 APSR.N = result<31>;
9577 APSR.Z = IsZeroBit(result);
9578 APSR.C = carry;
9579 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009580#endif
9581
Caroline Tice4cccd532011-03-29 23:44:20 +00009582 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009583
9584 if (ConditionPassed(opcode))
9585 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009586 uint32_t d;
9587 uint32_t n;
9588 uint32_t m;
9589 bool setflags;
9590 ARM_ShifterType shift_t;
9591 uint32_t shift_n;
9592
Caroline Ticed05b4902011-03-29 21:24:06 +00009593 switch (encoding)
9594 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009595 case eEncodingT1:
9596 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9597 d = Bits32 (opcode, 2, 0);
9598 n = Bits32 (opcode, 5, 3);
9599 m = Bits32 (opcode, 8, 6);
9600 setflags = !InITBlock();
9601
9602 // (shift_t, shift_n) = (SRType_LSL, 0);
9603 shift_t = SRType_LSL;
9604 shift_n = 0;
9605
9606 break;
9607
9608 case eEncodingT2:
Greg Clayton061b79d2011-05-09 20:18:18 +00009609 // if Rd == Ô1111Õ && S == Ô1Õ then SEE CMP (register);
9610 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9611 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009612 d = Bits32 (opcode, 11, 8);
9613 n = Bits32 (opcode, 19, 16);
9614 m = Bits32 (opcode, 3, 0);
9615 setflags = BitIsSet (opcode, 20);
9616
9617 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9618 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9619
9620 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9621 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9622 return false;
9623
9624 break;
9625
9626 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009627 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9628 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009629 d = Bits32 (opcode, 15, 12);
9630 n = Bits32 (opcode, 19, 16);
9631 m = Bits32 (opcode, 3, 0);
9632 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009633
Greg Clayton061b79d2011-05-09 20:18:18 +00009634 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009635 if ((d == 15) && setflags)
9636 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009637
9638 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9639 shift_n = DecodeImmShiftARM (opcode, shift_t);
9640
9641 break;
9642
9643 default:
9644 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009645 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009646
9647 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9648 uint32_t Rm = ReadCoreReg (m, &success);
9649 if (!success)
9650 return false;
9651
Johnny Chena4438a72011-06-02 22:50:51 +00009652 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9653 if (!success)
9654 return false;
Caroline Tice4cccd532011-03-29 23:44:20 +00009655
Greg Clayton061b79d2011-05-09 20:18:18 +00009656 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009657 uint32_t Rn = ReadCoreReg (n, &success);
9658 if (!success)
9659 return false;
9660
9661 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9662
9663 // if d == 15 then // Can only occur for ARM encoding
9664 // ALUWritePC(result); // setflags is always FALSE here
9665 // else
9666 // R[d] = result;
9667 // if setflags then
9668 // APSR.N = result<31>;
9669 // APSR.Z = IsZeroBit(result);
9670 // APSR.C = carry;
9671 // APSR.V = overflow;
9672
9673 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009674 context.type = eContextArithmetic;
9675 RegisterInfo reg_n;
9676 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9677 RegisterInfo reg_m;
9678 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009679 context.SetRegisterRegisterOperands (reg_n, reg_m);
9680
Caroline Ticeef440002011-03-30 05:40:56 +00009681 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009682 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009683 }
9684 return true;
9685}
Caroline Tice4cccd532011-03-29 23:44:20 +00009686
Caroline Ticed05b4902011-03-29 21:24:06 +00009687// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009688// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9689// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009690bool
9691EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9692{
9693#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009694 if ConditionPassed() then
9695 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9696 address = R[n] + imm32;
9697 if ExclusiveMonitorsPass(address,4) then
9698 MemA[address,4] = R[t];
9699 R[d] = 0;
9700 else
9701 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009702#endif
9703
Caroline Tice5168b6c2011-03-30 05:15:46 +00009704 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009705
9706 if (ConditionPassed(opcode))
9707 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009708 uint32_t d;
9709 uint32_t t;
9710 uint32_t n;
9711 uint32_t imm32;
9712 const uint32_t addr_byte_size = GetAddressByteSize();
9713
Caroline Ticed05b4902011-03-29 21:24:06 +00009714 switch (encoding)
9715 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009716 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009717 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009718 d = Bits32 (opcode, 11, 8);
9719 t = Bits32 (opcode, 15, 12);
9720 n = Bits32 (opcode, 19, 16);
9721 imm32 = Bits32 (opcode, 7, 0) << 2;
9722
9723 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9724 if (BadReg (d) || BadReg (t) || (n == 15))
9725 return false;
9726
9727 // if d == n || d == t then UNPREDICTABLE;
9728 if ((d == n) || (d == t))
9729 return false;
9730
9731 break;
9732
9733 case eEncodingA1:
9734 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9735 d = Bits32 (opcode, 15, 12);
9736 t = Bits32 (opcode, 3, 0);
9737 n = Bits32 (opcode, 19, 16);
9738 imm32 = 0;
9739
9740 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9741 if ((d == 15) || (t == 15) || (n == 15))
9742 return false;
9743
9744 // if d == n || d == t then UNPREDICTABLE;
9745 if ((d == n) || (d == t))
9746 return false;
9747
9748 break;
9749
9750 default:
9751 return false;
9752 }
9753
9754 // address = R[n] + imm32;
9755 uint32_t Rn = ReadCoreReg (n, &success);
9756 if (!success)
9757 return false;
9758
9759 addr_t address = Rn + imm32;
9760
Greg Claytonc07d4512011-04-26 23:48:45 +00009761 RegisterInfo base_reg;
9762 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9763 RegisterInfo data_reg;
9764 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009765 EmulateInstruction::Context context;
9766 context.type = eContextRegisterStore;
9767 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9768
9769 // if ExclusiveMonitorsPass(address,4) then
9770 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9771 // always return true.
9772 if (true)
9773 {
9774 // MemA[address,4] = R[t];
9775 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9776 if (!success)
9777 return false;
9778
9779 if (!MemAWrite (context, address, Rt, addr_byte_size))
9780 return false;
9781
9782 // R[d] = 0;
9783 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9784 return false;
9785 }
9786 else
9787 {
9788 // R[d] = 1;
9789 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9790 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009791 }
9792 }
9793 return true;
9794}
9795
9796// A8.6.197 STRB (immediate, ARM)
9797bool
9798EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9799{
9800#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009801 if ConditionPassed() then
9802 EncodingSpecificOperations();
9803 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9804 address = if index then offset_addr else R[n];
9805 MemU[address,1] = R[t]<7:0>;
9806 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009807#endif
9808
Caroline Ticeef440002011-03-30 05:40:56 +00009809 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009810
9811 if (ConditionPassed(opcode))
9812 {
Caroline Ticeef440002011-03-30 05:40:56 +00009813 uint32_t t;
9814 uint32_t n;
9815 uint32_t imm32;
9816 bool index;
9817 bool add;
9818 bool wback;
9819
Caroline Ticed05b4902011-03-29 21:24:06 +00009820 switch (encoding)
9821 {
Caroline Ticeef440002011-03-30 05:40:56 +00009822 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009823 // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
Caroline Ticeef440002011-03-30 05:40:56 +00009824 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9825 t = Bits32 (opcode, 15, 12);
9826 n = Bits32 (opcode, 19, 16);
9827 imm32 = Bits32 (opcode, 11, 0);
9828
Greg Clayton061b79d2011-05-09 20:18:18 +00009829 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeef440002011-03-30 05:40:56 +00009830 index = BitIsSet (opcode, 24);
9831 add = BitIsSet (opcode, 23);
9832 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9833
9834 // if t == 15 then UNPREDICTABLE;
9835 if (t == 15)
9836 return false;
9837
9838 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9839 if (wback && ((n == 15) || (n == t)))
9840 return false;
9841
9842 break;
9843
9844 default:
9845 return false;
9846 }
9847
9848 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9849 uint32_t Rn = ReadCoreReg (n, &success);
9850 if (!success)
9851 return false;
9852
9853 addr_t offset_addr;
9854 if (add)
9855 offset_addr = Rn + imm32;
9856 else
9857 offset_addr = Rn - imm32;
9858
9859 // address = if index then offset_addr else R[n];
9860 addr_t address;
9861 if (index)
9862 address = offset_addr;
9863 else
9864 address = Rn;
9865
9866 // MemU[address,1] = R[t]<7:0>;
9867 uint32_t Rt = ReadCoreReg (t, &success);
9868 if (!success)
9869 return false;
9870
Greg Claytonc07d4512011-04-26 23:48:45 +00009871 RegisterInfo base_reg;
9872 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9873 RegisterInfo data_reg;
9874 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticeef440002011-03-30 05:40:56 +00009875 EmulateInstruction::Context context;
9876 context.type = eContextRegisterStore;
9877 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9878
9879 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9880 return false;
9881
9882 // if wback then R[n] = offset_addr;
9883 if (wback)
9884 {
Caroline Tice523c5542011-04-13 00:42:12 +00009885 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009886 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009887 }
9888 }
9889 return true;
9890}
9891
9892// A8.6.194 STR (immediate, ARM)
9893bool
9894EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9895{
9896#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009897 if ConditionPassed() then
9898 EncodingSpecificOperations();
9899 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9900 address = if index then offset_addr else R[n];
9901 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9902 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009903#endif
9904
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009905 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009906
9907 if (ConditionPassed(opcode))
9908 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009909 uint32_t t;
9910 uint32_t n;
9911 uint32_t imm32;
9912 bool index;
9913 bool add;
9914 bool wback;
9915
9916 const uint32_t addr_byte_size = GetAddressByteSize();
9917
Caroline Ticed05b4902011-03-29 21:24:06 +00009918 switch (encoding)
9919 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009920 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009921 // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
9922 // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009923 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9924 t = Bits32 (opcode, 15, 12);
9925 n = Bits32 (opcode, 19, 16);
9926 imm32 = Bits32 (opcode, 11, 0);
9927
Greg Clayton061b79d2011-05-09 20:18:18 +00009928 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009929 index = BitIsSet (opcode, 24);
9930 add = BitIsSet (opcode, 23);
9931 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9932
9933 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9934 if (wback && ((n == 15) || (n == t)))
9935 return false;
9936
9937 break;
9938
9939 default:
9940 return false;
9941 }
9942
9943 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9944 uint32_t Rn = ReadCoreReg (n, &success);
9945 if (!success)
9946 return false;
9947
9948 addr_t offset_addr;
9949 if (add)
9950 offset_addr = Rn + imm32;
9951 else
9952 offset_addr = Rn - imm32;
9953
9954 // address = if index then offset_addr else R[n];
9955 addr_t address;
9956 if (index)
9957 address = offset_addr;
9958 else
9959 address = Rn;
9960
Greg Claytonc07d4512011-04-26 23:48:45 +00009961 RegisterInfo base_reg;
9962 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9963 RegisterInfo data_reg;
9964 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009965 EmulateInstruction::Context context;
9966 context.type = eContextRegisterStore;
9967 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9968
9969 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9970 uint32_t Rt = ReadCoreReg (t, &success);
9971 if (!success)
9972 return false;
9973
9974 if (t == 15)
9975 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009976 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009977 if (!success)
9978 return false;
9979
9980 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9981 return false;
9982 }
9983 else
9984 {
9985 if (!MemUWrite (context, address, Rt, addr_byte_size))
9986 return false;
9987 }
9988
9989 // if wback then R[n] = offset_addr;
9990 if (wback)
9991 {
9992 context.type = eContextAdjustBaseRegister;
9993 context.SetImmediate (offset_addr);
9994
9995 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9996 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009997 }
9998 }
9999 return true;
10000}
10001
Caroline Ticed05b4902011-03-29 21:24:06 +000010002// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +000010003// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
10004// 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 +000010005bool
10006EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
10007{
10008#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +000010009 if ConditionPassed() then
10010 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10011 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10012 address = if index then offset_addr else R[n];
10013 R[t] = MemA[address,4];
10014 R[t2] = MemA[address+4,4];
10015 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010016#endif
10017
Caroline Tice1697dd72011-03-30 17:11:45 +000010018 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010019
10020 if (ConditionPassed(opcode))
10021 {
Caroline Tice1697dd72011-03-30 17:11:45 +000010022 uint32_t t;
10023 uint32_t t2;
10024 uint32_t n;
10025 uint32_t imm32;
10026 bool index;
10027 bool add;
10028 bool wback;
10029
Caroline Ticed05b4902011-03-29 21:24:06 +000010030 switch (encoding)
10031 {
Caroline Tice1697dd72011-03-30 17:11:45 +000010032 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010033 //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10034 //if Rn == Ô1111Õ then SEE LDRD (literal);
10035 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice1697dd72011-03-30 17:11:45 +000010036 t = Bits32 (opcode, 15, 12);
10037 t2 = Bits32 (opcode, 11, 8);
10038 n = Bits32 (opcode, 19, 16);
10039 imm32 = Bits32 (opcode, 7, 0) << 2;
10040
Greg Clayton061b79d2011-05-09 20:18:18 +000010041 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +000010042 index = BitIsSet (opcode, 24);
10043 add = BitIsSet (opcode, 23);
10044 wback = BitIsSet (opcode, 21);
10045
10046 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10047 if (wback && ((n == t) || (n == t2)))
10048 return false;
10049
10050 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10051 if (BadReg (t) || BadReg (t2) || (t == t2))
10052 return false;
10053
10054 break;
10055
10056 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010057 //if Rn == Ô1111Õ then SEE LDRD (literal);
10058 //if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010059 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10060 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010061 if (BitIsSet (t, 0))
10062 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +000010063 t2 = t + 1;
10064 n = Bits32 (opcode, 19, 16);
10065 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10066
Greg Clayton061b79d2011-05-09 20:18:18 +000010067 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +000010068 index = BitIsSet (opcode, 24);
10069 add = BitIsSet (opcode, 23);
10070 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10071
Greg Clayton061b79d2011-05-09 20:18:18 +000010072 //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010073 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10074 return false;
10075
10076 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10077 if (wback && ((n == t) || (n == t2)))
10078 return false;
10079
10080 //if t2 == 15 then UNPREDICTABLE;
10081 if (t2 == 15)
10082 return false;
10083
10084 break;
10085
10086 default:
10087 return false;
10088 }
10089
10090 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10091 uint32_t Rn = ReadCoreReg (n, &success);
10092 if (!success)
10093 return false;
10094
10095 addr_t offset_addr;
10096 if (add)
10097 offset_addr = Rn + imm32;
10098 else
10099 offset_addr = Rn - imm32;
10100
10101 //address = if index then offset_addr else R[n];
10102 addr_t address;
10103 if (index)
10104 address = offset_addr;
10105 else
10106 address = Rn;
10107
10108 //R[t] = MemA[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +000010109 RegisterInfo base_reg;
10110 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1697dd72011-03-30 17:11:45 +000010111
10112 EmulateInstruction::Context context;
10113 context.type = eContextRegisterLoad;
10114 context.SetRegisterPlusOffset (base_reg, address - Rn);
10115
10116 const uint32_t addr_byte_size = GetAddressByteSize();
10117 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10118 if (!success)
10119 return false;
10120
10121 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10122 return false;
10123
10124 //R[t2] = MemA[address+4,4];
10125
10126 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10127 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10128 if (!success)
10129 return false;
10130
10131 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10132 return false;
10133
10134 //if wback then R[n] = offset_addr;
10135 if (wback)
10136 {
10137 context.type = eContextAdjustBaseRegister;
10138 context.SetAddress (offset_addr);
10139
10140 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10141 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010142 }
10143 }
10144 return true;
10145}
10146
Caroline Ticed05b4902011-03-29 21:24:06 +000010147// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010148// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10149// 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 +000010150bool
10151EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10152{
10153#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010154 if ConditionPassed() then
10155 EncodingSpecificOperations();
10156 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10157 address = if index then offset_addr else R[n];
10158 R[t] = MemA[address,4];
10159 R[t2] = MemA[address+4,4];
10160 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010161#endif
10162
Caroline Ticeeab301f2011-03-30 17:54:52 +000010163 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010164
10165 if (ConditionPassed(opcode))
10166 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010167 uint32_t t;
10168 uint32_t t2;
10169 uint32_t n;
10170 uint32_t m;
10171 bool index;
10172 bool add;
10173 bool wback;
10174
Caroline Ticed05b4902011-03-29 21:24:06 +000010175 switch (encoding)
10176 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010177 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010178 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010179 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10180 t = Bits32 (opcode, 15, 12);
10181 if (BitIsSet (t, 0))
10182 return false;
10183 t2 = t + 1;
10184 n = Bits32 (opcode, 19, 16);
10185 m = Bits32 (opcode, 3, 0);
10186
Greg Clayton061b79d2011-05-09 20:18:18 +000010187 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010188 index = BitIsSet (opcode, 24);
10189 add = BitIsSet (opcode, 23);
10190 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10191
Greg Clayton061b79d2011-05-09 20:18:18 +000010192 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010193 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10194 return false;
10195
10196 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10197 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10198 return false;
10199
10200 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10201 if (wback && ((n == 15) || (n == t) || (n == t2)))
10202 return false;
10203
10204 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10205 if ((ArchVersion() < 6) && wback && (m == n))
10206 return false;
10207 break;
10208
10209 default:
10210 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010211 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010212
Caroline Ticeeab301f2011-03-30 17:54:52 +000010213 uint32_t Rn = ReadCoreReg (n, &success);
10214 if (!success)
10215 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010216 RegisterInfo base_reg;
10217 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010218
Caroline Ticeeab301f2011-03-30 17:54:52 +000010219 uint32_t Rm = ReadCoreReg (m, &success);
10220 if (!success)
10221 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010222 RegisterInfo offset_reg;
10223 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010224
Caroline Ticeeab301f2011-03-30 17:54:52 +000010225 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10226 addr_t offset_addr;
10227 if (add)
10228 offset_addr = Rn + Rm;
10229 else
10230 offset_addr = Rn - Rm;
10231
10232 // address = if index then offset_addr else R[n];
10233 addr_t address;
10234 if (index)
10235 address = offset_addr;
10236 else
10237 address = Rn;
10238
10239 EmulateInstruction::Context context;
10240 context.type = eContextRegisterLoad;
10241 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10242
10243 // R[t] = MemA[address,4];
10244 const uint32_t addr_byte_size = GetAddressByteSize();
10245 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10246 if (!success)
10247 return false;
10248
10249 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10250 return false;
10251
10252 // R[t2] = MemA[address+4,4];
10253
10254 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10255 if (!success)
10256 return false;
10257
10258 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10259 return false;
10260
10261 // if wback then R[n] = offset_addr;
10262 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010263 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010264 context.type = eContextAdjustBaseRegister;
10265 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010266
Caroline Ticeeab301f2011-03-30 17:54:52 +000010267 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10268 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010269 }
10270 }
10271 return true;
10272}
Caroline Ticed05b4902011-03-29 21:24:06 +000010273
10274// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010275// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10276// 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 +000010277bool
10278EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10279{
10280#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010281 if ConditionPassed() then
10282 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10283 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10284 address = if index then offset_addr else R[n];
10285 MemA[address,4] = R[t];
10286 MemA[address+4,4] = R[t2];
10287 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010288#endif
10289
Caroline Tice74467fe2011-03-30 19:02:56 +000010290 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010291
Caroline Tice74467fe2011-03-30 19:02:56 +000010292 if (ConditionPassed(opcode))
10293 {
10294 uint32_t t;
10295 uint32_t t2;
10296 uint32_t n;
10297 uint32_t imm32;
10298 bool index;
10299 bool add;
10300 bool wback;
10301
10302 switch (encoding)
10303 {
10304 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010305 // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10306 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice74467fe2011-03-30 19:02:56 +000010307 t = Bits32 (opcode, 15, 12);
10308 t2 = Bits32 (opcode, 11, 8);
10309 n = Bits32 (opcode, 19, 16);
10310 imm32 = Bits32 (opcode, 7, 0) << 2;
10311
Greg Clayton061b79d2011-05-09 20:18:18 +000010312 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010313 index = BitIsSet (opcode, 24);
10314 add = BitIsSet (opcode, 23);
10315 wback = BitIsSet (opcode, 21);
10316
10317 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10318 if (wback && ((n == t) || (n == t2)))
10319 return false;
10320
10321 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10322 if ((n == 15) || BadReg (t) || BadReg (t2))
10323 return false;
10324
10325 break;
10326
10327 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010328 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010329 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10330 t = Bits32 (opcode, 15, 12);
10331 if (BitIsSet (t, 0))
10332 return false;
10333
10334 t2 = t + 1;
10335 n = Bits32 (opcode, 19, 16);
10336 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10337
Greg Clayton061b79d2011-05-09 20:18:18 +000010338 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010339 index = BitIsSet (opcode, 24);
10340 add = BitIsSet (opcode, 23);
10341 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10342
Greg Clayton061b79d2011-05-09 20:18:18 +000010343 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010344 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10345 return false;
10346
10347 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10348 if (wback && ((n == 15) || (n == t) || (n == t2)))
10349 return false;
10350
10351 // if t2 == 15 then UNPREDICTABLE;
10352 if (t2 == 15)
10353 return false;
10354
10355 break;
10356
10357 default:
10358 return false;
10359 }
10360
Greg Claytonc07d4512011-04-26 23:48:45 +000010361 RegisterInfo base_reg;
10362 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010363
10364 uint32_t Rn = ReadCoreReg (n, &success);
10365 if (!success)
10366 return false;
10367
10368 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10369 addr_t offset_addr;
10370 if (add)
10371 offset_addr = Rn + imm32;
10372 else
10373 offset_addr = Rn - imm32;
10374
10375 //address = if index then offset_addr else R[n];
10376 addr_t address;
10377 if (index)
10378 address = offset_addr;
10379 else
10380 address = Rn;
10381
10382 //MemA[address,4] = R[t];
Greg Claytonc07d4512011-04-26 23:48:45 +000010383 RegisterInfo data_reg;
10384 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010385
10386 uint32_t data = ReadCoreReg (t, &success);
10387 if (!success)
10388 return false;
10389
10390 EmulateInstruction::Context context;
10391 context.type = eContextRegisterStore;
10392 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10393
10394 const uint32_t addr_byte_size = GetAddressByteSize();
10395
10396 if (!MemAWrite (context, address, data, addr_byte_size))
10397 return false;
10398
10399 //MemA[address+4,4] = R[t2];
Greg Claytonc07d4512011-04-26 23:48:45 +000010400 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010401 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10402
10403 data = ReadCoreReg (t2, &success);
10404 if (!success)
10405 return false;
10406
10407 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10408 return false;
10409
10410 //if wback then R[n] = offset_addr;
10411 if (wback)
10412 {
10413 context.type = eContextAdjustBaseRegister;
10414 context.SetAddress (offset_addr);
10415
10416 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10417 return false;
10418 }
10419 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010420 return true;
10421}
10422
10423
10424// A8.6.201 STRD (register)
10425bool
10426EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10427{
10428#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010429 if ConditionPassed() then
10430 EncodingSpecificOperations();
10431 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10432 address = if index then offset_addr else R[n];
10433 MemA[address,4] = R[t];
10434 MemA[address+4,4] = R[t2];
10435 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010436#endif
10437
Caroline Tice74467fe2011-03-30 19:02:56 +000010438 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010439
Caroline Tice74467fe2011-03-30 19:02:56 +000010440 if (ConditionPassed(opcode))
10441 {
10442 uint32_t t;
10443 uint32_t t2;
10444 uint32_t n;
10445 uint32_t m;
10446 bool index;
10447 bool add;
10448 bool wback;
10449
10450 switch (encoding)
10451 {
10452 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010453 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010454 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10455 t = Bits32 (opcode, 15, 12);
10456 if (BitIsSet (t, 0))
10457 return false;
10458
10459 t2 = t+1;
10460 n = Bits32 (opcode, 19, 16);
10461 m = Bits32 (opcode, 3, 0);
10462
Greg Clayton061b79d2011-05-09 20:18:18 +000010463 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010464 index = BitIsSet (opcode, 24);
10465 add = BitIsSet (opcode, 23);
10466 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10467
Greg Clayton061b79d2011-05-09 20:18:18 +000010468 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010469 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10470 return false;
10471
10472 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10473 if ((t2 == 15) || (m == 15))
10474 return false;
10475
10476 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10477 if (wback && ((n == 15) || (n == t) || (n == t2)))
10478 return false;
10479
10480 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010481 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010482 return false;
10483
10484 break;
10485
10486 default:
10487 return false;
10488 }
10489
Greg Claytonc07d4512011-04-26 23:48:45 +000010490 RegisterInfo base_reg;
10491 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10492 RegisterInfo offset_reg;
10493 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10494 RegisterInfo data_reg;
Caroline Tice74467fe2011-03-30 19:02:56 +000010495
10496 uint32_t Rn = ReadCoreReg (n, &success);
10497 if (!success)
10498 return false;
10499
10500 uint32_t Rm = ReadCoreReg (m, &success);
10501 if (!success)
10502 return false;
10503
10504 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10505 addr_t offset_addr;
10506 if (add)
10507 offset_addr = Rn + Rm;
10508 else
10509 offset_addr = Rn - Rm;
10510
10511 // address = if index then offset_addr else R[n];
10512 addr_t address;
10513 if (index)
10514 address = offset_addr;
10515 else
10516 address = Rn;
10517 // MemA[address,4] = R[t];
10518 uint32_t Rt = ReadCoreReg (t, &success);
10519 if (!success)
10520 return false;
10521
10522 EmulateInstruction::Context context;
10523 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +000010524 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010525 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10526
10527 const uint32_t addr_byte_size = GetAddressByteSize();
10528
10529 if (!MemAWrite (context, address, Rt, addr_byte_size))
10530 return false;
10531
10532 // MemA[address+4,4] = R[t2];
10533 uint32_t Rt2 = ReadCoreReg (t2, &success);
10534 if (!success)
10535 return false;
10536
Greg Claytonc07d4512011-04-26 23:48:45 +000010537 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010538
10539 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10540
10541 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10542 return false;
10543
10544 // if wback then R[n] = offset_addr;
10545 if (wback)
10546 {
10547 context.type = eContextAdjustBaseRegister;
10548 context.SetAddress (offset_addr);
10549
10550 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10551 return false;
10552
10553 }
10554 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010555 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010556}
10557
Caroline Tice4f605582011-03-31 00:02:51 +000010558// A8.6.319 VLDM
10559// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10560// an ARM core register.
10561bool
10562EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10563{
10564#if 0
10565 if ConditionPassed() then
10566 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10567 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010568 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010569 for r = 0 to regs-1
10570 if single_regs then
10571 S[d+r] = MemA[address,4]; address = address+4;
10572 else
10573 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10574 // Combine the word-aligned words in the correct order for current endianness.
10575 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10576#endif
10577
10578 bool success = false;
10579
10580 if (ConditionPassed(opcode))
10581 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010582 bool single_regs;
10583 bool add;
10584 bool wback;
10585 uint32_t d;
10586 uint32_t n;
10587 uint32_t imm32;
10588 uint32_t regs;
10589
Caroline Tice4f605582011-03-31 00:02:51 +000010590 switch (encoding)
10591 {
10592 case eEncodingT1:
10593 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010594 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10595 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10596 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10597 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010598 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10599 return false;
10600
10601 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010602 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice4f605582011-03-31 00:02:51 +000010603 single_regs = false;
10604 add = BitIsSet (opcode, 23);
10605 wback = BitIsSet (opcode, 21);
10606
Greg Clayton061b79d2011-05-09 20:18:18 +000010607 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice4f605582011-03-31 00:02:51 +000010608 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10609 n = Bits32 (opcode, 19, 16);
10610 imm32 = Bits32 (opcode, 7, 0) << 2;
10611
Greg Clayton061b79d2011-05-09 20:18:18 +000010612 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
Caroline Tice4f605582011-03-31 00:02:51 +000010613 regs = Bits32 (opcode, 7, 0) / 2;
10614
10615 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10616 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10617 return false;
10618
10619 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10620 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10621 return false;
10622
10623 break;
10624
10625 case eEncodingT2:
10626 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010627 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10628 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10629 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10630 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010631 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10632 return false;
10633
10634 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010635 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Tice4f605582011-03-31 00:02:51 +000010636 single_regs = true;
10637 add = BitIsSet (opcode, 23);
10638 wback = BitIsSet (opcode, 21);
10639 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10640 n = Bits32 (opcode, 19, 16);
10641
Greg Clayton061b79d2011-05-09 20:18:18 +000010642 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Tice4f605582011-03-31 00:02:51 +000010643 imm32 = Bits32 (opcode, 7, 0) << 2;
10644 regs = Bits32 (opcode, 7, 0);
10645
10646 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10647 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10648 return false;
10649
10650 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10651 if ((regs == 0) || ((d + regs) > 32))
10652 return false;
10653 break;
10654
10655 default:
10656 return false;
10657 }
10658
Greg Claytonc07d4512011-04-26 23:48:45 +000010659 RegisterInfo base_reg;
10660 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4f605582011-03-31 00:02:51 +000010661
10662 uint32_t Rn = ReadCoreReg (n, &success);
10663 if (!success)
10664 return false;
10665
10666 // address = if add then R[n] else R[n]-imm32;
10667 addr_t address;
10668 if (add)
10669 address = Rn;
10670 else
10671 address = Rn - imm32;
10672
Greg Claytonc07d4512011-04-26 23:48:45 +000010673 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010674 EmulateInstruction::Context context;
10675
10676 if (wback)
10677 {
10678 uint32_t value;
10679 if (add)
10680 value = Rn + imm32;
10681 else
10682 value = Rn - imm32;
10683
10684 context.type = eContextAdjustBaseRegister;
10685 context.SetImmediateSigned (value - Rn);
10686 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10687 return false;
10688
10689 }
10690
10691 const uint32_t addr_byte_size = GetAddressByteSize();
10692 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10693
10694 context.type = eContextRegisterLoad;
10695
10696 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010697 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010698 {
10699 if (single_regs)
10700 {
10701 // S[d+r] = MemA[address,4]; address = address+4;
10702 context.SetRegisterPlusOffset (base_reg, address - Rn);
10703
10704 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10705 if (!success)
10706 return false;
10707
10708 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10709 return false;
10710
10711 address = address + 4;
10712 }
10713 else
10714 {
10715 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10716 context.SetRegisterPlusOffset (base_reg, address - Rn);
10717 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10718 if (!success)
10719 return false;
10720
10721 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10722 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10723 if (!success)
10724 return false;
10725
10726 address = address + 8;
10727 // // Combine the word-aligned words in the correct order for current endianness.
10728 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10729 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010730 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010731 {
10732 data = word1;
10733 data = (data << 32) | word2;
10734 }
10735 else
10736 {
10737 data = word2;
10738 data = (data << 32) | word1;
10739 }
10740
10741 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10742 return false;
10743 }
10744 }
10745 }
10746 return true;
10747}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010748
10749// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010750// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10751// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010752bool
10753EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10754{
10755#if 0
10756 if ConditionPassed() then
10757 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10758 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010759 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010760 for r = 0 to regs-1
10761 if single_regs then
10762 MemA[address,4] = S[d+r]; address = address+4;
10763 else
10764 // Store as two word-aligned words in the correct order for current endianness.
10765 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10766 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10767 address = address+8;
10768#endif
10769
10770 bool success = false;
10771
10772 if (ConditionPassed (opcode))
10773 {
10774 bool single_regs;
10775 bool add;
10776 bool wback;
10777 uint32_t d;
10778 uint32_t n;
10779 uint32_t imm32;
10780 uint32_t regs;
10781
10782 switch (encoding)
10783 {
10784 case eEncodingT1:
10785 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010786 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10787 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10788 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10789 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010790 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10791 return false;
10792
10793 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010794 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010795 single_regs = false;
10796 add = BitIsSet (opcode, 23);
10797 wback = BitIsSet (opcode, 21);
10798
Greg Clayton061b79d2011-05-09 20:18:18 +000010799 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010800 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10801 n = Bits32 (opcode, 19, 16);
10802 imm32 = Bits32 (opcode, 7, 0) << 2;
10803
Greg Clayton061b79d2011-05-09 20:18:18 +000010804 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010805 regs = Bits32 (opcode, 7, 0) / 2;
10806
10807 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10808 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10809 return false;
10810
10811 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10812 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10813 return false;
10814
10815 break;
10816
10817 case eEncodingT2:
10818 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010819 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10820 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10821 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10822 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010823 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10824 return false;
10825
10826 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010827 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010828 single_regs = true;
10829 add = BitIsSet (opcode, 23);
10830 wback = BitIsSet (opcode, 21);
10831 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10832 n = Bits32 (opcode, 19, 16);
10833
Greg Clayton061b79d2011-05-09 20:18:18 +000010834 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010835 imm32 = Bits32 (opcode, 7, 0) << 2;
10836 regs = Bits32 (opcode, 7, 0);
10837
10838 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10839 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10840 return false;
10841
10842 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10843 if ((regs == 0) || ((d + regs) > 32))
10844 return false;
10845
10846 break;
10847
10848 default:
10849 return false;
10850 }
10851
Greg Claytonc07d4512011-04-26 23:48:45 +000010852 RegisterInfo base_reg;
10853 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010854
10855 uint32_t Rn = ReadCoreReg (n, &success);
10856 if (!success)
10857 return false;
10858
10859 // address = if add then R[n] else R[n]-imm32;
10860 addr_t address;
10861 if (add)
10862 address = Rn;
10863 else
10864 address = Rn - imm32;
10865
10866 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +000010867 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010868 if (wback)
10869 {
10870 uint32_t value;
10871 if (add)
10872 value = Rn + imm32;
10873 else
10874 value = Rn - imm32;
10875
10876 context.type = eContextAdjustBaseRegister;
10877 context.SetRegisterPlusOffset (base_reg, value - Rn);
10878
10879 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10880 return false;
10881 }
10882
10883 const uint32_t addr_byte_size = GetAddressByteSize();
10884 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10885
10886 context.type = eContextRegisterStore;
10887 // for r = 0 to regs-1
10888 for (int r = 0; r < regs; ++r)
10889 {
Greg Claytonc07d4512011-04-26 23:48:45 +000010890
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010891 if (single_regs)
10892 {
10893 // MemA[address,4] = S[d+r]; address = address+4;
10894 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10895 if (!success)
10896 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010897
10898 RegisterInfo data_reg;
10899 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010900 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10901 if (!MemAWrite (context, address, data, addr_byte_size))
10902 return false;
10903
10904 address = address + 4;
10905 }
10906 else
10907 {
10908 // // Store as two word-aligned words in the correct order for current endianness.
10909 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10910 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10911 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10912 if (!success)
10913 return false;
10914
Greg Claytonc07d4512011-04-26 23:48:45 +000010915 RegisterInfo data_reg;
10916 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010917
Greg Clayton888a7332011-04-26 04:39:08 +000010918 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010919 {
10920 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10921 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10922 return false;
10923
10924 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10925 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10926 return false;
10927 }
10928 else
10929 {
10930 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10931 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10932 return false;
10933
10934 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10935 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10936 return false;
10937 }
10938 // address = address+8;
10939 address = address + 8;
10940 }
10941 }
10942 }
10943 return true;
10944}
10945
Caroline Tice917ad352011-03-31 05:05:30 +000010946// A8.6.320
10947// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10948// an optional offset.
10949bool
10950EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10951{
10952#if 0
10953 if ConditionPassed() then
10954 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10955 base = if n == 15 then Align(PC,4) else R[n];
10956 address = if add then (base + imm32) else (base - imm32);
10957 if single_reg then
10958 S[d] = MemA[address,4];
10959 else
10960 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10961 // Combine the word-aligned words in the correct order for current endianness.
10962 D[d] = if BigEndian() then word1:word2 else word2:word1;
10963#endif
10964
10965 bool success = false;
10966
10967 if (ConditionPassed (opcode))
10968 {
10969 bool single_reg;
10970 bool add;
10971 uint32_t imm32;
10972 uint32_t d;
10973 uint32_t n;
10974
10975 switch (encoding)
10976 {
10977 case eEncodingT1:
10978 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010979 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010980 single_reg = false;
10981 add = BitIsSet (opcode, 23);
10982 imm32 = Bits32 (opcode, 7, 0) << 2;
10983
10984 // d = UInt(D:Vd); n = UInt(Rn);
10985 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10986 n = Bits32 (opcode, 19, 16);
10987
10988 break;
10989
10990 case eEncodingT2:
10991 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010992 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010993 single_reg = true;
10994 add = BitIsSet (opcode, 23);
10995 imm32 = Bits32 (opcode, 7, 0) << 2;
10996
10997 // d = UInt(Vd:D); n = UInt(Rn);
10998 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10999 n = Bits32 (opcode, 19, 16);
11000
11001 break;
11002
11003 default:
11004 return false;
11005 }
Greg Claytonc07d4512011-04-26 23:48:45 +000011006 RegisterInfo base_reg;
11007 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice917ad352011-03-31 05:05:30 +000011008
11009 uint32_t Rn = ReadCoreReg (n, &success);
11010 if (!success)
11011 return false;
11012
11013 // base = if n == 15 then Align(PC,4) else R[n];
11014 uint32_t base;
11015 if (n == 15)
11016 base = AlignPC (Rn);
11017 else
11018 base = Rn;
11019
11020 // address = if add then (base + imm32) else (base - imm32);
11021 addr_t address;
11022 if (add)
11023 address = base + imm32;
11024 else
11025 address = base - imm32;
11026
11027 const uint32_t addr_byte_size = GetAddressByteSize();
11028 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11029
11030 EmulateInstruction::Context context;
11031 context.type = eContextRegisterLoad;
11032 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000011033
Caroline Tice917ad352011-03-31 05:05:30 +000011034 if (single_reg)
11035 {
11036 // S[d] = MemA[address,4];
11037 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
11038 if (!success)
11039 return false;
11040
11041 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
11042 return false;
11043 }
11044 else
11045 {
11046 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11047 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
11048 if (!success)
11049 return false;
11050
11051 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
11052 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
11053 if (!success)
11054 return false;
11055 // // Combine the word-aligned words in the correct order for current endianness.
11056 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11057 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000011058 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000011059 {
11060 data64 = word1;
11061 data64 = (data64 << 32) | word2;
11062 }
11063 else
11064 {
11065 data64 = word2;
11066 data64 = (data64 << 32) | word1;
11067 }
11068
11069 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
11070 return false;
11071 }
11072 }
11073 return true;
11074}
Caroline Tice424652f2011-03-31 05:38:36 +000011075
11076// A8.6.400 VSTR
11077// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
11078// optional offset.
11079bool
11080EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
11081{
11082#if 0
11083 if ConditionPassed() then
11084 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11085 address = if add then (R[n] + imm32) else (R[n] - imm32);
11086 if single_reg then
11087 MemA[address,4] = S[d];
11088 else
11089 // Store as two word-aligned words in the correct order for current endianness.
11090 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11091 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11092#endif
11093
11094 bool success = false;
11095
11096 if (ConditionPassed (opcode))
11097 {
11098 bool single_reg;
11099 bool add;
11100 uint32_t imm32;
11101 uint32_t d;
11102 uint32_t n;
11103
11104 switch (encoding)
11105 {
11106 case eEncodingT1:
11107 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011108 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011109 single_reg = false;
11110 add = BitIsSet (opcode, 23);
11111 imm32 = Bits32 (opcode, 7, 0) << 2;
11112
11113 // d = UInt(D:Vd); n = UInt(Rn);
11114 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11115 n = Bits32 (opcode, 19, 16);
11116
11117 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11118 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11119 return false;
11120
11121 break;
11122
11123 case eEncodingT2:
11124 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011125 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011126 single_reg = true;
11127 add = BitIsSet (opcode, 23);
11128 imm32 = Bits32 (opcode, 7, 0) << 2;
11129
11130 // d = UInt(Vd:D); n = UInt(Rn);
11131 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11132 n = Bits32 (opcode, 19, 16);
11133
11134 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11135 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11136 return false;
11137
11138 break;
11139
11140 default:
11141 return false;
11142 }
11143
Greg Claytonc07d4512011-04-26 23:48:45 +000011144 RegisterInfo base_reg;
11145 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011146
11147 uint32_t Rn = ReadCoreReg (n, &success);
11148 if (!success)
11149 return false;
11150
11151 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11152 addr_t address;
11153 if (add)
11154 address = Rn + imm32;
11155 else
11156 address = Rn - imm32;
11157
11158 const uint32_t addr_byte_size = GetAddressByteSize();
11159 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11160
Greg Claytonc07d4512011-04-26 23:48:45 +000011161 RegisterInfo data_reg;
11162 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011163 EmulateInstruction::Context context;
11164 context.type = eContextRegisterStore;
11165 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11166
11167 if (single_reg)
11168 {
11169 // MemA[address,4] = S[d];
11170 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11171 if (!success)
11172 return false;
11173
11174 if (!MemAWrite (context, address, data, addr_byte_size))
11175 return false;
11176 }
11177 else
11178 {
11179 // // Store as two word-aligned words in the correct order for current endianness.
11180 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11181 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11182 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11183 if (!success)
11184 return false;
11185
Greg Clayton888a7332011-04-26 04:39:08 +000011186 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011187 {
11188 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11189 return false;
11190
11191 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11192 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11193 return false;
11194 }
11195 else
11196 {
11197 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11198 return false;
11199
11200 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11201 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11202 return false;
11203 }
11204 }
11205 }
11206 return true;
11207}
Caroline Tice9121b352011-03-31 16:41:19 +000011208
11209// A8.6.307 VLDI1 (multiple single elements)
11210// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11211// element of each register is loaded.
11212bool
11213EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11214{
11215#if 0
11216 if ConditionPassed() then
11217 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11218 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11219 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11220 for r = 0 to regs-1
11221 for e = 0 to elements-1
11222 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11223 address = address + ebytes;
11224#endif
11225
11226 bool success = false;
11227
11228 if (ConditionPassed (opcode))
11229 {
11230 uint32_t regs;
11231 uint32_t alignment;
11232 uint32_t ebytes;
11233 uint32_t esize;
11234 uint32_t elements;
11235 uint32_t d;
11236 uint32_t n;
11237 uint32_t m;
11238 bool wback;
11239 bool register_index;
11240
11241 switch (encoding)
11242 {
11243 case eEncodingT1:
11244 case eEncodingA1:
11245 {
11246 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011247 // when Ô0111Õ
11248 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
11249 // when Ô1010Õ
11250 // regs = 2; if align == Ô11Õ then UNDEFINED;
11251 // when Ô0110Õ
11252 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
11253 // when Ô0010Õ
Caroline Tice9121b352011-03-31 16:41:19 +000011254 // regs = 4;
11255 // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011256 // SEE ÒRelated encodingsÓ;
Caroline Tice9121b352011-03-31 16:41:19 +000011257 uint32_t type = Bits32 (opcode, 11, 8);
11258 uint32_t align = Bits32 (opcode, 5, 4);
11259 if (type == 7) // '0111'
11260 {
11261 regs = 1;
11262 if (BitIsSet (align, 1))
11263 return false;
11264 }
11265 else if (type == 10) // '1010'
11266 {
11267 regs = 2;
11268 if (align == 3)
11269 return false;
11270
11271 }
11272 else if (type == 6) // '0110'
11273 {
11274 regs = 3;
11275 if (BitIsSet (align, 1))
11276 return false;
11277 }
11278 else if (type == 2) // '0010'
11279 {
11280 regs = 4;
11281 }
11282 else
11283 return false;
11284
Greg Clayton061b79d2011-05-09 20:18:18 +000011285 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice9121b352011-03-31 16:41:19 +000011286 if (align == 0)
11287 alignment = 1;
11288 else
11289 alignment = 4 << align;
11290
11291 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11292 ebytes = 1 << Bits32 (opcode, 7, 6);
11293 esize = 8 * ebytes;
11294 elements = 8 / ebytes;
11295
11296 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11297 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11298 n = Bits32 (opcode, 19, 15);
11299 m = Bits32 (opcode, 3, 0);
11300
11301 // wback = (m != 15); register_index = (m != 15 && m != 13);
11302 wback = (m != 15);
11303 register_index = ((m != 15) && (m != 13));
11304
11305 // if d+regs > 32 then UNPREDICTABLE;
11306 if ((d + regs) > 32)
11307 return false;
11308 }
11309 break;
11310
11311 default:
11312 return false;
11313 }
11314
Greg Claytonc07d4512011-04-26 23:48:45 +000011315 RegisterInfo base_reg;
11316 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice9121b352011-03-31 16:41:19 +000011317
11318 uint32_t Rn = ReadCoreReg (n, &success);
11319 if (!success)
11320 return false;
11321
11322 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11323 addr_t address = Rn;
11324 if ((address % alignment) != 0)
11325 return false;
11326
11327 EmulateInstruction::Context context;
11328 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11329 if (wback)
11330 {
11331 uint32_t Rm = ReadCoreReg (m, &success);
11332 if (!success)
11333 return false;
11334
11335 uint32_t offset;
11336 if (register_index)
11337 offset = Rm;
11338 else
11339 offset = 8 * regs;
11340
11341 uint32_t value = Rn + offset;
11342 context.type = eContextAdjustBaseRegister;
11343 context.SetRegisterPlusOffset (base_reg, offset);
11344
11345 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11346 return false;
11347
11348 }
11349
11350 // for r = 0 to regs-1
11351 for (int r = 0; r < regs; ++r)
11352 {
11353 // for e = 0 to elements-1
11354 uint64_t assembled_data = 0;
11355 for (int e = 0; e < elements; ++e)
11356 {
11357 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11358 context.type = eContextRegisterLoad;
11359 context.SetRegisterPlusOffset (base_reg, address - Rn);
11360 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11361 if (!success)
11362 return false;
11363
11364 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11365
11366 // address = address + ebytes;
11367 address = address + ebytes;
11368 }
11369 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11370 return false;
11371 }
11372 }
11373 return true;
11374}
11375
Caroline Ticeb6281b12011-03-31 17:58:23 +000011376// A8.6.308 VLD1 (single element to one lane)
11377//
11378bool
11379EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11380{
11381#if 0
11382 if ConditionPassed() then
11383 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11384 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11385 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11386 Elem[D[d],index,esize] = MemU[address,ebytes];
11387#endif
11388
11389 bool success = false;
11390
11391 if (ConditionPassed (opcode))
11392 {
11393 uint32_t ebytes;
11394 uint32_t esize;
11395 uint32_t index;
11396 uint32_t alignment;
11397 uint32_t d;
11398 uint32_t n;
11399 uint32_t m;
11400 bool wback;
11401 bool register_index;
11402
11403 switch (encoding)
11404 {
11405 case eEncodingT1:
11406 case eEncodingA1:
11407 {
11408 uint32_t size = Bits32 (opcode, 11, 10);
11409 uint32_t index_align = Bits32 (opcode, 7, 4);
Greg Clayton061b79d2011-05-09 20:18:18 +000011410 // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011411 if (size == 3)
11412 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011413 // case size of
11414 if (size == 0) // when '00'
11415 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011416 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011417 if (BitIsClear (index_align, 0))
11418 return false;
11419
11420 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11421 ebytes = 1;
11422 esize = 8;
11423 index = Bits32 (index_align, 3, 1);
11424 alignment = 1;
11425 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011426 else if (size == 1) // when Ô01Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011427 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011428 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011429 if (BitIsClear (index_align, 1))
11430 return false;
11431
11432 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11433 ebytes = 2;
11434 esize = 16;
11435 index = Bits32 (index_align, 3, 2);
11436
Greg Clayton061b79d2011-05-09 20:18:18 +000011437 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011438 if (BitIsClear (index_align, 0))
11439 alignment = 1;
11440 else
11441 alignment = 2;
11442 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011443 else if (size == 2) // when Ô10Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011444 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011445 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011446 if (BitIsClear (index_align, 2))
11447 return false;
11448
Greg Clayton061b79d2011-05-09 20:18:18 +000011449 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011450 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11451 return false;
11452
11453 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11454 ebytes = 4;
11455 esize = 32;
11456 index = Bit32 (index_align, 3);
11457
Greg Clayton061b79d2011-05-09 20:18:18 +000011458 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011459 if (Bits32 (index_align, 1, 0) == 0)
11460 alignment = 1;
11461 else
11462 alignment = 4;
11463 }
11464 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11465 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11466 n = Bits32 (opcode, 19, 16);
11467 m = Bits32 (opcode, 3, 0);
11468
11469 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11470 wback = (m != 15);
11471 register_index = ((m != 15) && (m != 13));
11472
11473 if (n == 15)
11474 return false;
11475
11476 }
11477 break;
11478
11479 default:
11480 return false;
11481 }
11482
Greg Claytonc07d4512011-04-26 23:48:45 +000011483 RegisterInfo base_reg;
11484 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011485
11486 uint32_t Rn = ReadCoreReg (n, &success);
11487 if (!success)
11488 return false;
11489
11490 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11491 addr_t address = Rn;
11492 if ((address % alignment) != 0)
11493 return false;
11494
11495 EmulateInstruction::Context context;
11496 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11497 if (wback)
11498 {
11499 uint32_t Rm = ReadCoreReg (m, &success);
11500 if (!success)
11501 return false;
11502
11503 uint32_t offset;
11504 if (register_index)
11505 offset = Rm;
11506 else
11507 offset = ebytes;
11508
11509 uint32_t value = Rn + offset;
11510
11511 context.type = eContextAdjustBaseRegister;
11512 context.SetRegisterPlusOffset (base_reg, offset);
11513
11514 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11515 return false;
11516 }
11517
11518 // Elem[D[d],index,esize] = MemU[address,ebytes];
11519 uint32_t element = MemURead (context, address, esize, 0, &success);
11520 if (!success)
11521 return false;
11522
11523 element = element << (index * esize);
11524
11525 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11526 if (!success)
11527 return false;
11528
11529 uint64_t all_ones = -1;
11530 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11531 // at element & to the right of element.
11532 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011533 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 +000011534 // now mask should be 0's where element goes & 1's
11535 // everywhere else.
11536
11537 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11538 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11539
11540 context.type = eContextRegisterLoad;
11541 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11542 return false;
11543 }
11544 return true;
11545}
11546
Caroline Tice1e542e32011-03-31 18:44:04 +000011547// A8.6.391 VST1 (multiple single elements)
11548// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11549// interleaving. Every element of each register is stored.
11550bool
11551EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11552{
11553#if 0
11554 if ConditionPassed() then
11555 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11556 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11557 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11558 for r = 0 to regs-1
11559 for e = 0 to elements-1
11560 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11561 address = address + ebytes;
11562#endif
11563
11564 bool success = false;
11565
11566 if (ConditionPassed (opcode))
11567 {
11568 uint32_t regs;
11569 uint32_t alignment;
11570 uint32_t ebytes;
11571 uint32_t esize;
11572 uint32_t elements;
11573 uint32_t d;
11574 uint32_t n;
11575 uint32_t m;
11576 bool wback;
11577 bool register_index;
11578
11579 switch (encoding)
11580 {
11581 case eEncodingT1:
11582 case eEncodingA1:
11583 {
11584 uint32_t type = Bits32 (opcode, 11, 8);
11585 uint32_t align = Bits32 (opcode, 5, 4);
11586
11587 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011588 if (type == 7) // when Ô0111Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011589 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011590 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011591 regs = 1;
11592 if (BitIsSet (align, 1))
11593 return false;
11594 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011595 else if (type == 10) // when Ô1010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011596 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011597 // regs = 2; if align == Ô11Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011598 regs = 2;
11599 if (align == 3)
11600 return false;
11601 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011602 else if (type == 6) // when Ô0110Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011603 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011604 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011605 regs = 3;
11606 if (BitIsSet (align, 1))
11607 return false;
11608 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011609 else if (type == 2) // when Ô0010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011610 // regs = 4;
11611 regs = 4;
11612 else // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011613 // SEE ÒRelated encodingsÓ;
Caroline Tice1e542e32011-03-31 18:44:04 +000011614 return false;
11615
Greg Clayton061b79d2011-05-09 20:18:18 +000011616 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice1e542e32011-03-31 18:44:04 +000011617 if (align == 0)
11618 alignment = 0;
11619 else
11620 alignment = 4 << align;
11621
11622 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11623 ebytes = 1 << Bits32 (opcode,7, 6);
11624 esize = 8 * ebytes;
11625 elements = 8 / ebytes;
11626
11627 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11628 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11629 n = Bits32 (opcode, 19, 16);
11630 m = Bits32 (opcode, 3, 0);
11631
11632 // wback = (m != 15); register_index = (m != 15 && m != 13);
11633 wback = (m != 15);
11634 register_index = ((m != 15) && (m != 13));
11635
11636 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11637 if ((d + regs) > 32)
11638 return false;
11639
11640 if (n == 15)
11641 return false;
11642
11643 }
11644 break;
11645
11646 default:
11647 return false;
11648 }
11649
Greg Claytonc07d4512011-04-26 23:48:45 +000011650 RegisterInfo base_reg;
11651 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011652
11653 uint32_t Rn = ReadCoreReg (n, &success);
11654 if (!success)
11655 return false;
11656
11657 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11658 addr_t address = Rn;
11659 if ((address % alignment) != 0)
11660 return false;
11661
11662 EmulateInstruction::Context context;
11663 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11664 if (wback)
11665 {
11666 uint32_t Rm = ReadCoreReg (m, &success);
11667 if (!success)
11668 return false;
11669
11670 uint32_t offset;
11671 if (register_index)
11672 offset = Rm;
11673 else
11674 offset = 8 * regs;
11675
11676 context.type = eContextAdjustBaseRegister;
11677 context.SetRegisterPlusOffset (base_reg, offset);
11678
11679 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11680 return false;
11681 }
11682
Greg Claytonc07d4512011-04-26 23:48:45 +000011683 RegisterInfo data_reg;
Caroline Tice1e542e32011-03-31 18:44:04 +000011684 context.type = eContextRegisterStore;
Caroline Tice1e542e32011-03-31 18:44:04 +000011685 // for r = 0 to regs-1
11686 for (int r = 0; r < regs; ++r)
11687 {
Greg Claytonc07d4512011-04-26 23:48:45 +000011688 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011689 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11690 if (!success)
11691 return false;
11692
11693 // for e = 0 to elements-1
11694 for (int e = 0; e < elements; ++e)
11695 {
11696 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011697 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011698
11699 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11700 if (!MemUWrite (context, address, word, ebytes))
11701 return false;
11702
11703 // address = address + ebytes;
11704 address = address + ebytes;
11705 }
11706 }
11707 }
11708 return true;
11709}
11710
Caroline Tice7b880942011-03-31 19:17:12 +000011711// A8.6.392 VST1 (single element from one lane)
11712// This instruction stores one element to memory from one element of a register.
11713bool
11714EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11715{
11716#if 0
11717 if ConditionPassed() then
11718 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11719 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11720 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11721 MemU[address,ebytes] = Elem[D[d],index,esize];
11722#endif
11723
11724 bool success = false;
11725
11726 if (ConditionPassed (opcode))
11727 {
11728 uint32_t ebytes;
11729 uint32_t esize;
11730 uint32_t index;
11731 uint32_t alignment;
11732 uint32_t d;
11733 uint32_t n;
11734 uint32_t m;
11735 bool wback;
11736 bool register_index;
11737
11738 switch (encoding)
11739 {
11740 case eEncodingT1:
11741 case eEncodingA1:
11742 {
11743 uint32_t size = Bits32 (opcode, 11, 10);
11744 uint32_t index_align = Bits32 (opcode, 7, 4);
11745
Greg Clayton061b79d2011-05-09 20:18:18 +000011746 // if size == Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011747 if (size == 3)
11748 return false;
11749
11750 // case size of
Greg Clayton061b79d2011-05-09 20:18:18 +000011751 if (size == 0) // when Ô00Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011752 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011753 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011754 if (BitIsClear (index_align, 0))
11755 return false;
11756 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11757 ebytes = 1;
11758 esize = 8;
11759 index = Bits32 (index_align, 3, 1);
11760 alignment = 1;
11761 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011762 else if (size == 1) // when Ô01Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011763 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011764 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011765 if (BitIsClear (index_align, 1))
11766 return false;
11767
11768 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11769 ebytes = 2;
11770 esize = 16;
11771 index = Bits32 (index_align, 3, 2);
11772
Greg Clayton061b79d2011-05-09 20:18:18 +000011773 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Tice7b880942011-03-31 19:17:12 +000011774 if (BitIsClear (index_align, 0))
11775 alignment = 1;
11776 else
11777 alignment = 2;
11778 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011779 else if (size == 2) // when Ô10Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011780 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011781 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011782 if (BitIsClear (index_align, 2))
11783 return false;
11784
Greg Clayton061b79d2011-05-09 20:18:18 +000011785 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011786 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11787 return false;
11788
11789 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11790 ebytes = 4;
11791 esize = 32;
11792 index = Bit32 (index_align, 3);
11793
Greg Clayton061b79d2011-05-09 20:18:18 +000011794 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Tice7b880942011-03-31 19:17:12 +000011795 if (Bits32 (index_align, 1, 0) == 0)
11796 alignment = 1;
11797 else
11798 alignment = 4;
11799 }
11800 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11801 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11802 n = Bits32 (opcode, 19, 16);
11803 m = Bits32 (opcode, 3, 0);
11804
11805 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11806 wback = (m != 15);
11807 register_index = ((m != 15) && (m != 13));
11808
11809 if (n == 15)
11810 return false;
11811 }
11812 break;
11813
11814 default:
11815 return false;
11816 }
11817
Greg Claytonc07d4512011-04-26 23:48:45 +000011818 RegisterInfo base_reg;
11819 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011820
11821 uint32_t Rn = ReadCoreReg (n, &success);
11822 if (!success)
11823 return false;
11824
11825 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11826 addr_t address = Rn;
11827 if ((address % alignment) != 0)
11828 return false;
11829
11830 EmulateInstruction::Context context;
11831 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11832 if (wback)
11833 {
11834 uint32_t Rm = ReadCoreReg (m, &success);
11835 if (!success)
11836 return false;
11837
11838 uint32_t offset;
11839 if (register_index)
11840 offset = Rm;
11841 else
11842 offset = ebytes;
11843
11844 context.type = eContextAdjustBaseRegister;
11845 context.SetRegisterPlusOffset (base_reg, offset);
11846
11847 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11848 return false;
11849 }
11850
11851 // MemU[address,ebytes] = Elem[D[d],index,esize];
11852 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11853 if (!success)
11854 return false;
11855
11856 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11857
Greg Claytonc07d4512011-04-26 23:48:45 +000011858 RegisterInfo data_reg;
11859 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011860 context.type = eContextRegisterStore;
11861 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11862
11863 if (!MemUWrite (context, address, word, ebytes))
11864 return false;
11865 }
11866 return true;
11867}
11868
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011869// A8.6.309 VLD1 (single element to all lanes)
11870// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011871bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011872EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011873{
11874#if 0
11875 if ConditionPassed() then
11876 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11877 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11878 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11879 replicated_element = Replicate(MemU[address,ebytes], elements);
11880 for r = 0 to regs-1
11881 D[d+r] = replicated_element;
11882#endif
11883
11884 bool success = false;
11885
11886 if (ConditionPassed (opcode))
11887 {
11888 uint32_t ebytes;
11889 uint32_t elements;
11890 uint32_t regs;
11891 uint32_t alignment;
11892 uint32_t d;
11893 uint32_t n;
11894 uint32_t m;
11895 bool wback;
11896 bool register_index;
11897
11898 switch (encoding)
11899 {
11900 case eEncodingT1:
11901 case eEncodingA1:
11902 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011903 //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
Caroline Tice93767b82011-03-31 21:15:29 +000011904 uint32_t size = Bits32 (opcode, 7, 6);
11905 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11906 return false;
11907
Greg Clayton061b79d2011-05-09 20:18:18 +000011908 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
Caroline Tice93767b82011-03-31 21:15:29 +000011909 ebytes = 1 << size;
11910 elements = 8 / ebytes;
11911 if (BitIsClear (opcode, 5))
11912 regs = 1;
11913 else
11914 regs = 2;
11915
Greg Clayton061b79d2011-05-09 20:18:18 +000011916 //alignment = if a == Ô0Õ then 1 else ebytes;
Caroline Tice93767b82011-03-31 21:15:29 +000011917 if (BitIsClear (opcode, 4))
11918 alignment = 1;
11919 else
11920 alignment = ebytes;
11921
11922 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11923 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11924 n = Bits32 (opcode, 19, 16);
11925 m = Bits32 (opcode, 3, 0);
11926
11927 //wback = (m != 15); register_index = (m != 15 && m != 13);
11928 wback = (m != 15);
11929 register_index = ((m != 15) && (m != 13));
11930
11931 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11932 if ((d + regs) > 32)
11933 return false;
11934
11935 if (n == 15)
11936 return false;
11937 }
11938 break;
11939
11940 default:
11941 break;
11942 }
11943
Greg Claytonc07d4512011-04-26 23:48:45 +000011944 RegisterInfo base_reg;
11945 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice93767b82011-03-31 21:15:29 +000011946
11947 uint32_t Rn = ReadCoreReg (n, &success);
11948 if (!success)
11949 return false;
11950
11951 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11952 addr_t address = Rn;
11953 if ((address % alignment) != 0)
11954 return false;
11955
11956 EmulateInstruction::Context context;
11957 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11958 if (wback)
11959 {
11960 uint32_t Rm = ReadCoreReg (m, &success);
11961 if (!success)
11962 return false;
11963
11964 uint32_t offset;
11965 if (register_index)
11966 offset = Rm;
11967 else
11968 offset = ebytes;
11969
11970 context.type = eContextAdjustBaseRegister;
11971 context.SetRegisterPlusOffset (base_reg, offset);
11972
11973 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11974 return false;
11975 }
11976
11977 // replicated_element = Replicate(MemU[address,ebytes], elements);
11978
11979 context.type = eContextRegisterLoad;
11980 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11981 if (!success)
11982 return false;
11983
11984 uint64_t replicated_element;
11985 uint32_t esize = ebytes * 8;
11986 for (int e = 0; e < elements; ++e)
11987 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11988
11989 // for r = 0 to regs-1
11990 for (int r = 0; r < regs; ++r)
11991 {
11992 // D[d+r] = replicated_element;
11993 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11994 return false;
11995 }
11996 }
11997 return true;
11998}
11999
Caroline Tice1f954f52011-04-11 15:51:10 +000012000// B6.2.13 SUBS PC, LR and related instructions
12001//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
12002// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
12003bool
12004EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
12005{
12006#if 0
12007 if ConditionPassed() then
12008 EncodingSpecificOperations();
12009 if CurrentInstrSet() == InstrSet_ThumbEE then
12010 UNPREDICTABLE;
12011 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12012 case opcode of
Greg Clayton061b79d2011-05-09 20:18:18 +000012013 when Ô0000Õ result = R[n] AND operand2; // AND
12014 when Ô0001Õ result = R[n] EOR operand2; // EOR
12015 when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
12016 when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
12017 when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
12018 when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12019 when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12020 when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12021 when Ô1100Õ result = R[n] OR operand2; // ORR
12022 when Ô1101Õ result = operand2; // MOV
12023 when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
12024 when Ô1111Õ result = NOT(operand2); // MVN
12025 CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012026 BranchWritePC(result);
12027#endif
12028
12029 bool success = false;
12030
12031 if (ConditionPassed (opcode))
12032 {
12033 uint32_t n;
12034 uint32_t m;
12035 uint32_t imm32;
12036 bool register_form;
12037 ARM_ShifterType shift_t;
12038 uint32_t shift_n;
12039 uint32_t code;
12040
12041 switch (encoding)
12042 {
12043 case eEncodingT1:
12044 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
Greg Clayton061b79d2011-05-09 20:18:18 +000012045 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012046 n = 14;
12047 imm32 = Bits32 (opcode, 7, 0);
12048 register_form = false;
12049 code = 2;
12050
12051 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12052 if (InITBlock() && !LastInITBlock())
12053 return false;
12054
12055 break;
12056
12057 case eEncodingA1:
12058 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12059 n = Bits32 (opcode, 19, 16);
12060 imm32 = ARMExpandImm (opcode);
12061 register_form = false;
12062 code = Bits32 (opcode, 24, 21);
12063
12064 break;
12065
12066 case eEncodingA2:
12067 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12068 n = Bits32 (opcode, 19, 16);
12069 m = Bits32 (opcode, 3, 0);
12070 register_form = true;
12071
12072 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12073 shift_n = DecodeImmShiftARM (opcode, shift_t);
12074
12075 break;
12076
12077 default:
12078 return false;
12079 }
12080
12081 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12082 uint32_t operand2;
12083 if (register_form)
12084 {
12085 uint32_t Rm = ReadCoreReg (m, &success);
12086 if (!success)
12087 return false;
12088
Johnny Chena4438a72011-06-02 22:50:51 +000012089 operand2 = Shift (Rm, shift_t, shift_n, APSR_C, &success);
12090 if (!success)
12091 return false;
Caroline Tice1f954f52011-04-11 15:51:10 +000012092 }
12093 else
12094 {
12095 operand2 = imm32;
12096 }
12097
12098 uint32_t Rn = ReadCoreReg (n, &success);
12099 if (!success)
12100 return false;
12101
12102 AddWithCarryResult result;
12103
12104 // case opcode of
12105 switch (code)
12106 {
Greg Clayton061b79d2011-05-09 20:18:18 +000012107 case 0: // when Ô0000Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012108 // result = R[n] AND operand2; // AND
12109 result.result = Rn & operand2;
12110 break;
12111
Greg Clayton061b79d2011-05-09 20:18:18 +000012112 case 1: // when Ô0001Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012113 // result = R[n] EOR operand2; // EOR
12114 result.result = Rn ^ operand2;
12115 break;
12116
Greg Clayton061b79d2011-05-09 20:18:18 +000012117 case 2: // when Ô0010Õ
12118 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012119 result = AddWithCarry (Rn, ~(operand2), 1);
12120 break;
12121
Greg Clayton061b79d2011-05-09 20:18:18 +000012122 case 3: // when Ô0011Õ
12123 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
Caroline Tice1f954f52011-04-11 15:51:10 +000012124 result = AddWithCarry (~(Rn), operand2, 1);
12125 break;
12126
Greg Clayton061b79d2011-05-09 20:18:18 +000012127 case 4: // when Ô0100Õ
12128 // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
Caroline Tice1f954f52011-04-11 15:51:10 +000012129 result = AddWithCarry (Rn, operand2, 0);
12130 break;
12131
Greg Clayton061b79d2011-05-09 20:18:18 +000012132 case 5: // when Ô0101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012133 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12134 result = AddWithCarry (Rn, operand2, APSR_C);
12135 break;
12136
Greg Clayton061b79d2011-05-09 20:18:18 +000012137 case 6: // when Ô0110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012138 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12139 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12140 break;
12141
Greg Clayton061b79d2011-05-09 20:18:18 +000012142 case 7: // when Ô0111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012143 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12144 result = AddWithCarry (~(Rn), operand2, APSR_C);
12145 break;
12146
Greg Clayton061b79d2011-05-09 20:18:18 +000012147 case 10: // when Ô1100Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012148 // result = R[n] OR operand2; // ORR
12149 result.result = Rn | operand2;
12150 break;
12151
Greg Clayton061b79d2011-05-09 20:18:18 +000012152 case 11: // when Ô1101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012153 // result = operand2; // MOV
12154 result.result = operand2;
12155 break;
12156
Greg Clayton061b79d2011-05-09 20:18:18 +000012157 case 12: // when Ô1110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012158 // result = R[n] AND NOT(operand2); // BIC
12159 result.result = Rn & ~(operand2);
12160 break;
12161
Greg Clayton061b79d2011-05-09 20:18:18 +000012162 case 15: // when Ô1111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012163 // result = NOT(operand2); // MVN
12164 result.result = ~(operand2);
12165 break;
12166
12167 default:
12168 return false;
12169 }
Greg Clayton061b79d2011-05-09 20:18:18 +000012170 // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012171
12172 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12173 // the best.
12174 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12175 if (!success)
12176 return false;
12177
12178 CPSRWriteByInstr (spsr, 15, true);
12179
12180 // BranchWritePC(result);
12181 EmulateInstruction::Context context;
12182 context.type = eContextAdjustPC;
12183 context.SetImmediate (result.result);
12184
12185 BranchWritePC (context, result.result);
12186 }
12187 return true;
12188}
12189
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012190EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012191EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012192{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012193 static ARMOpcode
12194 g_arm_opcodes[] =
12195 {
12196 //----------------------------------------------------------------------
12197 // Prologue instructions
12198 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012199
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012200 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012201 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12202 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012203
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012204 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012205 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12206 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012207 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012208 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12209 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12210 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012211
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012212 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012213 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12214 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012215
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012216 // push one register
12217 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012218 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012219
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012220 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012221 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12222 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012223
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012224 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012225 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012226 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012227
Caroline Tice4f605582011-03-31 00:02:51 +000012228 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12229 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12230 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12231 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012232
12233 //----------------------------------------------------------------------
12234 // Supervisor Call (previously Software Interrupt)
12235 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012236 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012237
12238 //----------------------------------------------------------------------
12239 // Branch instructions
12240 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012241 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012242 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012243 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12244 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12245 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012246 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012247 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012248 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012249 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012250
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012251 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012252 // Data-processing instructions
12253 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012254 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012255 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012256 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012257 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012258 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012259 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012260 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012261 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012262 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012263 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012264 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012265 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12266 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012267 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012268 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012269 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012270 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012271 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012272 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012273 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012274 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012275 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012276 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012277 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012278 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012279 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012280 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012281 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012282 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012283 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012284 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012285 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012286 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012287 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012288 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012289 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012290 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012291 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012292 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012293 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012294 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012295 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012296 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012297 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012298 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012299 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012300 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012301 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012302 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012303 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012304 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012305 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012306 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012307 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012308 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012309
Caroline Tice89c6d582011-03-29 19:53:44 +000012310 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012311 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12312 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012313 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012314 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012315 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012316 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012317 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012318 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012319 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012320 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012321 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012322 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012323 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012324 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012325 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012326 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012327 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012328 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012329 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012330 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012331 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012332 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012333 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012334 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012335 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012336 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012337 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012338 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012339 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012340 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012341 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012342 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012343 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012344 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012345 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012346 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012347
12348 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012349 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12350 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012351
12352 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012353 // Load instructions
12354 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012355 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12356 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12357 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12358 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12359 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12360 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12361 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12362 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12363 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12364 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12365 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12366 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12367 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12368 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12369 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12370 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12371 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12372 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012373 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12374 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12375 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12376 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012377 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12378 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012379 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012380
12381 //----------------------------------------------------------------------
12382 // Store instructions
12383 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012384 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12385 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12386 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12387 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12388 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12389 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12390 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12391 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12392 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012393 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012394 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012395 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12396 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12397 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12398 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12399 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012400 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012401
Caroline Tice6bf65162011-03-03 17:42:58 +000012402 //----------------------------------------------------------------------
12403 // Other instructions
12404 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012405 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12406 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12407 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12408 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12409 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012410
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012411 };
12412 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12413
12414 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12415 {
Greg Clayton888a7332011-04-26 04:39:08 +000012416 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12417 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012418 return &g_arm_opcodes[i];
12419 }
12420 return NULL;
12421}
Greg Clayton64c84432011-01-21 22:02:52 +000012422
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012423
12424EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012425EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012426{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012427
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012428 static ARMOpcode
12429 g_thumb_opcodes[] =
12430 {
12431 //----------------------------------------------------------------------
12432 // Prologue instructions
12433 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012434
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012435 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012436 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12437 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12438 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012439
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012440 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012441 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012442 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012443 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012444 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012445 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012446
Johnny Chen864a8e82011-02-18 00:07:39 +000012447 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012448 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012449
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012450 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012451 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12452 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12453 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12454 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12455 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012456
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012457 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012458 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12459 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012460
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012461 //----------------------------------------------------------------------
12462 // Epilogue instructions
12463 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012464
Caroline Tice4f605582011-03-31 00:02:51 +000012465 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12466 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12467 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12468 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12469 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12470 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12471 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012472
12473 //----------------------------------------------------------------------
12474 // Supervisor Call (previously Software Interrupt)
12475 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012476 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012477
12478 //----------------------------------------------------------------------
12479 // If Then makes up to four following instructions conditional.
12480 //----------------------------------------------------------------------
Greg Clayton04d397c2011-05-23 18:04:09 +000012481 // The next 5 opcode _must_ come before the if then instruction
12482 { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"},
12483 { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
12484 { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
12485 { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
12486 { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
12487 { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012488
12489 //----------------------------------------------------------------------
12490 // Branch instructions
12491 //----------------------------------------------------------------------
12492 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012493 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12494 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12495 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12496 { 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 +000012497 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012498 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012499 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012500 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12501 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012502 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012503 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012504 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012505 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012506 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012507 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012508 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012509 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012510 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012511 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012512
12513 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012514 // Data-processing instructions
12515 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012516 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012517 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012518 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012519 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12520 { 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 +000012521 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012522 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012523 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012524 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012525 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012526 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12527 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12528 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012529 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012530 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012531 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012532 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12533 { 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 +000012534 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012535 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012536 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012537 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12538 { 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 +000012539 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012540 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012541 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012542 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12543 { 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 +000012544 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012545 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012546 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012547 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12548 { 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 +000012549 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012550 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12551 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012552 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012553 { 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 +000012554 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012555 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012556 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012557 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12558 { 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 +000012559 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012560 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12561 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12562 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12563 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012564 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012565 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12566 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12567 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12568 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012569 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012570 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12571 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012572 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012573 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12574 { 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 +000012575 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012576 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012577 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012578 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012579 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012580 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012581 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012582 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12583 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012584
Johnny Chen7c5234d2011-02-18 23:41:11 +000012585
Johnny Chen338bf542011-02-10 19:29:03 +000012586 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012587 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012588 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012589 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012590 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012591 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012592 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012593 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12594 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12595 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012596 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012597 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012598 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012599 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12600 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012601 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012602 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012603 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012604 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12605 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012606 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012607 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12608 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012609 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012610 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012611 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012612 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012613 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012614 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12615 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012616 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012617 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12618 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012619 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012620 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12621 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012622 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012623 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12624 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012625 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012626 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12627 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012628 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012629 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12630 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012631 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012632 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012633 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012634 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012635 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012636 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12637 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012638 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012639 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012640 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012641 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012642
12643 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012644 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012645
12646 //----------------------------------------------------------------------
12647 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12648 // otherwise the wrong instructions will be selected.
12649 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012650
Caroline Tice080bf612011-04-05 18:46:00 +000012651 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12652 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12653
Johnny Chen26863dc2011-02-09 23:43:29 +000012654 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012655 // Load instructions
12656 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012657 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12658 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12659 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12660 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12661 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12662 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12663 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012664 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012665 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12666 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12667 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12668 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12669 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012670 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012671 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12672 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12673 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12674 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12675 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12676 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12677 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12678 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12679 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12680 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12681 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12682 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12683 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12684 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12685 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12686 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12687 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12688 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12689 { 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 +000012690 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012691 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12692 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12693 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12694 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012695 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12696 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012697 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012698
12699 //----------------------------------------------------------------------
12700 // Store instructions
12701 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012702 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12703 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12704 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12705 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12706 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12707 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12708 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12709 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12710 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12711 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12712 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12713 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12714 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12715 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12716 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12717 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012718 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12719 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12720 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12721 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12722 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012723 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012724
12725 //----------------------------------------------------------------------
12726 // Other instructions
12727 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012728 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12729 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12730 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12731 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12732 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12733 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12734 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12735 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012736 };
12737
12738 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12739 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12740 {
Greg Clayton888a7332011-04-26 04:39:08 +000012741 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12742 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012743 return &g_thumb_opcodes[i];
12744 }
12745 return NULL;
12746}
Greg Clayton64c84432011-01-21 22:02:52 +000012747
Greg Clayton31e2a382011-01-30 20:03:56 +000012748bool
Greg Clayton395fc332011-02-15 21:59:32 +000012749EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012750{
Caroline Tice080bf612011-04-05 18:46:00 +000012751 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012752 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012753 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012754 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012755 {
Greg Clayton395fc332011-02-15 21:59:32 +000012756 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12757 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12758 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12759 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12760 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12761 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12762 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12763 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12764 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12765 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Johnny Chen1d29a852011-04-26 18:51:57 +000012766 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12767 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
Greg Clayton31e2a382011-01-30 20:03:56 +000012768 }
12769 return m_arm_isa != 0;
12770}
12771
Caroline Tice080bf612011-04-05 18:46:00 +000012772bool
Greg Clayton888a7332011-04-26 04:39:08 +000012773EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012774{
Greg Clayton888a7332011-04-26 04:39:08 +000012775 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12776 {
12777 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12778 m_opcode_mode = eModeThumb;
12779 else
12780 {
12781 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012782
Greg Clayton888a7332011-04-26 04:39:08 +000012783 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12784 m_opcode_mode = eModeARM;
12785 else if (addr_class == eAddressClassCodeAlternateISA)
12786 m_opcode_mode = eModeThumb;
12787 else
12788 return false;
12789 }
12790 if (m_opcode_mode == eModeThumb)
12791 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12792 else
12793 m_opcode_cpsr = CPSR_MODE_USR;
12794 return true;
12795 }
12796 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012797}
Greg Clayton31e2a382011-01-30 20:03:56 +000012798
Greg Clayton64c84432011-01-21 22:02:52 +000012799bool
12800EmulateInstructionARM::ReadInstruction ()
12801{
12802 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012803 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012804 if (success)
12805 {
12806 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12807 if (success)
12808 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012809 Context read_inst_context;
12810 read_inst_context.type = eContextReadOpcode;
12811 read_inst_context.SetNoArgs ();
12812
Greg Claytonb3448432011-03-24 21:19:54 +000012813 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012814 {
Greg Claytonb3448432011-03-24 21:19:54 +000012815 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012816 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012817
12818 if (success)
12819 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012820 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012821 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012822 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012823 }
12824 else
12825 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012826 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012827 }
12828 }
12829 }
12830 else
12831 {
Greg Claytonb3448432011-03-24 21:19:54 +000012832 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012833 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012834 }
12835 }
12836 }
12837 if (!success)
12838 {
Greg Claytonb3448432011-03-24 21:19:54 +000012839 m_opcode_mode = eModeInvalid;
Greg Clayton3063c952011-04-29 22:50:31 +000012840 m_addr = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012841 }
12842 return success;
12843}
12844
Johnny Chenee9b1f72011-02-09 01:00:31 +000012845uint32_t
12846EmulateInstructionARM::ArchVersion ()
12847{
12848 return m_arm_isa;
12849}
12850
Greg Clayton64c84432011-01-21 22:02:52 +000012851bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012852EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012853{
Greg Clayton888a7332011-04-26 04:39:08 +000012854 // If we are ignoring conditions, then always return true.
12855 // this allows us to iterate over disassembly code and still
12856 // emulate an instruction even if we don't have all the right
12857 // bits set in the CPSR register...
12858 if (m_ignore_conditions)
12859 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000012860
Greg Clayton7bc39082011-03-24 23:53:38 +000012861 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012862
12863 if (cond == UINT32_MAX)
12864 return false;
12865
12866 bool result = false;
12867 switch (UnsignedBits(cond, 3, 1))
12868 {
Caroline Tice080bf612011-04-05 18:46:00 +000012869 case 0:
12870 if (m_opcode_cpsr == 0)
12871 return true;
12872 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12873 break;
12874 case 1:
12875 if (m_opcode_cpsr == 0)
12876 return true;
12877 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12878 break;
12879 case 2:
12880 if (m_opcode_cpsr == 0)
12881 return true;
12882 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12883 break;
12884 case 3:
12885 if (m_opcode_cpsr == 0)
12886 return true;
12887 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12888 break;
12889 case 4:
12890 if (m_opcode_cpsr == 0)
12891 return true;
12892 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12893 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012894 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012895 if (m_opcode_cpsr == 0)
12896 return true;
12897 else
12898 {
Greg Claytonb3448432011-03-24 21:19:54 +000012899 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12900 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012901 result = n == v;
12902 }
12903 break;
12904 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012905 if (m_opcode_cpsr == 0)
12906 return true;
12907 else
12908 {
Greg Claytonb3448432011-03-24 21:19:54 +000012909 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12910 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12911 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012912 }
12913 break;
12914 case 7:
12915 result = true;
12916 break;
12917 }
12918
12919 if (cond & 1)
12920 result = !result;
12921 return result;
12922}
12923
Johnny Chen9ee056b2011-02-08 00:06:35 +000012924uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012925EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012926{
Greg Claytonb3448432011-03-24 21:19:54 +000012927 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012928 {
12929 default:
12930 case eModeInvalid:
12931 break;
12932
12933 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012934 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012935
12936 case eModeThumb:
12937 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12938 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012939 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012940 const uint32_t byte_size = m_opcode.GetByteSize();
12941 if (byte_size == 2)
12942 {
12943 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12944 return Bits32(opcode, 11, 7);
12945 }
Johnny Chen6dc5a1a2011-06-02 23:19:06 +000012946 else if (byte_size == 4)
Greg Clayton7bc39082011-03-24 23:53:38 +000012947 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012948 if (Bits32(opcode, 31, 27) == 0x1e &&
12949 Bits32(opcode, 15, 14) == 0x02 &&
12950 Bits32(opcode, 12, 12) == 0x00 &&
12951 Bits32(opcode, 25, 22) <= 0x0d)
12952 {
12953 return Bits32(opcode, 25, 22);
12954 }
12955 }
Johnny Chen6dc5a1a2011-06-02 23:19:06 +000012956 else
12957 // We have an invalid thumb instruction, let's bail out.
12958 break;
Greg Clayton7bc39082011-03-24 23:53:38 +000012959
12960 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012961 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012962 }
12963 return UINT32_MAX; // Return invalid value
12964}
12965
Johnny Chen9ee056b2011-02-08 00:06:35 +000012966bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012967EmulateInstructionARM::InITBlock()
12968{
12969 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12970}
12971
12972bool
12973EmulateInstructionARM::LastInITBlock()
12974{
12975 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12976}
12977
Caroline Ticeb27771d2011-03-03 22:37:46 +000012978bool
12979EmulateInstructionARM::BadMode (uint32_t mode)
12980{
12981
12982 switch (mode)
12983 {
12984 case 16: return false; // '10000'
12985 case 17: return false; // '10001'
12986 case 18: return false; // '10010'
12987 case 19: return false; // '10011'
12988 case 22: return false; // '10110'
12989 case 23: return false; // '10111'
12990 case 27: return false; // '11011'
12991 case 31: return false; // '11111'
12992 default: return true;
12993 }
12994 return true;
12995}
12996
12997bool
12998EmulateInstructionARM::CurrentModeIsPrivileged ()
12999{
Greg Claytonb3448432011-03-24 21:19:54 +000013000 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000013001
13002 if (BadMode (mode))
13003 return false;
13004
13005 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000013006 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000013007
13008 return true;
13009}
13010
13011void
13012EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
13013{
13014 bool privileged = CurrentModeIsPrivileged();
13015
13016 uint32_t tmp_cpsr = 0;
13017
Greg Claytonb3448432011-03-24 21:19:54 +000013018 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000013019
13020 if (BitIsSet (bytemask, 3))
13021 {
13022 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
13023 if (affect_execstate)
13024 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
13025 }
13026
13027 if (BitIsSet (bytemask, 2))
13028 {
13029 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
13030 }
13031
13032 if (BitIsSet (bytemask, 1))
13033 {
13034 if (affect_execstate)
13035 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
13036 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
13037 if (privileged)
13038 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
13039 }
13040
13041 if (BitIsSet (bytemask, 0))
13042 {
13043 if (privileged)
13044 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
13045 if (affect_execstate)
13046 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
13047 if (privileged)
13048 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
13049 }
13050
Greg Claytonb3448432011-03-24 21:19:54 +000013051 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000013052}
13053
13054
Johnny Chen098ae2d2011-02-12 00:50:05 +000013055bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000013056EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
13057{
13058 addr_t target;
13059
Johnny Chenee9b1f72011-02-09 01:00:31 +000013060 // Check the current instruction set.
13061 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013062 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013063 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000013064 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013065
Johnny Chen9ee056b2011-02-08 00:06:35 +000013066 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013067 return false;
13068
13069 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013070}
13071
13072// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
13073bool
Johnny Chen668b4512011-02-15 21:08:58 +000013074EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013075{
13076 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000013077 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
13078 // we want to record it and issue a WriteRegister callback so the clients
13079 // can track the mode changes accordingly.
13080 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013081
13082 if (BitIsSet(addr, 0))
13083 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013084 if (CurrentInstrSet() != eModeThumb)
13085 {
13086 SelectInstrSet(eModeThumb);
13087 cpsr_changed = true;
13088 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013089 target = addr & 0xfffffffe;
Greg Claytonc07d4512011-04-26 23:48:45 +000013090 context.SetISA (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013091 }
13092 else if (BitIsClear(addr, 1))
13093 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013094 if (CurrentInstrSet() != eModeARM)
13095 {
13096 SelectInstrSet(eModeARM);
13097 cpsr_changed = true;
13098 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013099 target = addr & 0xfffffffc;
Greg Claytonc07d4512011-04-26 23:48:45 +000013100 context.SetISA (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013101 }
13102 else
13103 return false; // address<1:0> == '10' => UNPREDICTABLE
13104
Johnny Chen0f309db2011-02-09 19:11:32 +000013105 if (cpsr_changed)
13106 {
Johnny Chen558133b2011-02-09 23:59:17 +000013107 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000013108 return false;
13109 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013110 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013111 return false;
13112
13113 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013114}
Greg Clayton64c84432011-01-21 22:02:52 +000013115
Johnny Chenee9b1f72011-02-09 01:00:31 +000013116// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13117bool
Johnny Chen668b4512011-02-15 21:08:58 +000013118EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000013119{
13120 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000013121 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000013122 else
13123 return BranchWritePC((const Context)context, addr);
13124}
13125
Johnny Chen26863dc2011-02-09 23:43:29 +000013126// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13127bool
Johnny Chen668b4512011-02-15 21:08:58 +000013128EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000013129{
13130 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013131 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013132 else
13133 return BranchWritePC((const Context)context, addr);
13134}
13135
Johnny Chenee9b1f72011-02-09 01:00:31 +000013136EmulateInstructionARM::Mode
13137EmulateInstructionARM::CurrentInstrSet ()
13138{
Greg Claytonb3448432011-03-24 21:19:54 +000013139 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013140}
13141
Greg Claytonb3448432011-03-24 21:19:54 +000013142// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013143// ReadInstruction() is performed. This function has a side effect of updating
13144// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013145bool
13146EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13147{
Greg Claytonb3448432011-03-24 21:19:54 +000013148 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013149 switch (arm_or_thumb)
13150 {
13151 default:
13152 return false;
13153 eModeARM:
13154 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013155 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013156 break;
13157 eModeThumb:
13158 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013159 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013160 break;
13161 }
13162 return true;
13163}
13164
Johnny Chenef21b592011-02-10 01:52:38 +000013165// This function returns TRUE if the processor currently provides support for
13166// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13167// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13168bool
13169EmulateInstructionARM::UnalignedSupport()
13170{
13171 return (ArchVersion() >= ARMv7);
13172}
13173
Johnny Chenbf6ad172011-02-11 01:29:53 +000013174// The main addition and subtraction instructions can produce status information
13175// about both unsigned carry and signed overflow conditions. This status
13176// information can be used to synthesize multi-word additions and subtractions.
13177EmulateInstructionARM::AddWithCarryResult
13178EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13179{
13180 uint32_t result;
13181 uint8_t carry_out;
13182 uint8_t overflow;
13183
13184 uint64_t unsigned_sum = x + y + carry_in;
13185 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13186
13187 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013188// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013189 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013190
13191 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013192 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013193 else
13194 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013195
13196 AddWithCarryResult res = { result, carry_out, overflow };
13197 return res;
13198}
13199
Johnny Chen157b9592011-02-18 21:13:05 +000013200uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013201EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013202{
Johnny Chene39f22d2011-02-19 01:36:13 +000013203 uint32_t reg_kind, reg_num;
13204 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013205 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013206 case SP_REG:
13207 reg_kind = eRegisterKindGeneric;
13208 reg_num = LLDB_REGNUM_GENERIC_SP;
13209 break;
13210 case LR_REG:
13211 reg_kind = eRegisterKindGeneric;
13212 reg_num = LLDB_REGNUM_GENERIC_RA;
13213 break;
13214 case PC_REG:
13215 reg_kind = eRegisterKindGeneric;
13216 reg_num = LLDB_REGNUM_GENERIC_PC;
13217 break;
13218 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013219 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013220 {
13221 reg_kind = eRegisterKindDWARF;
13222 reg_num = dwarf_r0 + num;
13223 }
Johnny Chen157b9592011-02-18 21:13:05 +000013224 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013225 {
Greg Claytone1f47bb2011-06-02 22:23:35 +000013226 //assert(0 && "Invalid register number");
Johnny Chene39f22d2011-02-19 01:36:13 +000013227 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013228 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013229 }
13230 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013231 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013232
13233 // Read our register.
13234 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13235
13236 // When executing an ARM instruction , PC reads as the address of the current
13237 // instruction plus 8.
13238 // When executing a Thumb instruction , PC reads as the address of the current
13239 // instruction plus 4.
13240 if (num == 15)
13241 {
13242 if (CurrentInstrSet() == eModeARM)
13243 val += 8;
13244 else
13245 val += 4;
13246 }
Johnny Chen157b9592011-02-18 21:13:05 +000013247
13248 return val;
13249}
13250
Johnny Chenca67d1c2011-02-17 01:35:27 +000013251// Write the result to the ARM core register Rd, and optionally update the
13252// condition flags based on the result.
13253//
13254// This helper method tries to encapsulate the following pseudocode from the
13255// ARM Architecture Reference Manual:
13256//
13257// if d == 15 then // Can only occur for encoding A1
13258// ALUWritePC(result); // setflags is always FALSE here
13259// else
13260// R[d] = result;
13261// if setflags then
13262// APSR.N = result<31>;
13263// APSR.Z = IsZeroBit(result);
13264// APSR.C = carry;
13265// // APSR.V unchanged
13266//
13267// In the above case, the API client does not pass in the overflow arg, which
13268// defaults to ~0u.
13269bool
Johnny Chen10530c22011-02-17 22:37:12 +000013270EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13271 const uint32_t result,
13272 const uint32_t Rd,
13273 bool setflags,
13274 const uint32_t carry,
13275 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013276{
13277 if (Rd == 15)
13278 {
13279 if (!ALUWritePC (context, result))
13280 return false;
13281 }
13282 else
13283 {
Johnny Chena695f952011-02-23 21:24:25 +000013284 uint32_t reg_kind, reg_num;
13285 switch (Rd)
13286 {
13287 case SP_REG:
13288 reg_kind = eRegisterKindGeneric;
13289 reg_num = LLDB_REGNUM_GENERIC_SP;
13290 break;
13291 case LR_REG:
13292 reg_kind = eRegisterKindGeneric;
13293 reg_num = LLDB_REGNUM_GENERIC_RA;
13294 break;
13295 default:
13296 reg_kind = eRegisterKindDWARF;
13297 reg_num = dwarf_r0 + Rd;
13298 }
13299 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013300 return false;
13301 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013302 return WriteFlags (context, result, carry, overflow);
13303 }
13304 return true;
13305}
13306
13307// This helper method tries to encapsulate the following pseudocode from the
13308// ARM Architecture Reference Manual:
13309//
13310// APSR.N = result<31>;
13311// APSR.Z = IsZeroBit(result);
13312// APSR.C = carry;
13313// APSR.V = overflow
13314//
13315// Default arguments can be specified for carry and overflow parameters, which means
13316// not to update the respective flags.
13317bool
13318EmulateInstructionARM::WriteFlags (Context &context,
13319 const uint32_t result,
13320 const uint32_t carry,
13321 const uint32_t overflow)
13322{
Greg Claytonb3448432011-03-24 21:19:54 +000013323 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013324 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13325 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013326 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013327 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013328 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013329 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013330 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013331 {
13332 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13333 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013334 }
13335 return true;
13336}
13337
Greg Clayton64c84432011-01-21 22:02:52 +000013338bool
Greg Clayton888a7332011-04-26 04:39:08 +000013339EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013340{
Johnny Chenc315f862011-02-05 00:46:10 +000013341 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013342 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013343 m_it_session.ITAdvance();
13344
Greg Clayton888a7332011-04-26 04:39:08 +000013345 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013346
13347 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013348 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013349 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013350 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13351
13352 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013353 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013354
Greg Clayton888a7332011-04-26 04:39:08 +000013355 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13356 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013357
Greg Clayton888a7332011-04-26 04:39:08 +000013358 bool success = false;
13359 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013360 {
Greg Clayton888a7332011-04-26 04:39:08 +000013361 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
Greg Clayton061b79d2011-05-09 20:18:18 +000013362 dwarf_cpsr,
13363 0,
13364 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013365 }
13366
Greg Clayton888a7332011-04-26 04:39:08 +000013367 // Only return false if we are unable to read the CPSR if we care about conditions
13368 if (success == false && m_ignore_conditions == false)
13369 return false;
13370
13371 uint32_t orig_pc_value = 0;
13372 if (auto_advance_pc)
13373 {
13374 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13375 if (!success)
13376 return false;
13377 }
13378
13379 // Call the Emulate... function.
13380 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13381 if (!success)
13382 return false;
13383
13384 if (auto_advance_pc)
13385 {
13386 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13387 if (!success)
13388 return false;
13389
13390 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13391 {
13392 if (opcode_data->size == eSize32)
13393 after_pc_value += 4;
13394 else if (opcode_data->size == eSize16)
13395 after_pc_value += 2;
13396
13397 EmulateInstruction::Context context;
13398 context.type = eContextAdvancePC;
13399 context.SetNoArgs();
13400 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13401 return false;
13402
13403 }
13404 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013405 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013406}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013407
13408bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013409EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013410{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013411 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013412 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013413 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013414 return false;
13415 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013416
13417 static ConstString opcode_key ("opcode");
13418 static ConstString before_key ("before_state");
13419 static ConstString after_key ("after_state");
13420
13421 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013422
13423 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013424 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013425 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013426 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013427 return false;
13428 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013429 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013430
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013431 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13432 {
13433 m_opcode_mode = eModeARM;
13434 m_opcode.SetOpcode32 (test_opcode);
13435 }
13436 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13437 {
13438 m_opcode_mode = eModeThumb;
13439 if (test_opcode < 0x10000)
13440 m_opcode.SetOpcode16 (test_opcode);
13441 else
13442 m_opcode.SetOpcode32 (test_opcode);
13443
13444 }
13445 else
13446 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013447 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013448 return false;
13449 }
13450
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013451 EmulationStateARM before_state;
13452 EmulationStateARM after_state;
13453
Caroline Ticedfb2e202011-04-22 05:08:45 +000013454 value_sp = test_data->GetValueForKey (before_key);
13455 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013456 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013457 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013458 return false;
13459 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013460
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013461 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013462 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013463 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013464 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013465 return false;
13466 }
13467
Caroline Ticedfb2e202011-04-22 05:08:45 +000013468 value_sp = test_data->GetValueForKey (after_key);
13469 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013470 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013471 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013472 return false;
13473 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013474
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013475 state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013476 if (!after_state.LoadStateFromDictionary (state_dictionary))
13477 {
13478 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13479 return false;
13480 }
13481
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013482 SetBaton ((void *) &before_state);
13483 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13484 &EmulationStateARM::WritePseudoMemory,
13485 &EmulationStateARM::ReadPseudoRegister,
13486 &EmulationStateARM::WritePseudoRegister);
13487
Greg Clayton888a7332011-04-26 04:39:08 +000013488 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013489 if (!success)
13490 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013491 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013492 return false;
13493 }
13494
13495 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013496 if (!success)
13497 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13498
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013499 return success;
13500}
Greg Claytonc07d4512011-04-26 23:48:45 +000013501//
13502//
13503//const char *
13504//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13505//{
13506// if (reg_kind == eRegisterKindGeneric)
13507// {
13508// switch (reg_num)
13509// {
13510// case LLDB_REGNUM_GENERIC_PC: return "pc";
13511// case LLDB_REGNUM_GENERIC_SP: return "sp";
13512// case LLDB_REGNUM_GENERIC_FP: return "fp";
13513// case LLDB_REGNUM_GENERIC_RA: return "lr";
13514// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13515// default: return NULL;
13516// }
13517// }
13518// else if (reg_kind == eRegisterKindDWARF)
13519// {
13520// return GetARMDWARFRegisterName (reg_num);
13521// }
13522// return NULL;
13523//}
13524//
13525bool
13526EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
Greg Clayton888a7332011-04-26 04:39:08 +000013527{
Greg Clayton75906e42011-05-11 18:39:18 +000013528 unwind_plan.Clear();
Greg Claytonc07d4512011-04-26 23:48:45 +000013529 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13530
13531 UnwindPlan::Row row;
Greg Claytonc07d4512011-04-26 23:48:45 +000013532
13533 // Our previous Call Frame Address is the stack pointer
13534 row.SetCFARegister (dwarf_sp);
13535
13536 // Our previous PC is in the LR
Greg Clayton75906e42011-05-11 18:39:18 +000013537 row.SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
Greg Claytonc07d4512011-04-26 23:48:45 +000013538 unwind_plan.AppendRow (row);
13539
13540 // All other registers are the same.
13541
13542 unwind_plan.SetSourceName ("EmulateInstructionARM");
13543 return true;
Greg Clayton888a7332011-04-26 04:39:08 +000013544}
13545
Greg Claytonc07d4512011-04-26 23:48:45 +000013546
13547
13548