blob: 7bd9d5798faa2550173791c5e1a31e2c9dd4def1 [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
1124 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1125 uint32_t result = ~shifted;
1126
1127 // The context specifies that an immediate is to be moved into Rd.
1128 EmulateInstruction::Context context;
1129 context.type = EmulateInstruction::eContextImmediate;
1130 context.SetNoArgs ();
1131
1132 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1133 return false;
1134 }
1135 return true;
1136}
1137
Johnny Chen788e0552011-01-27 22:52:23 +00001138// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1139// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001140bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001141EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001142{
1143#if 0
1144 // ARM pseudo code...
1145 if (ConditionPassed())
1146 {
1147 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1148 base = Align(PC,4);
1149 address = if add then (base + imm32) else (base - imm32);
1150 data = MemU[address,4];
1151 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001152 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1153 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001154 R[t] = data;
1155 else // Can only apply before ARMv7
1156 if CurrentInstrSet() == InstrSet_ARM then
1157 R[t] = ROR(data, 8*UInt(address<1:0>));
1158 else
1159 R[t] = bits(32) UNKNOWN;
1160 }
1161#endif
1162
Greg Clayton7bc39082011-03-24 23:53:38 +00001163 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001164 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001165 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001166 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001167 if (!success)
1168 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001169
1170 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001171 EmulateInstruction::Context context;
1172 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001173 RegisterInfo pc_reg;
1174 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001175 context.SetRegisterPlusOffset (pc_reg, 0);
1176
Johnny Chenc9de9102011-02-11 19:12:30 +00001177 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001178 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001179 bool add; // +imm32 or -imm32?
1180 addr_t base; // the base address
1181 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001182 uint32_t data; // the literal data value from the PC relative load
1183 switch (encoding) {
1184 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001185 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001186 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001187 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001188 break;
1189 case eEncodingT2:
1190 Rt = Bits32(opcode, 15, 12);
1191 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1192 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001193 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001194 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001195 break;
1196 default:
1197 return false;
1198 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001199
Johnny Chene39f22d2011-02-19 01:36:13 +00001200 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001201 if (add)
1202 address = base + imm32;
1203 else
1204 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001205
1206 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001207 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001208 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001209 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001210
1211 if (Rt == 15)
1212 {
1213 if (Bits32(address, 1, 0) == 0)
1214 {
1215 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001216 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001217 return false;
1218 }
1219 else
1220 return false;
1221 }
1222 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1223 {
1224 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1225 return false;
1226 }
1227 else // We don't handle ARM for now.
1228 return false;
1229
Johnny Chen788e0552011-01-27 22:52:23 +00001230 }
1231 return true;
1232}
1233
Johnny Chen5b442b72011-01-27 19:34:30 +00001234// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001235// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001236bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001237EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001238{
1239#if 0
1240 // ARM pseudo code...
1241 if (ConditionPassed())
1242 {
1243 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001244 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001245 if d == 15 then // Can only occur for ARM encoding
1246 ALUWritePC(result); // setflags is always FALSE here
1247 else
1248 R[d] = result;
1249 if setflags then
1250 APSR.N = result<31>;
1251 APSR.Z = IsZeroBit(result);
1252 APSR.C = carry;
1253 APSR.V = overflow;
1254 }
1255#endif
1256
1257 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001258
Greg Clayton7bc39082011-03-24 23:53:38 +00001259 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001260 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001261 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001262 if (!success)
1263 return false;
1264 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001265 uint32_t d;
1266 bool setflags;
1267 switch (encoding)
1268 {
1269 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001270 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001271 d = Bits32 (opcode, 10, 8);
1272 setflags = false;
1273 imm32 = (Bits32 (opcode, 7, 0) << 2);
1274
1275 break;
1276
1277 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001278 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001279 d = 13;
1280 setflags = false;
1281 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1282
1283 break;
1284
1285 default:
1286 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001287 }
1288 addr_t sp_offset = imm32;
1289 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1290
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001291 EmulateInstruction::Context context;
1292 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +00001293 RegisterInfo sp_reg;
1294 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001295 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001296
Caroline Ticee2212882011-03-22 22:38:28 +00001297 if (d == 15)
1298 {
1299 if (!ALUWritePC (context, addr))
1300 return false;
1301 }
1302 else
1303 {
1304 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1305 return false;
1306 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001307 }
1308 return true;
1309}
1310
1311// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001312// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001313bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001314EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001315{
1316#if 0
1317 // ARM pseudo code...
1318 if (ConditionPassed())
1319 {
1320 EncodingSpecificOperations();
1321 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001322 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001323 if d == 15 then
1324 ALUWritePC(result); // setflags is always FALSE here
1325 else
1326 R[d] = result;
1327 if setflags then
1328 APSR.N = result<31>;
1329 APSR.Z = IsZeroBit(result);
1330 APSR.C = carry;
1331 APSR.V = overflow;
1332 }
1333#endif
1334
1335 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001336
Greg Clayton7bc39082011-03-24 23:53:38 +00001337 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001338 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001339 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001340 if (!success)
1341 return false;
1342 uint32_t Rm; // the second operand
1343 switch (encoding) {
1344 case eEncodingT2:
1345 Rm = Bits32(opcode, 6, 3);
1346 break;
1347 default:
1348 return false;
1349 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001350 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001351 if (!success)
1352 return false;
1353
1354 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1355
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001356 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00001357 context.type = eContextArithmetic;
1358 RegisterInfo sp_reg;
1359 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1360
1361 RegisterInfo other_reg;
1362 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001363 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001364
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001365 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001366 return false;
1367 }
1368 return true;
1369}
1370
Johnny Chen9b8d7832011-02-02 01:13:56 +00001371// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1372// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1373// from Thumb to ARM.
1374// BLX (immediate)
1375bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001376EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001377{
1378#if 0
1379 // ARM pseudo code...
1380 if (ConditionPassed())
1381 {
1382 EncodingSpecificOperations();
1383 if CurrentInstrSet() == InstrSet_ARM then
1384 LR = PC - 4;
1385 else
1386 LR = PC<31:1> : '1';
1387 if targetInstrSet == InstrSet_ARM then
1388 targetAddress = Align(PC,4) + imm32;
1389 else
1390 targetAddress = PC + imm32;
1391 SelectInstrSet(targetInstrSet);
1392 BranchWritePC(targetAddress);
1393 }
1394#endif
1395
Greg Clayton7bc39082011-03-24 23:53:38 +00001396 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001397
Greg Clayton7bc39082011-03-24 23:53:38 +00001398 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001399 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001400 EmulateInstruction::Context context;
1401 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001402 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001403 if (!success)
1404 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001405 addr_t lr; // next instruction address
1406 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001407 int32_t imm32; // PC-relative offset
1408 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001409 case eEncodingT1:
1410 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001411 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001412 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001413 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001414 uint32_t J1 = Bit32(opcode, 13);
1415 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001416 uint32_t imm11 = Bits32(opcode, 10, 0);
1417 uint32_t I1 = !(J1 ^ S);
1418 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001419 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001420 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001421 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001422 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001423 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001424 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001425 break;
1426 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001427 case eEncodingT2:
1428 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001429 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001430 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001431 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001432 uint32_t J1 = Bit32(opcode, 13);
1433 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001434 uint32_t imm10L = Bits32(opcode, 10, 1);
1435 uint32_t I1 = !(J1 ^ S);
1436 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001437 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001438 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001439 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001440 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001441 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001442 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001443 break;
1444 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001445 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001446 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001447 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001448 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001449 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001450 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001451 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001452 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001453 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001454 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001455 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001456 break;
1457 default:
1458 return false;
1459 }
1460 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1461 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001462 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001463 return false;
1464 }
1465 return true;
1466}
1467
1468// Branch with Link and Exchange (register) calls a subroutine at an address and
1469// instruction set specified by a register.
1470// BLX (register)
1471bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001472EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001473{
1474#if 0
1475 // ARM pseudo code...
1476 if (ConditionPassed())
1477 {
1478 EncodingSpecificOperations();
1479 target = R[m];
1480 if CurrentInstrSet() == InstrSet_ARM then
1481 next_instr_addr = PC - 4;
1482 LR = next_instr_addr;
1483 else
1484 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001485 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001486 BXWritePC(target);
1487 }
1488#endif
1489
1490 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001491
Greg Clayton7bc39082011-03-24 23:53:38 +00001492 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001493 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001494 EmulateInstruction::Context context;
1495 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001496 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001497 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001498 if (!success)
1499 return false;
1500 uint32_t Rm; // the register with the target address
1501 switch (encoding) {
1502 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001503 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001504 Rm = Bits32(opcode, 6, 3);
1505 // if m == 15 then UNPREDICTABLE;
1506 if (Rm == 15)
1507 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001508 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001509 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001510 break;
1511 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001512 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001513 Rm = Bits32(opcode, 3, 0);
1514 // if m == 15 then UNPREDICTABLE;
1515 if (Rm == 15)
1516 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001517 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001518 default:
1519 return false;
1520 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001521 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001522 if (!success)
1523 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001524 RegisterInfo dwarf_reg;
1525 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001526 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001527 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1528 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001529 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001530 return false;
1531 }
1532 return true;
1533}
1534
Johnny Chenab3b3512011-02-12 00:10:51 +00001535// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001536bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001537EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001538{
1539#if 0
1540 // ARM pseudo code...
1541 if (ConditionPassed())
1542 {
1543 EncodingSpecificOperations();
1544 BXWritePC(R[m]);
1545 }
1546#endif
1547
Greg Clayton7bc39082011-03-24 23:53:38 +00001548 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001549 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001550 EmulateInstruction::Context context;
1551 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001552 uint32_t Rm; // the register with the target address
1553 switch (encoding) {
1554 case eEncodingT1:
1555 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001556 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001557 return false;
1558 break;
1559 case eEncodingA1:
1560 Rm = Bits32(opcode, 3, 0);
1561 break;
1562 default:
1563 return false;
1564 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001565 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001566 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001567 if (!success)
1568 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001569
1570 RegisterInfo dwarf_reg;
1571 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen668b4512011-02-15 21:08:58 +00001572 context.SetRegister (dwarf_reg);
1573 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001574 return false;
1575 }
1576 return true;
1577}
1578
Johnny Chen59e6ab72011-02-24 21:01:20 +00001579// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1580// address and instruction set specified by a register as though it were a BX instruction.
1581//
1582// TODO: Emulate Jazelle architecture?
1583// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1584bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001585EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001586{
1587#if 0
1588 // ARM pseudo code...
1589 if (ConditionPassed())
1590 {
1591 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001592 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001593 BXWritePC(R[m]);
1594 else
1595 if JazelleAcceptsExecution() then
1596 SwitchToJazelleExecution();
1597 else
1598 SUBARCHITECTURE_DEFINED handler call;
1599 }
1600#endif
1601
Greg Clayton7bc39082011-03-24 23:53:38 +00001602 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001603 {
1604 EmulateInstruction::Context context;
1605 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1606 uint32_t Rm; // the register with the target address
1607 switch (encoding) {
1608 case eEncodingT1:
1609 Rm = Bits32(opcode, 19, 16);
1610 if (BadReg(Rm))
1611 return false;
1612 if (InITBlock() && !LastInITBlock())
1613 return false;
1614 break;
1615 case eEncodingA1:
1616 Rm = Bits32(opcode, 3, 0);
1617 if (Rm == 15)
1618 return false;
1619 break;
1620 default:
1621 return false;
1622 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001623 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001624 addr_t target = ReadCoreReg (Rm, &success);
1625 if (!success)
1626 return false;
1627
Greg Claytonc07d4512011-04-26 23:48:45 +00001628 RegisterInfo dwarf_reg;
1629 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen59e6ab72011-02-24 21:01:20 +00001630 context.SetRegister (dwarf_reg);
1631 if (!BXWritePC(context, target))
1632 return false;
1633 }
1634 return true;
1635}
1636
Johnny Chen0d0148e2011-01-28 02:26:08 +00001637// Set r7 to point to some ip offset.
1638// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001639bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001640EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001641{
1642#if 0
1643 // ARM pseudo code...
1644 if (ConditionPassed())
1645 {
1646 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001647 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001648 if d == 15 then // Can only occur for ARM encoding
1649 ALUWritePC(result); // setflags is always FALSE here
1650 else
1651 R[d] = result;
1652 if setflags then
1653 APSR.N = result<31>;
1654 APSR.Z = IsZeroBit(result);
1655 APSR.C = carry;
1656 APSR.V = overflow;
1657 }
1658#endif
1659
Greg Clayton7bc39082011-03-24 23:53:38 +00001660 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001661 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001662 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001663 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001664 if (!success)
1665 return false;
1666 uint32_t imm32;
1667 switch (encoding) {
1668 case eEncodingA1:
1669 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1670 break;
1671 default:
1672 return false;
1673 }
1674 addr_t ip_offset = imm32;
1675 addr_t addr = ip - ip_offset; // the adjusted ip value
1676
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001677 EmulateInstruction::Context context;
1678 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001679 RegisterInfo dwarf_reg;
1680 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001681 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001682
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001684 return false;
1685 }
1686 return true;
1687}
1688
1689// Set ip to point to some stack offset.
1690// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001691bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001692EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001693{
1694#if 0
1695 // ARM pseudo code...
1696 if (ConditionPassed())
1697 {
1698 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001699 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001700 if d == 15 then // Can only occur for ARM encoding
1701 ALUWritePC(result); // setflags is always FALSE here
1702 else
1703 R[d] = result;
1704 if setflags then
1705 APSR.N = result<31>;
1706 APSR.Z = IsZeroBit(result);
1707 APSR.C = carry;
1708 APSR.V = overflow;
1709 }
1710#endif
1711
Greg Clayton7bc39082011-03-24 23:53:38 +00001712 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001713 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001714 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001715 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001716 if (!success)
1717 return false;
1718 uint32_t imm32;
1719 switch (encoding) {
1720 case eEncodingA1:
1721 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1722 break;
1723 default:
1724 return false;
1725 }
1726 addr_t sp_offset = imm32;
1727 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1728
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001729 EmulateInstruction::Context context;
1730 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001731 RegisterInfo dwarf_reg;
1732 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001733 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001734
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001735 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001736 return false;
1737 }
1738 return true;
1739}
1740
Johnny Chenc9e747f2011-02-23 01:55:07 +00001741// This instruction subtracts an immediate value from the SP value, and writes
1742// the result to the destination register.
1743//
1744// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001745bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001746EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001747{
1748#if 0
1749 // ARM pseudo code...
1750 if (ConditionPassed())
1751 {
1752 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001753 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001754 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001755 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001756 else
1757 R[d] = result;
1758 if setflags then
1759 APSR.N = result<31>;
1760 APSR.Z = IsZeroBit(result);
1761 APSR.C = carry;
1762 APSR.V = overflow;
1763 }
1764#endif
1765
1766 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001767 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001768 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001769 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001770 if (!success)
1771 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001772
1773 uint32_t Rd;
1774 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001775 uint32_t imm32;
1776 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001777 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001778 Rd = 13;
1779 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001780 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001781 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001782 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001783 Rd = Bits32(opcode, 11, 8);
1784 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001785 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001786 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001787 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001788 if (Rd == 15 && !setflags)
1789 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001790 break;
1791 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001792 Rd = Bits32(opcode, 11, 8);
1793 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001794 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001795 if (Rd == 15)
1796 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001797 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001798 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001799 Rd = Bits32(opcode, 15, 12);
1800 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001801 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001802
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001803 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001804 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001805 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001806 break;
1807 default:
1808 return false;
1809 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001810 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1811
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001812 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001813 if (Rd == 13)
1814 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001815 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1816 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001817 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001818 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001819 }
1820 else
1821 {
1822 context.type = EmulateInstruction::eContextImmediate;
1823 context.SetNoArgs ();
1824 }
1825
1826 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001827 return false;
1828 }
1829 return true;
1830}
1831
Johnny Chen08c25e82011-01-31 18:02:28 +00001832// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001833bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001834EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001835{
1836#if 0
1837 // ARM pseudo code...
1838 if (ConditionPassed())
1839 {
1840 EncodingSpecificOperations();
1841 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1842 address = if index then offset_addr else R[n];
1843 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1844 if wback then R[n] = offset_addr;
1845 }
1846#endif
1847
1848 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001849
Greg Clayton7bc39082011-03-24 23:53:38 +00001850 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001851 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001852 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001853 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001854 if (!success)
1855 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001856 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001857 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001858 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1859
1860 bool index;
1861 bool add;
1862 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001863 switch (encoding) {
1864 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001865 Rt = Bits32(opcode, 15, 12);
1866 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001867 Rn = Bits32 (opcode, 19, 16);
1868
1869 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1870 return false;
1871
1872 index = BitIsSet (opcode, 24);
1873 add = BitIsSet (opcode, 23);
1874 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1875
1876 if (wback && ((Rn == 15) || (Rn == Rt)))
1877 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001878 break;
1879 default:
1880 return false;
1881 }
Caroline Tice3e407972011-03-18 19:41:00 +00001882 addr_t offset_addr;
1883 if (add)
1884 offset_addr = sp + imm12;
1885 else
1886 offset_addr = sp - imm12;
1887
1888 addr_t addr;
1889 if (index)
1890 addr = offset_addr;
1891 else
1892 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001893
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001894 EmulateInstruction::Context context;
1895 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001896 RegisterInfo sp_reg;
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001897 RegisterInfo dwarf_reg;
1898
Greg Claytonc07d4512011-04-26 23:48:45 +00001899 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001900 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1901 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001902 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001903 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001904 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001905 if (!success)
1906 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001907 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001908 return false;
1909 }
1910 else
1911 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001912 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001913 if (!success)
1914 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001915 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001916 return false;
1917 }
1918
Caroline Tice3e407972011-03-18 19:41:00 +00001919
1920 if (wback)
1921 {
1922 context.type = EmulateInstruction::eContextAdjustStackPointer;
1923 context.SetImmediateSigned (addr - sp);
1924 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1925 return false;
1926 }
Johnny Chence1ca772011-01-25 01:13:00 +00001927 }
1928 return true;
1929}
1930
Johnny Chen08c25e82011-01-31 18:02:28 +00001931// Vector Push stores multiple extension registers to the stack.
1932// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001933bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001934EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001935{
1936#if 0
1937 // ARM pseudo code...
1938 if (ConditionPassed())
1939 {
1940 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1941 address = SP - imm32;
1942 SP = SP - imm32;
1943 if single_regs then
1944 for r = 0 to regs-1
1945 MemA[address,4] = S[d+r]; address = address+4;
1946 else
1947 for r = 0 to regs-1
1948 // Store as two word-aligned words in the correct order for current endianness.
1949 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1950 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1951 address = address+8;
1952 }
1953#endif
1954
1955 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001956
Greg Clayton7bc39082011-03-24 23:53:38 +00001957 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001958 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001959 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001960 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001961 if (!success)
1962 return false;
1963 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001964 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001965 uint32_t imm32; // stack offset
1966 uint32_t regs; // number of registers
1967 switch (encoding) {
1968 case eEncodingT1:
1969 case eEncodingA1:
1970 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001971 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001972 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1973 // If UInt(imm8) is odd, see "FSTMX".
1974 regs = Bits32(opcode, 7, 0) / 2;
1975 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1976 if (regs == 0 || regs > 16 || (d + regs) > 32)
1977 return false;
1978 break;
1979 case eEncodingT2:
1980 case eEncodingA2:
1981 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001982 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001983 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1984 regs = Bits32(opcode, 7, 0);
1985 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1986 if (regs == 0 || regs > 16 || (d + regs) > 32)
1987 return false;
1988 break;
1989 default:
1990 return false;
1991 }
1992 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1993 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1994 addr_t sp_offset = imm32;
1995 addr_t addr = sp - sp_offset;
1996 uint32_t i;
1997
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001998 EmulateInstruction::Context context;
1999 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002000 RegisterInfo dwarf_reg;
2001 RegisterInfo sp_reg;
2002 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002003 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00002004 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002005 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002006 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00002007 // uint64_t to accommodate 64-bit registers.
Greg Clayton061b79d2011-05-09 20:18:18 +00002008 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00002009 if (!success)
2010 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002011 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00002012 return false;
2013 addr += reg_byte_size;
2014 }
2015
2016 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002017 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00002018
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002019 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00002020 return false;
2021 }
2022 return true;
2023}
2024
Johnny Chen587a0a42011-02-01 18:35:28 +00002025// Vector Pop loads multiple extension registers from the stack.
2026// It also updates SP to point just above the loaded data.
2027bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002028EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00002029{
2030#if 0
2031 // ARM pseudo code...
2032 if (ConditionPassed())
2033 {
2034 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2035 address = SP;
2036 SP = SP + imm32;
2037 if single_regs then
2038 for r = 0 to regs-1
2039 S[d+r] = MemA[address,4]; address = address+4;
2040 else
2041 for r = 0 to regs-1
2042 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2043 // Combine the word-aligned words in the correct order for current endianness.
2044 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2045 }
2046#endif
2047
2048 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002049
Greg Clayton7bc39082011-03-24 23:53:38 +00002050 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002051 {
2052 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002053 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002054 if (!success)
2055 return false;
2056 bool single_regs;
2057 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2058 uint32_t imm32; // stack offset
2059 uint32_t regs; // number of registers
2060 switch (encoding) {
2061 case eEncodingT1:
2062 case eEncodingA1:
2063 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002064 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002065 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2066 // If UInt(imm8) is odd, see "FLDMX".
2067 regs = Bits32(opcode, 7, 0) / 2;
2068 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2069 if (regs == 0 || regs > 16 || (d + regs) > 32)
2070 return false;
2071 break;
2072 case eEncodingT2:
2073 case eEncodingA2:
2074 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002075 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002076 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2077 regs = Bits32(opcode, 7, 0);
2078 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2079 if (regs == 0 || regs > 16 || (d + regs) > 32)
2080 return false;
2081 break;
2082 default:
2083 return false;
2084 }
2085 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2086 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2087 addr_t sp_offset = imm32;
2088 addr_t addr = sp;
2089 uint32_t i;
2090 uint64_t data; // uint64_t to accomodate 64-bit registers.
2091
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002092 EmulateInstruction::Context context;
2093 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002094 RegisterInfo dwarf_reg;
2095 RegisterInfo sp_reg;
2096 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002097 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002098 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002099 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002100 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002101 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002102 if (!success)
2103 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +00002104 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002105 return false;
2106 addr += reg_byte_size;
2107 }
2108
2109 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002110 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002111
2112 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2113 return false;
2114 }
2115 return true;
2116}
2117
Johnny Chenb77be412011-02-04 00:40:18 +00002118// SVC (previously SWI)
2119bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002120EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002121{
2122#if 0
2123 // ARM pseudo code...
2124 if (ConditionPassed())
2125 {
2126 EncodingSpecificOperations();
2127 CallSupervisor();
2128 }
2129#endif
2130
2131 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002132
Greg Clayton7bc39082011-03-24 23:53:38 +00002133 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002134 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002135 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002136 addr_t lr; // next instruction address
2137 if (!success)
2138 return false;
2139 uint32_t imm32; // the immediate constant
2140 uint32_t mode; // ARM or Thumb mode
2141 switch (encoding) {
2142 case eEncodingT1:
2143 lr = (pc + 2) | 1u; // return address
2144 imm32 = Bits32(opcode, 7, 0);
2145 mode = eModeThumb;
2146 break;
2147 case eEncodingA1:
2148 lr = pc + 4; // return address
2149 imm32 = Bits32(opcode, 23, 0);
2150 mode = eModeARM;
2151 break;
2152 default:
2153 return false;
2154 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002155
2156 EmulateInstruction::Context context;
2157 context.type = EmulateInstruction::eContextSupervisorCall;
Greg Claytonc07d4512011-04-26 23:48:45 +00002158 context.SetISAAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002159 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2160 return false;
2161 }
2162 return true;
2163}
2164
Johnny Chenc315f862011-02-05 00:46:10 +00002165// If Then makes up to four following instructions (the IT block) conditional.
2166bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002167EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002168{
2169#if 0
2170 // ARM pseudo code...
2171 EncodingSpecificOperations();
2172 ITSTATE.IT<7:0> = firstcond:mask;
2173#endif
2174
Johnny Chenc315f862011-02-05 00:46:10 +00002175 m_it_session.InitIT(Bits32(opcode, 7, 0));
2176 return true;
2177}
2178
Greg Clayton04d397c2011-05-23 18:04:09 +00002179bool
2180EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding)
2181{
2182 // NOP, nothing to do...
2183 return true;
2184}
2185
Johnny Chen3b620b32011-02-07 20:11:47 +00002186// Branch causes a branch to a target address.
2187bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002188EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002189{
2190#if 0
2191 // ARM pseudo code...
2192 if (ConditionPassed())
2193 {
2194 EncodingSpecificOperations();
2195 BranchWritePC(PC + imm32);
2196 }
2197#endif
2198
2199 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002200
Greg Clayton7bc39082011-03-24 23:53:38 +00002201 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002202 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002203 EmulateInstruction::Context context;
2204 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002205 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002206 if (!success)
2207 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002208 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002209 int32_t imm32; // PC-relative offset
2210 switch (encoding) {
2211 case eEncodingT1:
2212 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2213 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002214 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002215 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002216 break;
2217 case eEncodingT2:
2218 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002219 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002220 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002221 break;
2222 case eEncodingT3:
2223 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2224 {
Johnny Chenbd599902011-02-10 21:39:01 +00002225 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002226 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002227 uint32_t J1 = Bit32(opcode, 13);
2228 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002229 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002230 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002231 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002232 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002233 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002234 break;
2235 }
2236 case eEncodingT4:
2237 {
Johnny Chenbd599902011-02-10 21:39:01 +00002238 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002239 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002240 uint32_t J1 = Bit32(opcode, 13);
2241 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002242 uint32_t imm11 = Bits32(opcode, 10, 0);
2243 uint32_t I1 = !(J1 ^ S);
2244 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002245 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002246 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002247 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002248 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002249 break;
2250 }
2251 case eEncodingA1:
2252 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002253 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002254 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002255 break;
2256 default:
2257 return false;
2258 }
2259 if (!BranchWritePC(context, target))
2260 return false;
2261 }
2262 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002263}
2264
Johnny Chen53ebab72011-02-08 23:21:57 +00002265// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2266// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2267// CBNZ, CBZ
2268bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002269EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002270{
2271#if 0
2272 // ARM pseudo code...
2273 EncodingSpecificOperations();
2274 if nonzero ^ IsZero(R[n]) then
2275 BranchWritePC(PC + imm32);
2276#endif
2277
2278 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002279
2280 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002281 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002282 if (!success)
2283 return false;
2284
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002285 EmulateInstruction::Context context;
2286 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002287 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002288 if (!success)
2289 return false;
2290
2291 addr_t target; // target address
2292 uint32_t imm32; // PC-relative offset to branch forward
2293 bool nonzero;
2294 switch (encoding) {
2295 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002296 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002297 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002298 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002299 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002300 break;
2301 default:
2302 return false;
2303 }
2304 if (nonzero ^ (reg_val == 0))
2305 if (!BranchWritePC(context, target))
2306 return false;
2307
2308 return true;
2309}
2310
Johnny Chen60299ec2011-02-17 19:34:27 +00002311// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2312// A base register provides a pointer to the table, and a second register supplies an index into the table.
2313// The branch length is twice the value of the byte returned from the table.
2314//
2315// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2316// A base register provides a pointer to the table, and a second register supplies an index into the table.
2317// The branch length is twice the value of the halfword returned from the table.
2318// TBB, TBH
2319bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002320EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002321{
2322#if 0
2323 // ARM pseudo code...
2324 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2325 if is_tbh then
2326 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2327 else
2328 halfwords = UInt(MemU[R[n]+R[m], 1]);
2329 BranchWritePC(PC + 2*halfwords);
2330#endif
2331
2332 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002333
2334 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2335 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2336 bool is_tbh; // true if table branch halfword
2337 switch (encoding) {
2338 case eEncodingT1:
2339 Rn = Bits32(opcode, 19, 16);
2340 Rm = Bits32(opcode, 3, 0);
2341 is_tbh = BitIsSet(opcode, 4);
2342 if (Rn == 13 || BadReg(Rm))
2343 return false;
2344 if (InITBlock() && !LastInITBlock())
2345 return false;
2346 break;
2347 default:
2348 return false;
2349 }
2350
2351 // Read the address of the table from the operand register Rn.
2352 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002353 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002354 if (!success)
2355 return false;
2356
2357 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002358 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002359 if (!success)
2360 return false;
2361
2362 // the offsetted table address
2363 addr_t addr = base + (is_tbh ? index*2 : index);
2364
2365 // PC-relative offset to branch forward
2366 EmulateInstruction::Context context;
2367 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002368 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002369 if (!success)
2370 return false;
2371
Johnny Chene39f22d2011-02-19 01:36:13 +00002372 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002373 if (!success)
2374 return false;
2375
2376 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002377 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002378 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Greg Claytonc07d4512011-04-26 23:48:45 +00002379 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
Johnny Chen60299ec2011-02-17 19:34:27 +00002380
2381 if (!BranchWritePC(context, target))
2382 return false;
2383
2384 return true;
2385}
2386
Caroline Ticedcc11b32011-03-02 23:57:02 +00002387// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2388// It can optionally update the condition flags based on the result.
2389bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002390EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002391{
2392#if 0
2393 if ConditionPassed() then
2394 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002395 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002396 R[d] = result;
2397 if setflags then
2398 APSR.N = result<31>;
2399 APSR.Z = IsZeroBit(result);
2400 APSR.C = carry;
2401 APSR.V = overflow;
2402#endif
2403
2404 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002405
Greg Clayton7bc39082011-03-24 23:53:38 +00002406 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002407 {
2408 uint32_t d;
2409 uint32_t n;
2410 bool setflags;
2411 uint32_t imm32;
2412 uint32_t carry_out;
2413
2414 //EncodingSpecificOperations();
2415 switch (encoding)
2416 {
2417 case eEncodingT1:
2418 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2419 d = Bits32 (opcode, 2, 0);
2420 n = Bits32 (opcode, 5, 3);
2421 setflags = !InITBlock();
2422 imm32 = Bits32 (opcode, 8,6);
2423
2424 break;
2425
2426 case eEncodingT2:
2427 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2428 d = Bits32 (opcode, 10, 8);
2429 n = Bits32 (opcode, 10, 8);
2430 setflags = !InITBlock();
2431 imm32 = Bits32 (opcode, 7, 0);
2432
2433 break;
2434
2435 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002436 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2437 // if Rn == '1101' then SEE ADD (SP plus immediate);
2438 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002439 d = Bits32 (opcode, 11, 8);
2440 n = Bits32 (opcode, 19, 16);
2441 setflags = BitIsSet (opcode, 20);
2442 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2443
2444 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2445 if (BadReg (d) || (n == 15))
2446 return false;
2447
2448 break;
2449
2450 case eEncodingT4:
2451 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002452 // if Rn == '1111' then SEE ADR;
2453 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002454 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2455 d = Bits32 (opcode, 11, 8);
2456 n = Bits32 (opcode, 19, 16);
2457 setflags = false;
2458 uint32_t i = Bit32 (opcode, 26);
2459 uint32_t imm3 = Bits32 (opcode, 14, 12);
2460 uint32_t imm8 = Bits32 (opcode, 7, 0);
2461 imm32 = (i << 11) | (imm3 << 8) | imm8;
2462
2463 // if BadReg(d) then UNPREDICTABLE;
2464 if (BadReg (d))
2465 return false;
2466
2467 break;
2468 }
2469 default:
2470 return false;
2471 }
2472
2473 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2474 if (!success)
2475 return false;
2476
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002477 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002478 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2479
Greg Claytonc07d4512011-04-26 23:48:45 +00002480 RegisterInfo reg_n;
2481 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002482
2483 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002484 context.type = eContextArithmetic;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002485 context.SetRegisterPlusOffset (reg_n, imm32);
2486
2487 //R[d] = result;
2488 //if setflags then
2489 //APSR.N = result<31>;
2490 //APSR.Z = IsZeroBit(result);
2491 //APSR.C = carry;
2492 //APSR.V = overflow;
2493 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2494 return false;
2495
2496 }
2497 return true;
2498}
2499
Johnny Chen8fa20592011-02-18 01:22:22 +00002500// This instruction adds an immediate value to a register value, and writes the result to the destination
2501// register. It can optionally update the condition flags based on the result.
2502bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002503EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002504{
2505#if 0
2506 // ARM pseudo code...
2507 if ConditionPassed() then
2508 EncodingSpecificOperations();
2509 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2510 if d == 15 then
2511 ALUWritePC(result); // setflags is always FALSE here
2512 else
2513 R[d] = result;
2514 if setflags then
2515 APSR.N = result<31>;
2516 APSR.Z = IsZeroBit(result);
2517 APSR.C = carry;
2518 APSR.V = overflow;
2519#endif
2520
2521 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002522
Greg Clayton7bc39082011-03-24 23:53:38 +00002523 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002524 {
2525 uint32_t Rd, Rn;
2526 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2527 bool setflags;
2528 switch (encoding)
2529 {
2530 case eEncodingA1:
2531 Rd = Bits32(opcode, 15, 12);
2532 Rn = Bits32(opcode, 19, 16);
2533 setflags = BitIsSet(opcode, 20);
2534 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2535 break;
2536 default:
2537 return false;
2538 }
2539
Johnny Chen8fa20592011-02-18 01:22:22 +00002540 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002541 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002542 if (!success)
2543 return false;
2544
2545 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2546
2547 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002548 context.type = eContextArithmetic;
2549 RegisterInfo dwarf_reg;
2550 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00002551 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002552
2553 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2554 return false;
2555 }
2556 return true;
2557}
2558
Johnny Chend761dcf2011-02-17 22:03:29 +00002559// This instruction adds a register value and an optionally-shifted register value, and writes the result
2560// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002561bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002562EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002563{
2564#if 0
2565 // ARM pseudo code...
2566 if ConditionPassed() then
2567 EncodingSpecificOperations();
2568 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2569 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2570 if d == 15 then
2571 ALUWritePC(result); // setflags is always FALSE here
2572 else
2573 R[d] = result;
2574 if setflags then
2575 APSR.N = result<31>;
2576 APSR.Z = IsZeroBit(result);
2577 APSR.C = carry;
2578 APSR.V = overflow;
2579#endif
2580
2581 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002582
Greg Clayton7bc39082011-03-24 23:53:38 +00002583 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002584 {
2585 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002586 ARM_ShifterType shift_t;
2587 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002588 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002589 switch (encoding)
2590 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002591 case eEncodingT1:
2592 Rd = Bits32(opcode, 2, 0);
2593 Rn = Bits32(opcode, 5, 3);
2594 Rm = Bits32(opcode, 8, 6);
2595 setflags = !InITBlock();
2596 shift_t = SRType_LSL;
2597 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002598 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002599 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002600 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002601 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002602 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002603 shift_t = SRType_LSL;
2604 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002605 if (Rn == 15 && Rm == 15)
2606 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002607 if (Rd == 15 && InITBlock() && !LastInITBlock())
2608 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002609 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002610 case eEncodingA1:
2611 Rd = Bits32(opcode, 15, 12);
2612 Rn = Bits32(opcode, 19, 16);
2613 Rm = Bits32(opcode, 3, 0);
2614 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002615 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002616 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002617 default:
2618 return false;
2619 }
2620
Johnny Chen26863dc2011-02-09 23:43:29 +00002621 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002622 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002623 if (!success)
2624 return false;
2625
2626 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002627 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002628 if (!success)
2629 return false;
2630
Johnny Chene97c0d52011-02-18 19:32:20 +00002631 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002632 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002633
2634 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002635 context.type = eContextArithmetic;
2636 RegisterInfo op1_reg;
2637 RegisterInfo op2_reg;
2638 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2639 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00002640 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002641
Johnny Chen10530c22011-02-17 22:37:12 +00002642 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002643 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002644 }
2645 return true;
2646}
2647
Johnny Chen34075cb2011-02-22 01:56:31 +00002648// Compare Negative (immediate) adds a register value and an immediate value.
2649// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002650bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002651EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002652{
2653#if 0
2654 // ARM pseudo code...
2655 if ConditionPassed() then
2656 EncodingSpecificOperations();
2657 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2658 APSR.N = result<31>;
2659 APSR.Z = IsZeroBit(result);
2660 APSR.C = carry;
2661 APSR.V = overflow;
2662#endif
2663
2664 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002665
2666 uint32_t Rn; // the first operand
2667 uint32_t imm32; // the immediate value to be compared with
2668 switch (encoding) {
2669 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002670 Rn = Bits32(opcode, 19, 16);
2671 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2672 if (Rn == 15)
2673 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002674 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002675 case eEncodingA1:
2676 Rn = Bits32(opcode, 19, 16);
2677 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2678 break;
2679 default:
2680 return false;
2681 }
2682 // Read the register value from the operand register Rn.
2683 uint32_t reg_val = ReadCoreReg(Rn, &success);
2684 if (!success)
2685 return false;
2686
Johnny Chen078fbc62011-02-22 19:48:22 +00002687 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002688
2689 EmulateInstruction::Context context;
2690 context.type = EmulateInstruction::eContextImmediate;
2691 context.SetNoArgs ();
2692 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2693 return false;
2694
2695 return true;
2696}
2697
2698// Compare Negative (register) adds a register value and an optionally-shifted register value.
2699// It updates the condition flags based on the result, and discards the result.
2700bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002701EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002702{
2703#if 0
2704 // ARM pseudo code...
2705 if ConditionPassed() then
2706 EncodingSpecificOperations();
2707 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2708 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2709 APSR.N = result<31>;
2710 APSR.Z = IsZeroBit(result);
2711 APSR.C = carry;
2712 APSR.V = overflow;
2713#endif
2714
2715 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002716
2717 uint32_t Rn; // the first operand
2718 uint32_t Rm; // the second operand
2719 ARM_ShifterType shift_t;
2720 uint32_t shift_n; // the shift applied to the value read from Rm
2721 switch (encoding) {
2722 case eEncodingT1:
2723 Rn = Bits32(opcode, 2, 0);
2724 Rm = Bits32(opcode, 5, 3);
2725 shift_t = SRType_LSL;
2726 shift_n = 0;
2727 break;
2728 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002729 Rn = Bits32(opcode, 19, 16);
2730 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002731 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002732 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2733 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002734 return false;
2735 break;
2736 case eEncodingA1:
2737 Rn = Bits32(opcode, 19, 16);
2738 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002739 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002740 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002741 default:
2742 return false;
2743 }
2744 // Read the register value from register Rn.
2745 uint32_t val1 = ReadCoreReg(Rn, &success);
2746 if (!success)
2747 return false;
2748
2749 // Read the register value from register Rm.
2750 uint32_t val2 = ReadCoreReg(Rm, &success);
2751 if (!success)
2752 return false;
2753
2754 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002755 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002756
2757 EmulateInstruction::Context context;
2758 context.type = EmulateInstruction::eContextImmediate;
2759 context.SetNoArgs();
2760 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2761 return false;
2762
2763 return true;
2764}
2765
2766// Compare (immediate) subtracts an immediate value from a register value.
2767// It updates the condition flags based on the result, and discards the result.
2768bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002769EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002770{
2771#if 0
2772 // ARM pseudo code...
2773 if ConditionPassed() then
2774 EncodingSpecificOperations();
2775 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2776 APSR.N = result<31>;
2777 APSR.Z = IsZeroBit(result);
2778 APSR.C = carry;
2779 APSR.V = overflow;
2780#endif
2781
2782 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002783
2784 uint32_t Rn; // the first operand
2785 uint32_t imm32; // the immediate value to be compared with
2786 switch (encoding) {
2787 case eEncodingT1:
2788 Rn = Bits32(opcode, 10, 8);
2789 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002790 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002791 case eEncodingT2:
2792 Rn = Bits32(opcode, 19, 16);
2793 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2794 if (Rn == 15)
2795 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002796 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002797 case eEncodingA1:
2798 Rn = Bits32(opcode, 19, 16);
2799 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002800 break;
2801 default:
2802 return false;
2803 }
2804 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002805 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002806 if (!success)
2807 return false;
2808
Johnny Chen10530c22011-02-17 22:37:12 +00002809 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2810
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002811 EmulateInstruction::Context context;
2812 context.type = EmulateInstruction::eContextImmediate;
2813 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002814 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2815 return false;
2816
Johnny Chend4dc4442011-02-11 02:02:56 +00002817 return true;
2818}
2819
Johnny Chen34075cb2011-02-22 01:56:31 +00002820// Compare (register) subtracts an optionally-shifted register value from a register value.
2821// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002822bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002823EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002824{
2825#if 0
2826 // ARM pseudo code...
2827 if ConditionPassed() then
2828 EncodingSpecificOperations();
2829 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2830 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2831 APSR.N = result<31>;
2832 APSR.Z = IsZeroBit(result);
2833 APSR.C = carry;
2834 APSR.V = overflow;
2835#endif
2836
2837 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002838
2839 uint32_t Rn; // the first operand
2840 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002841 ARM_ShifterType shift_t;
2842 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002843 switch (encoding) {
2844 case eEncodingT1:
2845 Rn = Bits32(opcode, 2, 0);
2846 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002847 shift_t = SRType_LSL;
2848 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002849 break;
2850 case eEncodingT2:
2851 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2852 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002853 shift_t = SRType_LSL;
2854 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002855 if (Rn < 8 && Rm < 8)
2856 return false;
2857 if (Rn == 15 || Rm == 15)
2858 return false;
2859 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002860 case eEncodingA1:
2861 Rn = Bits32(opcode, 19, 16);
2862 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002863 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002864 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002865 default:
2866 return false;
2867 }
2868 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002869 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002870 if (!success)
2871 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002872
Johnny Chene4a4d302011-02-11 21:53:58 +00002873 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002874 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002875 if (!success)
2876 return false;
2877
Johnny Chen34075cb2011-02-22 01:56:31 +00002878 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2879 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002880
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002881 EmulateInstruction::Context context;
2882 context.type = EmulateInstruction::eContextImmediate;
2883 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002884 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2885 return false;
2886
Johnny Chene4a4d302011-02-11 21:53:58 +00002887 return true;
2888}
2889
Johnny Chen82f16aa2011-02-15 20:10:55 +00002890// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2891// shifting in copies of its sign bit, and writes the result to the destination register. It can
2892// optionally update the condition flags based on the result.
2893bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002894EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002895{
2896#if 0
2897 // ARM pseudo code...
2898 if ConditionPassed() then
2899 EncodingSpecificOperations();
2900 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2901 if d == 15 then // Can only occur for ARM encoding
2902 ALUWritePC(result); // setflags is always FALSE here
2903 else
2904 R[d] = result;
2905 if setflags then
2906 APSR.N = result<31>;
2907 APSR.Z = IsZeroBit(result);
2908 APSR.C = carry;
2909 // APSR.V unchanged
2910#endif
2911
Greg Clayton7bc39082011-03-24 23:53:38 +00002912 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002913}
2914
2915// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2916// shifting in copies of its sign bit, and writes the result to the destination register.
2917// The variable number of bits is read from the bottom byte of a register. It can optionally update
2918// the condition flags based on the result.
2919bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002920EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002921{
2922#if 0
2923 // ARM pseudo code...
2924 if ConditionPassed() then
2925 EncodingSpecificOperations();
2926 shift_n = UInt(R[m]<7:0>);
2927 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2928 R[d] = result;
2929 if setflags then
2930 APSR.N = result<31>;
2931 APSR.Z = IsZeroBit(result);
2932 APSR.C = carry;
2933 // APSR.V unchanged
2934#endif
2935
Greg Clayton7bc39082011-03-24 23:53:38 +00002936 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002937}
2938
2939// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2940// shifting in zeros, and writes the result to the destination register. It can optionally
2941// update the condition flags based on the result.
2942bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002943EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002944{
2945#if 0
2946 // ARM pseudo code...
2947 if ConditionPassed() then
2948 EncodingSpecificOperations();
2949 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2950 if d == 15 then // Can only occur for ARM encoding
2951 ALUWritePC(result); // setflags is always FALSE here
2952 else
2953 R[d] = result;
2954 if setflags then
2955 APSR.N = result<31>;
2956 APSR.Z = IsZeroBit(result);
2957 APSR.C = carry;
2958 // APSR.V unchanged
2959#endif
2960
Greg Clayton7bc39082011-03-24 23:53:38 +00002961 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002962}
2963
2964// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2965// shifting in zeros, and writes the result to the destination register. The variable number
2966// of bits is read from the bottom byte of a register. It can optionally update the condition
2967// flags based on the result.
2968bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002969EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002970{
2971#if 0
2972 // ARM pseudo code...
2973 if ConditionPassed() then
2974 EncodingSpecificOperations();
2975 shift_n = UInt(R[m]<7:0>);
2976 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2977 R[d] = result;
2978 if setflags then
2979 APSR.N = result<31>;
2980 APSR.Z = IsZeroBit(result);
2981 APSR.C = carry;
2982 // APSR.V unchanged
2983#endif
2984
Greg Clayton7bc39082011-03-24 23:53:38 +00002985 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002986}
2987
2988// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2989// shifting in zeros, and writes the result to the destination register. It can optionally
2990// update the condition flags based on the result.
2991bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002992EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002993{
2994#if 0
2995 // ARM pseudo code...
2996 if ConditionPassed() then
2997 EncodingSpecificOperations();
2998 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2999 if d == 15 then // Can only occur for ARM encoding
3000 ALUWritePC(result); // setflags is always FALSE here
3001 else
3002 R[d] = result;
3003 if setflags then
3004 APSR.N = result<31>;
3005 APSR.Z = IsZeroBit(result);
3006 APSR.C = carry;
3007 // APSR.V unchanged
3008#endif
3009
Greg Clayton7bc39082011-03-24 23:53:38 +00003010 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003011}
3012
3013// Logical Shift Right (register) shifts a register value right by a variable number of bits,
3014// shifting in zeros, and writes the result to the destination register. The variable number
3015// of bits is read from the bottom byte of a register. It can optionally update the condition
3016// flags based on the result.
3017bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003018EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003019{
3020#if 0
3021 // ARM pseudo code...
3022 if ConditionPassed() then
3023 EncodingSpecificOperations();
3024 shift_n = UInt(R[m]<7:0>);
3025 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3026 R[d] = result;
3027 if setflags then
3028 APSR.N = result<31>;
3029 APSR.Z = IsZeroBit(result);
3030 APSR.C = carry;
3031 // APSR.V unchanged
3032#endif
3033
Greg Clayton7bc39082011-03-24 23:53:38 +00003034 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003035}
3036
Johnny Cheneeab4852011-02-16 22:14:44 +00003037// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3038// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3039// It can optionally update the condition flags based on the result.
3040bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003041EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003042{
3043#if 0
3044 // ARM pseudo code...
3045 if ConditionPassed() then
3046 EncodingSpecificOperations();
3047 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3048 if d == 15 then // Can only occur for ARM encoding
3049 ALUWritePC(result); // setflags is always FALSE here
3050 else
3051 R[d] = result;
3052 if setflags then
3053 APSR.N = result<31>;
3054 APSR.Z = IsZeroBit(result);
3055 APSR.C = carry;
3056 // APSR.V unchanged
3057#endif
3058
Greg Clayton7bc39082011-03-24 23:53:38 +00003059 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003060}
3061
3062// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3063// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3064// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3065// flags based on the result.
3066bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003067EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003068{
3069#if 0
3070 // ARM pseudo code...
3071 if ConditionPassed() then
3072 EncodingSpecificOperations();
3073 shift_n = UInt(R[m]<7:0>);
3074 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3075 R[d] = result;
3076 if setflags then
3077 APSR.N = result<31>;
3078 APSR.Z = IsZeroBit(result);
3079 APSR.C = carry;
3080 // APSR.V unchanged
3081#endif
3082
Greg Clayton7bc39082011-03-24 23:53:38 +00003083 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003084}
3085
3086// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3087// with the carry flag shifted into bit [31].
3088//
3089// RRX can optionally update the condition flags based on the result.
3090// In that case, bit [0] is shifted into the carry flag.
3091bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003092EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003093{
3094#if 0
3095 // ARM pseudo code...
3096 if ConditionPassed() then
3097 EncodingSpecificOperations();
3098 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3099 if d == 15 then // Can only occur for ARM encoding
3100 ALUWritePC(result); // setflags is always FALSE here
3101 else
3102 R[d] = result;
3103 if setflags then
3104 APSR.N = result<31>;
3105 APSR.Z = IsZeroBit(result);
3106 APSR.C = carry;
3107 // APSR.V unchanged
3108#endif
3109
Greg Clayton7bc39082011-03-24 23:53:38 +00003110 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003111}
3112
Johnny Chen41a0a152011-02-16 01:27:54 +00003113bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003114EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003115{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003116// assert(shift_type == SRType_ASR
3117// || shift_type == SRType_LSL
3118// || shift_type == SRType_LSR
3119// || shift_type == SRType_ROR
3120// || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003121
Johnny Chen82f16aa2011-02-15 20:10:55 +00003122 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003123
Greg Clayton7bc39082011-03-24 23:53:38 +00003124 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003125 {
Johnny Chene7f89532011-02-15 23:22:46 +00003126 uint32_t Rd; // the destination register
3127 uint32_t Rm; // the first operand register
3128 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003129 uint32_t carry; // the carry bit after the shift operation
3130 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003131
3132 // Special case handling!
3133 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003134 ARMEncoding use_encoding = encoding;
3135 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003136 {
3137 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3138 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003139 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003140 }
3141
Greg Clayton7bc39082011-03-24 23:53:38 +00003142 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003143 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003144 // Due to the above special case handling!
Greg Claytone1f47bb2011-06-02 22:23:35 +00003145 //assert(shift_type != SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003146
Johnny Chen82f16aa2011-02-15 20:10:55 +00003147 Rd = Bits32(opcode, 2, 0);
3148 Rm = Bits32(opcode, 5, 3);
3149 setflags = !InITBlock();
3150 imm5 = Bits32(opcode, 10, 6);
3151 break;
3152 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003153 // A8.6.141 RRX
Greg Claytone1f47bb2011-06-02 22:23:35 +00003154 //assert(shift_type != SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003155
Johnny Chen82f16aa2011-02-15 20:10:55 +00003156 Rd = Bits32(opcode, 11, 8);
3157 Rm = Bits32(opcode, 3, 0);
3158 setflags = BitIsSet(opcode, 20);
3159 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3160 if (BadReg(Rd) || BadReg(Rm))
3161 return false;
3162 break;
3163 case eEncodingA1:
3164 Rd = Bits32(opcode, 15, 12);
3165 Rm = Bits32(opcode, 3, 0);
3166 setflags = BitIsSet(opcode, 20);
3167 imm5 = Bits32(opcode, 11, 7);
3168 break;
3169 default:
3170 return false;
3171 }
3172
Johnny Cheneeab4852011-02-16 22:14:44 +00003173 // A8.6.139 ROR (immediate)
3174 if (shift_type == SRType_ROR && imm5 == 0)
3175 shift_type = SRType_RRX;
3176
Johnny Chen82f16aa2011-02-15 20:10:55 +00003177 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003178 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003179 if (!success)
3180 return false;
3181
Johnny Cheneeab4852011-02-16 22:14:44 +00003182 // Decode the shift amount if not RRX.
3183 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003184
Johnny Chene97c0d52011-02-18 19:32:20 +00003185 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003186
3187 // The context specifies that an immediate is to be moved into Rd.
3188 EmulateInstruction::Context context;
3189 context.type = EmulateInstruction::eContextImmediate;
3190 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003191
Johnny Chen10530c22011-02-17 22:37:12 +00003192 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003193 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003194 }
3195 return true;
3196}
3197
Johnny Chene7f89532011-02-15 23:22:46 +00003198bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003199EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003200{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003201 // assert(shift_type == SRType_ASR
3202 // || shift_type == SRType_LSL
3203 // || shift_type == SRType_LSR
3204 // || shift_type == SRType_ROR);
Johnny Chene7f89532011-02-15 23:22:46 +00003205
3206 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003207
Greg Clayton7bc39082011-03-24 23:53:38 +00003208 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003209 {
3210 uint32_t Rd; // the destination register
3211 uint32_t Rn; // the first operand register
3212 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3213 uint32_t carry; // the carry bit after the shift operation
3214 bool setflags;
3215 switch (encoding) {
3216 case eEncodingT1:
3217 Rd = Bits32(opcode, 2, 0);
3218 Rn = Rd;
3219 Rm = Bits32(opcode, 5, 3);
3220 setflags = !InITBlock();
3221 break;
3222 case eEncodingT2:
3223 Rd = Bits32(opcode, 11, 8);
3224 Rn = Bits32(opcode, 19, 16);
3225 Rm = Bits32(opcode, 3, 0);
3226 setflags = BitIsSet(opcode, 20);
3227 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3228 return false;
3229 break;
3230 case eEncodingA1:
3231 Rd = Bits32(opcode, 15, 12);
3232 Rn = Bits32(opcode, 3, 0);
3233 Rm = Bits32(opcode, 11, 8);
3234 setflags = BitIsSet(opcode, 20);
3235 if (Rd == 15 || Rn == 15 || Rm == 15)
3236 return false;
3237 break;
3238 default:
3239 return false;
3240 }
3241
3242 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003243 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003244 if (!success)
3245 return false;
3246 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003247 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003248 if (!success)
3249 return false;
3250
3251 // Get the shift amount.
3252 uint32_t amt = Bits32(val, 7, 0);
3253
Johnny Chene97c0d52011-02-18 19:32:20 +00003254 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003255
3256 // The context specifies that an immediate is to be moved into Rd.
3257 EmulateInstruction::Context context;
3258 context.type = EmulateInstruction::eContextImmediate;
3259 context.SetNoArgs ();
3260
Johnny Chen10530c22011-02-17 22:37:12 +00003261 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003262 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003263 }
3264 return true;
3265}
3266
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003267// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003268// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003269// can be written back to the base register.
3270bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003271EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003272{
3273#if 0
3274 // ARM pseudo code...
3275 if ConditionPassed()
3276 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3277 address = R[n];
3278
3279 for i = 0 to 14
3280 if registers<i> == '1' then
3281 R[i] = MemA[address, 4]; address = address + 4;
3282 if registers<15> == '1' then
3283 LoadWritePC (MemA[address, 4]);
3284
3285 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3286 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3287
3288#endif
3289
3290 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003291
Greg Clayton7bc39082011-03-24 23:53:38 +00003292 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003293 {
3294 uint32_t n;
3295 uint32_t registers = 0;
3296 bool wback;
3297 const uint32_t addr_byte_size = GetAddressByteSize();
3298 switch (encoding)
3299 {
3300 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003301 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003302 n = Bits32 (opcode, 10, 8);
3303 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003304 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003305 wback = BitIsClear (registers, n);
3306 // if BitCount(registers) < 1 then UNPREDICTABLE;
3307 if (BitCount(registers) < 1)
3308 return false;
3309 break;
3310 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003311 // if W == '1' && Rn == '1101' then SEE POP;
3312 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003313 n = Bits32 (opcode, 19, 16);
3314 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003315 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003316 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003317
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003318 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003319 if ((n == 15)
3320 || (BitCount (registers) < 2)
3321 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3322 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003323
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003324 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003325 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003326 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003327
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003328 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003329 if (wback
3330 && BitIsSet (registers, n))
3331 return false;
3332 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003333
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003334 case eEncodingA1:
3335 n = Bits32 (opcode, 19, 16);
3336 registers = Bits32 (opcode, 15, 0);
3337 wback = BitIsSet (opcode, 21);
3338 if ((n == 15)
3339 || (BitCount (registers) < 1))
3340 return false;
3341 break;
3342 default:
3343 return false;
3344 }
3345
3346 int32_t offset = 0;
3347 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3348 if (!success)
3349 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003350
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003351 EmulateInstruction::Context context;
3352 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003353 RegisterInfo dwarf_reg;
3354 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003355 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003356
3357 for (int i = 0; i < 14; ++i)
3358 {
3359 if (BitIsSet (registers, i))
3360 {
Caroline Tice85aab332011-02-08 23:56:10 +00003361 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003362 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003363 if (wback && (n == 13)) // Pop Instruction
3364 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3365
3366 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003367 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003368 if (!success)
3369 return false;
3370
3371 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3372 return false;
3373
3374 offset += addr_byte_size;
3375 }
3376 }
3377
3378 if (BitIsSet (registers, 15))
3379 {
3380 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003381 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003382 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003383 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003384 if (!success)
3385 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003386 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003387 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003388 return false;
3389 }
3390
3391 if (wback && BitIsClear (registers, n))
3392 {
Caroline Ticefa172202011-02-11 22:49:54 +00003393 // R[n] = R[n] + 4 * BitCount (registers)
3394 int32_t offset = addr_byte_size * BitCount (registers);
3395 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003396 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003397
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003398 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3399 return false;
3400 }
3401 if (wback && BitIsSet (registers, n))
3402 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003403 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003404 }
3405 return true;
3406}
Caroline Tice713c2662011-02-11 17:59:55 +00003407
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003408// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3409// The consecutive memory locations end at this address and the address just below the lowest of those locations
3410// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003411bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003412EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003413{
3414#if 0
3415 // ARM pseudo code...
3416 if ConditionPassed() then
3417 EncodingSpecificOperations();
3418 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003419
Caroline Tice713c2662011-02-11 17:59:55 +00003420 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003421 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003422 R[i] = MemA[address,4]; address = address + 4;
3423
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003424 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003425 LoadWritePC(MemA[address,4]);
3426
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003427 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3428 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003429#endif
3430
3431 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003432
Greg Clayton7bc39082011-03-24 23:53:38 +00003433 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003434 {
3435 uint32_t n;
3436 uint32_t registers = 0;
3437 bool wback;
3438 const uint32_t addr_byte_size = GetAddressByteSize();
3439
3440 // EncodingSpecificOperations();
3441 switch (encoding)
3442 {
3443 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003444 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003445 n = Bits32 (opcode, 19, 16);
3446 registers = Bits32 (opcode, 15, 0);
3447 wback = BitIsSet (opcode, 21);
3448
3449 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3450 if ((n == 15) || (BitCount (registers) < 1))
3451 return false;
3452
3453 break;
3454
3455 default:
3456 return false;
3457 }
3458 // address = R[n] - 4*BitCount(registers) + 4;
3459
3460 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003461 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003462
3463 if (!success)
3464 return false;
3465
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003466 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003467
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003468 EmulateInstruction::Context context;
3469 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003470 RegisterInfo dwarf_reg;
3471 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003472 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003473
3474 // for i = 0 to 14
3475 for (int i = 0; i < 14; ++i)
3476 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003477 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003478 if (BitIsSet (registers, i))
3479 {
3480 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003481 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003482 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003483 if (!success)
3484 return false;
3485 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3486 return false;
3487 offset += addr_byte_size;
3488 }
3489 }
3490
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003491 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003492 // LoadWritePC(MemA[address,4]);
3493 if (BitIsSet (registers, 15))
3494 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003495 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003496 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003497 if (!success)
3498 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003499 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003500 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003501 return false;
3502 }
3503
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003504 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003505 if (wback && BitIsClear (registers, n))
3506 {
Caroline Tice713c2662011-02-11 17:59:55 +00003507 if (!success)
3508 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003509
3510 offset = (addr_byte_size * BitCount (registers)) * -1;
3511 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003512 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003513 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003514 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3515 return false;
3516 }
3517
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003518 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003519 if (wback && BitIsSet (registers, n))
3520 return WriteBits32Unknown (n);
3521 }
3522 return true;
3523}
3524
3525// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3526// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3527// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003528bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003529EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003530{
3531#if 0
3532 // ARM pseudo code...
3533 if ConditionPassed() then
3534 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3535 address = R[n] - 4*BitCount(registers);
3536
3537 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003538 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003539 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003540 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003541 LoadWritePC(MemA[address,4]);
3542
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003543 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3544 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003545#endif
3546
3547 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003548
Greg Clayton7bc39082011-03-24 23:53:38 +00003549 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003550 {
3551 uint32_t n;
3552 uint32_t registers = 0;
3553 bool wback;
3554 const uint32_t addr_byte_size = GetAddressByteSize();
3555 switch (encoding)
3556 {
3557 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003558 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003559 n = Bits32 (opcode, 19, 16);
3560 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003561 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003562 wback = BitIsSet (opcode, 21);
3563
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003564 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003565 if ((n == 15)
3566 || (BitCount (registers) < 2)
3567 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3568 return false;
3569
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003570 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003571 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003572 return false;
3573
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003574 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003575 if (wback && BitIsSet (registers, n))
3576 return false;
3577
3578 break;
3579
3580 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003581 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003582 n = Bits32 (opcode, 19, 16);
3583 registers = Bits32 (opcode, 15, 0);
3584 wback = BitIsSet (opcode, 21);
3585
3586 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3587 if ((n == 15) || (BitCount (registers) < 1))
3588 return false;
3589
3590 break;
3591
3592 default:
3593 return false;
3594 }
3595
Caroline Tice713c2662011-02-11 17:59:55 +00003596 // address = R[n] - 4*BitCount(registers);
3597
Caroline Tice0b29e242011-02-08 23:16:02 +00003598 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003599 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003600
3601 if (!success)
3602 return false;
3603
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003604 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003605 EmulateInstruction::Context context;
3606 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003607 RegisterInfo dwarf_reg;
3608 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003609 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003610
3611 for (int i = 0; i < 14; ++i)
3612 {
3613 if (BitIsSet (registers, i))
3614 {
3615 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003616 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003617 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003618 if (!success)
3619 return false;
3620
3621 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3622 return false;
3623
3624 offset += addr_byte_size;
3625 }
3626 }
3627
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003628 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003629 // LoadWritePC(MemA[address,4]);
3630 if (BitIsSet (registers, 15))
3631 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003632 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003633 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003634 if (!success)
3635 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003636 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003637 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003638 return false;
3639 }
3640
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003641 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003642 if (wback && BitIsClear (registers, n))
3643 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003644 if (!success)
3645 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003646
3647 offset = (addr_byte_size * BitCount (registers)) * -1;
3648 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003649 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003650 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003651 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3652 return false;
3653 }
3654
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003655 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003656 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003657 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003658 }
3659 return true;
3660}
Caroline Tice85aab332011-02-08 23:56:10 +00003661
Caroline Tice713c2662011-02-11 17:59:55 +00003662// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3663// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3664// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003665bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003666EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003667{
3668#if 0
3669 if ConditionPassed() then
3670 EncodingSpecificOperations();
3671 address = R[n] + 4;
3672
3673 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003674 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003675 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003676 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003677 LoadWritePC(MemA[address,4]);
3678
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003679 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3680 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003681#endif
3682
3683 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003684
Greg Clayton7bc39082011-03-24 23:53:38 +00003685 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003686 {
3687 uint32_t n;
3688 uint32_t registers = 0;
3689 bool wback;
3690 const uint32_t addr_byte_size = GetAddressByteSize();
3691 switch (encoding)
3692 {
3693 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003694 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003695 n = Bits32 (opcode, 19, 16);
3696 registers = Bits32 (opcode, 15, 0);
3697 wback = BitIsSet (opcode, 21);
3698
3699 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3700 if ((n == 15) || (BitCount (registers) < 1))
3701 return false;
3702
3703 break;
3704 default:
3705 return false;
3706 }
3707 // address = R[n] + 4;
3708
3709 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003710 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003711
3712 if (!success)
3713 return false;
3714
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003715 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003716
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003717 EmulateInstruction::Context context;
3718 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003719 RegisterInfo dwarf_reg;
3720 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003721 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003722
3723 for (int i = 0; i < 14; ++i)
3724 {
3725 if (BitIsSet (registers, i))
3726 {
3727 // R[i] = MemA[address,4]; address = address + 4;
3728
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003729 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003730 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003731 if (!success)
3732 return false;
3733
3734 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3735 return false;
3736
3737 offset += addr_byte_size;
3738 }
3739 }
3740
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003741 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003742 // LoadWritePC(MemA[address,4]);
3743 if (BitIsSet (registers, 15))
3744 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003745 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003746 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003747 if (!success)
3748 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003749 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003750 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003751 return false;
3752 }
3753
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003754 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003755 if (wback && BitIsClear (registers, n))
3756 {
Caroline Tice85aab332011-02-08 23:56:10 +00003757 if (!success)
3758 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003759
3760 offset = addr_byte_size * BitCount (registers);
3761 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003762 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003763 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003764 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3765 return false;
3766 }
3767
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003768 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003769 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003770 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003771 }
3772 return true;
3773}
Caroline Tice0b29e242011-02-08 23:16:02 +00003774
Johnny Chenef21b592011-02-10 01:52:38 +00003775// Load Register (immediate) calculates an address from a base register value and
3776// an immediate offset, loads a word from memory, and writes to a register.
3777// LDR (immediate, Thumb)
3778bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003779EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003780{
3781#if 0
3782 // ARM pseudo code...
3783 if (ConditionPassed())
3784 {
3785 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3786 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3787 address = if index then offset_addr else R[n];
3788 data = MemU[address,4];
3789 if wback then R[n] = offset_addr;
3790 if t == 15 then
3791 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3792 elsif UnalignedSupport() || address<1:0> = '00' then
3793 R[t] = data;
3794 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3795 }
3796#endif
3797
3798 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003799
Greg Clayton7bc39082011-03-24 23:53:38 +00003800 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003801 {
3802 uint32_t Rt; // the destination register
3803 uint32_t Rn; // the base register
3804 uint32_t imm32; // the immediate offset used to form the address
3805 addr_t offset_addr; // the offset address
3806 addr_t address; // the calculated address
3807 uint32_t data; // the literal data value from memory load
3808 bool add, index, wback;
3809 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003810 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003811 Rt = Bits32(opcode, 2, 0);
3812 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003813 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3814 // index = TRUE; add = TRUE; wback = FALSE
3815 add = true;
3816 index = true;
3817 wback = false;
3818
3819 break;
3820
3821 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003822 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003823 Rt = Bits32 (opcode, 10, 8);
3824 Rn = 13;
3825 imm32 = Bits32 (opcode, 7, 0) << 2;
3826
3827 // index = TRUE; add = TRUE; wback = FALSE;
3828 index = true;
3829 add = true;
3830 wback = false;
3831
3832 break;
3833
3834 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003835 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003836 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3837 Rt = Bits32 (opcode, 15, 12);
3838 Rn = Bits32 (opcode, 19, 16);
3839 imm32 = Bits32 (opcode, 11, 0);
3840
3841 // index = TRUE; add = TRUE; wback = FALSE;
3842 index = true;
3843 add = true;
3844 wback = false;
3845
3846 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3847 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3848 return false;
3849
3850 break;
3851
3852 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003853 // if Rn == '1111' then SEE LDR (literal);
3854 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3855 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3856 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003857 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3858 return false;
3859
3860 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3861 Rt = Bits32 (opcode, 15, 12);
3862 Rn = Bits32 (opcode, 19, 16);
3863 imm32 = Bits32 (opcode, 7, 0);
3864
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003865 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003866 index = BitIsSet (opcode, 10);
3867 add = BitIsSet (opcode, 9);
3868 wback = BitIsSet (opcode, 8);
3869
3870 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3871 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3872 return false;
3873
3874 break;
3875
3876 default:
3877 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003878 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003879 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003880 if (!success)
3881 return false;
3882 if (add)
3883 offset_addr = base + imm32;
3884 else
3885 offset_addr = base - imm32;
3886
3887 address = (index ? offset_addr : base);
3888
Greg Claytonc07d4512011-04-26 23:48:45 +00003889 RegisterInfo base_reg;
3890 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
Johnny Chenef21b592011-02-10 01:52:38 +00003891 if (wback)
3892 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003893 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003894 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3895 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003896
Johnny Chenef21b592011-02-10 01:52:38 +00003897 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3898 return false;
3899 }
3900
3901 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003902 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003903 context.type = EmulateInstruction::eContextRegisterLoad;
3904 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003905
3906 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003907 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003908 if (!success)
3909 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003910
3911 if (Rt == 15)
3912 {
3913 if (Bits32(address, 1, 0) == 0)
3914 {
Johnny Chen668b4512011-02-15 21:08:58 +00003915 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003916 return false;
3917 }
3918 else
3919 return false;
3920 }
3921 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3922 {
3923 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3924 return false;
3925 }
3926 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003927 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003928 }
3929 return true;
3930}
3931
Caroline Ticeaf556562011-02-15 18:42:15 +00003932// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3933// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3934// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003935bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003936EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003937{
3938#if 0
3939 if ConditionPassed() then
3940 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3941 address = R[n];
3942
3943 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003944 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003945 if i == n && wback && i != LowestSetBit(registers) then
3946 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3947 else
3948 MemA[address,4] = R[i];
3949 address = address + 4;
3950
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003951 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003952 MemA[address,4] = PCStoreValue();
3953 if wback then R[n] = R[n] + 4*BitCount(registers);
3954#endif
3955
3956 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003957
Greg Clayton7bc39082011-03-24 23:53:38 +00003958 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003959 {
3960 uint32_t n;
3961 uint32_t registers = 0;
3962 bool wback;
3963 const uint32_t addr_byte_size = GetAddressByteSize();
3964
3965 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3966 switch (encoding)
3967 {
3968 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003969 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003970 n = Bits32 (opcode, 10, 8);
3971 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003972 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003973 wback = true;
3974
3975 // if BitCount(registers) < 1 then UNPREDICTABLE;
3976 if (BitCount (registers) < 1)
3977 return false;
3978
3979 break;
3980
3981 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003982 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003983 n = Bits32 (opcode, 19, 16);
3984 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003985 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003986 wback = BitIsSet (opcode, 21);
3987
3988 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3989 if ((n == 15) || (BitCount (registers) < 2))
3990 return false;
3991
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003992 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003993 if (wback && BitIsSet (registers, n))
3994 return false;
3995
3996 break;
3997
3998 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003999 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00004000 n = Bits32 (opcode, 19, 16);
4001 registers = Bits32 (opcode, 15, 0);
4002 wback = BitIsSet (opcode, 21);
4003
4004 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4005 if ((n == 15) || (BitCount (registers) < 1))
4006 return false;
4007
4008 break;
4009
4010 default:
4011 return false;
4012 }
4013
4014 // address = R[n];
4015 int32_t offset = 0;
4016 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4017 if (!success)
4018 return false;
4019
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004020 EmulateInstruction::Context context;
4021 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004022 RegisterInfo base_reg;
4023 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefa172202011-02-11 22:49:54 +00004024
4025 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004026 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00004027 for (int i = 0; i < 14; ++i)
4028 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004029 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00004030 if (BitIsSet (registers, i))
4031 {
4032 if (i < lowest_set_bit)
4033 lowest_set_bit = i;
4034 // if i == n && wback && i != LowestSetBit(registers) then
4035 if ((i == n) && wback && (i != lowest_set_bit))
4036 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4037 WriteBits32UnknownToMemory (address + offset);
4038 else
4039 {
4040 // MemA[address,4] = R[i];
4041 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4042 if (!success)
4043 return false;
4044
Greg Claytonc07d4512011-04-26 23:48:45 +00004045 RegisterInfo data_reg;
4046 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004047 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004048 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004049 return false;
4050 }
4051
4052 // address = address + 4;
4053 offset += addr_byte_size;
4054 }
4055 }
4056
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004057 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004058 // MemA[address,4] = PCStoreValue();
4059 if (BitIsSet (registers, 15))
4060 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004061 RegisterInfo pc_reg;
4062 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004063 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004064 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004065 if (!success)
4066 return false;
4067
Caroline Tice8d681f52011-03-17 23:50:16 +00004068 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004069 return false;
4070 }
4071
4072 // if wback then R[n] = R[n] + 4*BitCount(registers);
4073 if (wback)
4074 {
4075 offset = addr_byte_size * BitCount (registers);
4076 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004077 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004078 addr_t data = address + offset;
4079 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4080 return false;
4081 }
4082 }
4083 return true;
4084}
4085
Caroline Ticeaf556562011-02-15 18:42:15 +00004086// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4087// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4088// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004089bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004090EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004091{
4092#if 0
4093 if ConditionPassed() then
4094 EncodingSpecificOperations();
4095 address = R[n] - 4*BitCount(registers) + 4;
4096
4097 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004098 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004099 if i == n && wback && i != LowestSetBit(registers) then
4100 MemA[address,4] = bits(32) UNKNOWN;
4101 else
4102 MemA[address,4] = R[i];
4103 address = address + 4;
4104
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004105 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004106 MemA[address,4] = PCStoreValue();
4107
4108 if wback then R[n] = R[n] - 4*BitCount(registers);
4109#endif
4110
4111 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004112
Greg Clayton7bc39082011-03-24 23:53:38 +00004113 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004114 {
4115 uint32_t n;
4116 uint32_t registers = 0;
4117 bool wback;
4118 const uint32_t addr_byte_size = GetAddressByteSize();
4119
4120 // EncodingSpecificOperations();
4121 switch (encoding)
4122 {
4123 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004124 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004125 n = Bits32 (opcode, 19, 16);
4126 registers = Bits32 (opcode, 15, 0);
4127 wback = BitIsSet (opcode, 21);
4128
4129 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4130 if ((n == 15) || (BitCount (registers) < 1))
4131 return false;
4132 break;
4133 default:
4134 return false;
4135 }
4136
4137 // address = R[n] - 4*BitCount(registers) + 4;
4138 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004139 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004140 if (!success)
4141 return false;
4142
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004143 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004144
4145 EmulateInstruction::Context context;
4146 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004147 RegisterInfo base_reg;
4148 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004149
4150 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004151 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004152 for (int i = 0; i < 14; ++i)
4153 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004154 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004155 if (BitIsSet (registers, i))
4156 {
4157 if (i < lowest_bit_set)
4158 lowest_bit_set = i;
4159 //if i == n && wback && i != LowestSetBit(registers) then
4160 if ((i == n) && wback && (i != lowest_bit_set))
4161 // MemA[address,4] = bits(32) UNKNOWN;
4162 WriteBits32UnknownToMemory (address + offset);
4163 else
4164 {
4165 // MemA[address,4] = R[i];
4166 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4167 if (!success)
4168 return false;
4169
Greg Claytonc07d4512011-04-26 23:48:45 +00004170 RegisterInfo data_reg;
4171 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004172 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004173 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004174 return false;
4175 }
4176
4177 // address = address + 4;
4178 offset += addr_byte_size;
4179 }
4180 }
4181
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004182 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004183 // MemA[address,4] = PCStoreValue();
4184 if (BitIsSet (registers, 15))
4185 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004186 RegisterInfo pc_reg;
4187 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004188 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004189 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004190 if (!success)
4191 return false;
4192
Caroline Tice8d681f52011-03-17 23:50:16 +00004193 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004194 return false;
4195 }
4196
4197 // if wback then R[n] = R[n] - 4*BitCount(registers);
4198 if (wback)
4199 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004200 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004201 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4202 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004203 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004204 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4205 return false;
4206 }
4207 }
4208 return true;
4209}
4210
Caroline Ticeaf556562011-02-15 18:42:15 +00004211// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4212// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4213// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004214bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004215EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004216{
4217#if 0
4218 if ConditionPassed() then
4219 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4220 address = R[n] - 4*BitCount(registers);
4221
4222 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004223 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004224 if i == n && wback && i != LowestSetBit(registers) then
4225 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4226 else
4227 MemA[address,4] = R[i];
4228 address = address + 4;
4229
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004230 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004231 MemA[address,4] = PCStoreValue();
4232
4233 if wback then R[n] = R[n] - 4*BitCount(registers);
4234#endif
4235
4236
4237 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004238
Greg Clayton7bc39082011-03-24 23:53:38 +00004239 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004240 {
4241 uint32_t n;
4242 uint32_t registers = 0;
4243 bool wback;
4244 const uint32_t addr_byte_size = GetAddressByteSize();
4245
4246 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4247 switch (encoding)
4248 {
4249 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004250 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004251 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4252 {
4253 // See PUSH
4254 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004255 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004256 n = Bits32 (opcode, 19, 16);
4257 registers = Bits32 (opcode, 15, 0);
4258 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4259 wback = BitIsSet (opcode, 21);
4260 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4261 if ((n == 15) || BitCount (registers) < 2)
4262 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004263 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004264 if (wback && BitIsSet (registers, n))
4265 return false;
4266 break;
4267
4268 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00004269 // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004270 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4271 {
4272 // See Push
4273 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004274 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004275 n = Bits32 (opcode, 19, 16);
4276 registers = Bits32 (opcode, 15, 0);
4277 wback = BitIsSet (opcode, 21);
4278 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4279 if ((n == 15) || BitCount (registers) < 1)
4280 return false;
4281 break;
4282
4283 default:
4284 return false;
4285 }
4286
4287 // address = R[n] - 4*BitCount(registers);
4288
4289 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004290 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004291 if (!success)
4292 return false;
4293
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004294 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004295
4296 EmulateInstruction::Context context;
4297 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004298 RegisterInfo base_reg;
4299 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004300
4301 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004302 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004303 for (int i = 0; i < 14; ++i)
4304 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004305 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004306 if (BitIsSet (registers, i))
4307 {
4308 if (i < lowest_set_bit)
4309 lowest_set_bit = i;
4310 // if i == n && wback && i != LowestSetBit(registers) then
4311 if ((i == n) && wback && (i != lowest_set_bit))
4312 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4313 WriteBits32UnknownToMemory (address + offset);
4314 else
4315 {
4316 // MemA[address,4] = R[i];
4317 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4318 if (!success)
4319 return false;
4320
Greg Claytonc07d4512011-04-26 23:48:45 +00004321 RegisterInfo data_reg;
4322 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004323 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004324 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004325 return false;
4326 }
4327
4328 // address = address + 4;
4329 offset += addr_byte_size;
4330 }
4331 }
4332
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004333 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004334 // MemA[address,4] = PCStoreValue();
4335 if (BitIsSet (registers, 15))
4336 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004337 RegisterInfo pc_reg;
4338 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004339 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004340 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004341 if (!success)
4342 return false;
4343
Caroline Tice8d681f52011-03-17 23:50:16 +00004344 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004345 return false;
4346 }
4347
4348 // if wback then R[n] = R[n] - 4*BitCount(registers);
4349 if (wback)
4350 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004351 offset = (addr_byte_size * BitCount (registers)) * -1;
4352 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4353 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004354 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004355 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4356 return false;
4357 }
4358 }
4359 return true;
4360}
4361
4362// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4363// from a base register. The consecutive memory locations start just above this address, and the address of the last
4364// of those locations can optionally be written back to the base register.
4365bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004366EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004367{
4368#if 0
4369 if ConditionPassed() then
4370 EncodingSpecificOperations();
4371 address = R[n] + 4;
4372
4373 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004374 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004375 if i == n && wback && i != LowestSetBit(registers) then
4376 MemA[address,4] = bits(32) UNKNOWN;
4377 else
4378 MemA[address,4] = R[i];
4379 address = address + 4;
4380
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004381 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004382 MemA[address,4] = PCStoreValue();
4383
4384 if wback then R[n] = R[n] + 4*BitCount(registers);
4385#endif
4386
4387 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004388
Greg Clayton7bc39082011-03-24 23:53:38 +00004389 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004390 {
4391 uint32_t n;
4392 uint32_t registers = 0;
4393 bool wback;
4394 const uint32_t addr_byte_size = GetAddressByteSize();
4395
4396 // EncodingSpecificOperations();
4397 switch (encoding)
4398 {
4399 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004400 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004401 n = Bits32 (opcode, 19, 16);
4402 registers = Bits32 (opcode, 15, 0);
4403 wback = BitIsSet (opcode, 21);
4404
4405 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4406 if ((n == 15) && (BitCount (registers) < 1))
4407 return false;
4408 break;
4409 default:
4410 return false;
4411 }
4412 // address = R[n] + 4;
4413
4414 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004415 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004416 if (!success)
4417 return false;
4418
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004419 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004420
4421 EmulateInstruction::Context context;
4422 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004423 RegisterInfo base_reg;
4424 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004425
4426 uint32_t lowest_set_bit = 14;
4427 // for i = 0 to 14
4428 for (int i = 0; i < 14; ++i)
4429 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004430 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004431 if (BitIsSet (registers, i))
4432 {
4433 if (i < lowest_set_bit)
4434 lowest_set_bit = i;
4435 // if i == n && wback && i != LowestSetBit(registers) then
4436 if ((i == n) && wback && (i != lowest_set_bit))
4437 // MemA[address,4] = bits(32) UNKNOWN;
4438 WriteBits32UnknownToMemory (address + offset);
4439 // else
4440 else
4441 {
4442 // MemA[address,4] = R[i];
4443 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4444 if (!success)
4445 return false;
4446
Greg Claytonc07d4512011-04-26 23:48:45 +00004447 RegisterInfo data_reg;
4448 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004449 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004450 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004451 return false;
4452 }
4453
4454 // address = address + 4;
4455 offset += addr_byte_size;
4456 }
4457 }
4458
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004459 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004460 // MemA[address,4] = PCStoreValue();
4461 if (BitIsSet (registers, 15))
4462 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004463 RegisterInfo pc_reg;
4464 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004465 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004466 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004467 if (!success)
4468 return false;
4469
Caroline Tice8d681f52011-03-17 23:50:16 +00004470 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004471 return false;
4472 }
4473
4474 // if wback then R[n] = R[n] + 4*BitCount(registers);
4475 if (wback)
4476 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004477 offset = addr_byte_size * BitCount (registers);
4478 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4479 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004480 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004481 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4482 return false;
4483 }
4484 }
4485 return true;
4486}
Caroline Tice7fac8572011-02-15 22:53:54 +00004487
4488// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4489// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4490bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004491EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004492{
4493#if 0
4494 if ConditionPassed() then
4495 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4496 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4497 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004498 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004499 MemU[address,4] = R[t];
4500 else // Can only occur before ARMv7
4501 MemU[address,4] = bits(32) UNKNOWN;
4502 if wback then R[n] = offset_addr;
4503#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004504
Caroline Tice7fac8572011-02-15 22:53:54 +00004505 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004506
Greg Clayton7bc39082011-03-24 23:53:38 +00004507 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004508 {
4509 const uint32_t addr_byte_size = GetAddressByteSize();
4510
4511 uint32_t t;
4512 uint32_t n;
4513 uint32_t imm32;
4514 bool index;
4515 bool add;
4516 bool wback;
4517 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4518 switch (encoding)
4519 {
4520 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004521 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004522 t = Bits32 (opcode, 2, 0);
4523 n = Bits32 (opcode, 5, 3);
4524 imm32 = Bits32 (opcode, 10, 6) << 2;
4525
4526 // index = TRUE; add = TRUE; wback = FALSE;
4527 index = true;
4528 add = false;
4529 wback = false;
4530 break;
4531
4532 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004533 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004534 t = Bits32 (opcode, 10, 8);
4535 n = 13;
4536 imm32 = Bits32 (opcode, 7, 0) << 2;
4537
4538 // index = TRUE; add = TRUE; wback = FALSE;
4539 index = true;
4540 add = true;
4541 wback = false;
4542 break;
4543
4544 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004545 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004546 if (Bits32 (opcode, 19, 16) == 15)
4547 return false;
4548
4549 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4550 t = Bits32 (opcode, 15, 12);
4551 n = Bits32 (opcode, 19, 16);
4552 imm32 = Bits32 (opcode, 11, 0);
4553
4554 // index = TRUE; add = TRUE; wback = FALSE;
4555 index = true;
4556 add = true;
4557 wback = false;
4558
4559 // if t == 15 then UNPREDICTABLE;
4560 if (t == 15)
4561 return false;
4562 break;
4563
4564 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004565 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4566 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4567 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004568 if ((Bits32 (opcode, 19, 16) == 15)
4569 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4570 return false;
4571
4572 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4573 t = Bits32 (opcode, 15, 12);
4574 n = Bits32 (opcode, 19, 16);
4575 imm32 = Bits32 (opcode, 7, 0);
4576
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004577 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004578 index = BitIsSet (opcode, 10);
4579 add = BitIsSet (opcode, 9);
4580 wback = BitIsSet (opcode, 8);
4581
4582 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4583 if ((t == 15) || (wback && (n == t)))
4584 return false;
4585 break;
4586
4587 default:
4588 return false;
4589 }
4590
4591 addr_t offset_addr;
4592 addr_t address;
4593
4594 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004595 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004596 if (!success)
4597 return false;
4598
4599 if (add)
4600 offset_addr = base_address + imm32;
4601 else
4602 offset_addr = base_address - imm32;
4603
4604 // address = if index then offset_addr else R[n];
4605 if (index)
4606 address = offset_addr;
4607 else
4608 address = base_address;
4609
4610 EmulateInstruction::Context context;
4611 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004612 RegisterInfo base_reg;
4613 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004614
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004615 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004616 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4617 {
4618 // MemU[address,4] = R[t];
4619 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4620 if (!success)
4621 return false;
4622
Greg Claytonc07d4512011-04-26 23:48:45 +00004623 RegisterInfo data_reg;
4624 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004625 int32_t offset = address - base_address;
4626 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004627 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004628 return false;
4629 }
4630 else
4631 {
4632 // MemU[address,4] = bits(32) UNKNOWN;
4633 WriteBits32UnknownToMemory (address);
4634 }
4635
4636 // if wback then R[n] = offset_addr;
4637 if (wback)
4638 {
4639 context.type = eContextRegisterLoad;
4640 context.SetAddress (offset_addr);
4641 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4642 return false;
4643 }
4644 }
4645 return true;
4646}
Caroline Ticeaf556562011-02-15 18:42:15 +00004647
Caroline Tice3fd63e92011-02-16 00:33:43 +00004648// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4649// word from a register to memory. The offset register value can optionally be shifted.
4650bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004651EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004652{
4653#if 0
4654 if ConditionPassed() then
4655 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4656 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4657 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4658 address = if index then offset_addr else R[n];
4659 if t == 15 then // Only possible for encoding A1
4660 data = PCStoreValue();
4661 else
4662 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004663 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004664 MemU[address,4] = data;
4665 else // Can only occur before ARMv7
4666 MemU[address,4] = bits(32) UNKNOWN;
4667 if wback then R[n] = offset_addr;
4668#endif
4669
4670 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004671
Greg Clayton7bc39082011-03-24 23:53:38 +00004672 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004673 {
4674 const uint32_t addr_byte_size = GetAddressByteSize();
4675
4676 uint32_t t;
4677 uint32_t n;
4678 uint32_t m;
4679 ARM_ShifterType shift_t;
4680 uint32_t shift_n;
4681 bool index;
4682 bool add;
4683 bool wback;
4684
4685 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4686 switch (encoding)
4687 {
4688 case eEncodingT1:
4689 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4690 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4691 t = Bits32 (opcode, 2, 0);
4692 n = Bits32 (opcode, 5, 3);
4693 m = Bits32 (opcode, 8, 6);
4694
4695 // index = TRUE; add = TRUE; wback = FALSE;
4696 index = true;
4697 add = true;
4698 wback = false;
4699
4700 // (shift_t, shift_n) = (SRType_LSL, 0);
4701 shift_t = SRType_LSL;
4702 shift_n = 0;
4703 break;
4704
4705 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004706 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004707 if (Bits32 (opcode, 19, 16) == 15)
4708 return false;
4709
4710 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4711 t = Bits32 (opcode, 15, 12);
4712 n = Bits32 (opcode, 19, 16);
4713 m = Bits32 (opcode, 3, 0);
4714
4715 // index = TRUE; add = TRUE; wback = FALSE;
4716 index = true;
4717 add = true;
4718 wback = false;
4719
4720 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4721 shift_t = SRType_LSL;
4722 shift_n = Bits32 (opcode, 5, 4);
4723
4724 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4725 if ((t == 15) || (BadReg (m)))
4726 return false;
4727 break;
4728
4729 case eEncodingA1:
4730 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004731 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004732 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4733 t = Bits32 (opcode, 15, 12);
4734 n = Bits32 (opcode, 19, 16);
4735 m = Bits32 (opcode, 3, 0);
4736
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004737 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004738 index = BitIsSet (opcode, 24);
4739 add = BitIsSet (opcode, 23);
4740 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4741
4742 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4743 uint32_t typ = Bits32 (opcode, 6, 5);
4744 uint32_t imm5 = Bits32 (opcode, 11, 7);
4745 shift_n = DecodeImmShift(typ, imm5, shift_t);
4746
4747 // if m == 15 then UNPREDICTABLE;
4748 if (m == 15)
4749 return false;
4750
4751 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4752 if (wback && ((n == 15) || (n == t)))
4753 return false;
4754
4755 break;
4756 }
4757 default:
4758 return false;
4759 }
4760
4761 addr_t offset_addr;
4762 addr_t address;
4763 int32_t offset = 0;
4764
4765 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4766 if (!success)
4767 return false;
4768
4769 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4770 if (!success)
4771 return false;
4772
4773 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004774 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004775
4776 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4777 if (add)
4778 offset_addr = base_address + offset;
4779 else
4780 offset_addr = base_address - offset;
4781
4782 // address = if index then offset_addr else R[n];
4783 if (index)
4784 address = offset_addr;
4785 else
4786 address = base_address;
4787
4788 uint32_t data;
4789 // if t == 15 then // Only possible for encoding A1
4790 if (t == 15)
4791 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004792 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004793 else
4794 // data = R[t];
4795 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4796
4797 if (!success)
4798 return false;
4799
4800 EmulateInstruction::Context context;
4801 context.type = eContextRegisterStore;
4802
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004803 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004804 if (UnalignedSupport ()
4805 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4806 || CurrentInstrSet() == eModeARM)
4807 {
4808 // MemU[address,4] = data;
4809
Greg Claytonc07d4512011-04-26 23:48:45 +00004810 RegisterInfo base_reg;
4811 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004812
Greg Claytonc07d4512011-04-26 23:48:45 +00004813 RegisterInfo data_reg;
4814 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004815
4816 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004817 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004818 return false;
4819
4820 }
4821 else
4822 // MemU[address,4] = bits(32) UNKNOWN;
4823 WriteBits32UnknownToMemory (address);
4824
4825 // if wback then R[n] = offset_addr;
4826 if (wback)
4827 {
4828 context.type = eContextRegisterLoad;
4829 context.SetAddress (offset_addr);
4830 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4831 return false;
4832 }
4833
4834 }
4835 return true;
4836}
Caroline Tice73a29de2011-02-16 20:22:22 +00004837
4838bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004839EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004840{
4841#if 0
4842 if ConditionPassed() then
4843 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4844 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4845 address = if index then offset_addr else R[n];
4846 MemU[address,1] = R[t]<7:0>;
4847 if wback then R[n] = offset_addr;
4848#endif
4849
4850
4851 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004852
Greg Clayton7bc39082011-03-24 23:53:38 +00004853 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004854 {
4855 uint32_t t;
4856 uint32_t n;
4857 uint32_t imm32;
4858 bool index;
4859 bool add;
4860 bool wback;
4861 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4862 switch (encoding)
4863 {
4864 case eEncodingT1:
4865 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4866 t = Bits32 (opcode, 2, 0);
4867 n = Bits32 (opcode, 5, 3);
4868 imm32 = Bits32 (opcode, 10, 6);
4869
4870 // index = TRUE; add = TRUE; wback = FALSE;
4871 index = true;
4872 add = true;
4873 wback = false;
4874 break;
4875
4876 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004877 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004878 if (Bits32 (opcode, 19, 16) == 15)
4879 return false;
4880
4881 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4882 t = Bits32 (opcode, 15, 12);
4883 n = Bits32 (opcode, 19, 16);
4884 imm32 = Bits32 (opcode, 11, 0);
4885
4886 // index = TRUE; add = TRUE; wback = FALSE;
4887 index = true;
4888 add = true;
4889 wback = false;
4890
4891 // if BadReg(t) then UNPREDICTABLE;
4892 if (BadReg (t))
4893 return false;
4894 break;
4895
4896 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004897 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4898 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004899 if (Bits32 (opcode, 19, 16) == 15)
4900 return false;
4901
4902 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4903 t = Bits32 (opcode, 15, 12);
4904 n = Bits32 (opcode, 19, 16);
4905 imm32 = Bits32 (opcode, 7, 0);
4906
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004907 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004908 index = BitIsSet (opcode, 10);
4909 add = BitIsSet (opcode, 9);
4910 wback = BitIsSet (opcode, 8);
4911
4912 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4913 if ((BadReg (t)) || (wback && (n == t)))
4914 return false;
4915 break;
4916
4917 default:
4918 return false;
4919 }
4920
4921 addr_t offset_addr;
4922 addr_t address;
4923 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4924 if (!success)
4925 return false;
4926
4927 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4928 if (add)
4929 offset_addr = base_address + imm32;
4930 else
4931 offset_addr = base_address - imm32;
4932
4933 // address = if index then offset_addr else R[n];
4934 if (index)
4935 address = offset_addr;
4936 else
4937 address = base_address;
4938
Caroline Ticecc96eb52011-02-17 19:20:40 +00004939 // MemU[address,1] = R[t]<7:0>
Greg Claytonc07d4512011-04-26 23:48:45 +00004940 RegisterInfo base_reg;
4941 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004942
Greg Claytonc07d4512011-04-26 23:48:45 +00004943 RegisterInfo data_reg;
4944 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004945
4946 EmulateInstruction::Context context;
4947 context.type = eContextRegisterStore;
4948 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4949
4950 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4951 if (!success)
4952 return false;
4953
4954 data = Bits32 (data, 7, 0);
4955
Caroline Ticecc96eb52011-02-17 19:20:40 +00004956 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004957 return false;
4958
4959 // if wback then R[n] = offset_addr;
4960 if (wback)
4961 {
4962 context.type = eContextRegisterLoad;
4963 context.SetAddress (offset_addr);
4964 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4965 return false;
4966 }
4967
4968 }
4969
4970 return true;
4971}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004972
4973// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4974// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4975bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004976EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004977{
4978#if 0
4979 if ConditionPassed() then
4980 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4981 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4982 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4983 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004984 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004985 MemU[address,2] = R[t]<15:0>;
4986 else // Can only occur before ARMv7
4987 MemU[address,2] = bits(16) UNKNOWN;
4988 if wback then R[n] = offset_addr;
4989#endif
4990
4991 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004992
Greg Clayton7bc39082011-03-24 23:53:38 +00004993 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004994 {
4995 uint32_t t;
4996 uint32_t n;
4997 uint32_t m;
4998 bool index;
4999 bool add;
5000 bool wback;
5001 ARM_ShifterType shift_t;
5002 uint32_t shift_n;
5003
5004 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5005 switch (encoding)
5006 {
5007 case eEncodingT1:
5008 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5009 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5010 t = Bits32 (opcode, 2, 0);
5011 n = Bits32 (opcode, 5, 3);
5012 m = Bits32 (opcode, 8, 6);
5013
5014 // index = TRUE; add = TRUE; wback = FALSE;
5015 index = true;
5016 add = true;
5017 wback = false;
5018
5019 // (shift_t, shift_n) = (SRType_LSL, 0);
5020 shift_t = SRType_LSL;
5021 shift_n = 0;
5022
5023 break;
5024
5025 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005026 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005027 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5028 t = Bits32 (opcode, 15, 12);
5029 n = Bits32 (opcode, 19, 16);
5030 m = Bits32 (opcode, 3, 0);
5031 if (n == 15)
5032 return false;
5033
5034 // index = TRUE; add = TRUE; wback = FALSE;
5035 index = true;
5036 add = true;
5037 wback = false;
5038
5039 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5040 shift_t = SRType_LSL;
5041 shift_n = Bits32 (opcode, 5, 4);
5042
5043 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5044 if (BadReg (t) || BadReg (m))
5045 return false;
5046
5047 break;
5048
5049 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005050 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005051 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5052 t = Bits32 (opcode, 15, 12);
5053 n = Bits32 (opcode, 19, 16);
5054 m = Bits32 (opcode, 3, 0);
5055
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005056 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005057 index = BitIsSet (opcode, 24);
5058 add = BitIsSet (opcode, 23);
5059 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5060
5061 // (shift_t, shift_n) = (SRType_LSL, 0);
5062 shift_t = SRType_LSL;
5063 shift_n = 0;
5064
5065 // if t == 15 || m == 15 then UNPREDICTABLE;
5066 if ((t == 15) || (m == 15))
5067 return false;
5068
5069 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5070 if (wback && ((n == 15) || (n == t)))
5071 return false;
5072
5073 break;
5074
5075 default:
5076 return false;
5077 }
5078
5079 uint32_t Rm = ReadCoreReg (m, &success);
5080 if (!success)
5081 return false;
5082
5083 uint32_t Rn = ReadCoreReg (n, &success);
5084 if (!success)
5085 return false;
5086
5087 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5088 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5089
5090 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5091 addr_t offset_addr;
5092 if (add)
5093 offset_addr = Rn + offset;
5094 else
5095 offset_addr = Rn - offset;
5096
5097 // address = if index then offset_addr else R[n];
5098 addr_t address;
5099 if (index)
5100 address = offset_addr;
5101 else
5102 address = Rn;
5103
5104 EmulateInstruction::Context context;
5105 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005106 RegisterInfo base_reg;
5107 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5108 RegisterInfo offset_reg;
5109 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005110
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005111 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005112 if (UnalignedSupport() || BitIsClear (address, 0))
5113 {
5114 // MemU[address,2] = R[t]<15:0>;
5115 uint32_t Rt = ReadCoreReg (t, &success);
5116 if (!success)
5117 return false;
5118
5119 EmulateInstruction::Context context;
5120 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005121 RegisterInfo base_reg;
5122 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5123 RegisterInfo offset_reg;
5124 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5125 RegisterInfo data_reg;
5126 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005127 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5128
5129 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5130 return false;
5131 }
5132 else // Can only occur before ARMv7
5133 {
5134 // MemU[address,2] = bits(16) UNKNOWN;
5135 }
5136
5137 // if wback then R[n] = offset_addr;
5138 if (wback)
5139 {
5140 context.type = eContextAdjustBaseRegister;
5141 context.SetAddress (offset_addr);
5142 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5143 return false;
5144 }
5145 }
5146
5147 return true;
5148}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005149
Johnny Chen157b9592011-02-18 21:13:05 +00005150// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5151// and writes the result to the destination register. It can optionally update the condition flags
5152// based on the result.
5153bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005154EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005155{
5156#if 0
5157 // ARM pseudo code...
5158 if ConditionPassed() then
5159 EncodingSpecificOperations();
5160 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5161 if d == 15 then // Can only occur for ARM encoding
5162 ALUWritePC(result); // setflags is always FALSE here
5163 else
5164 R[d] = result;
5165 if setflags then
5166 APSR.N = result<31>;
5167 APSR.Z = IsZeroBit(result);
5168 APSR.C = carry;
5169 APSR.V = overflow;
5170#endif
5171
5172 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005173
Greg Clayton7bc39082011-03-24 23:53:38 +00005174 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005175 {
5176 uint32_t Rd, Rn;
5177 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5178 bool setflags;
5179 switch (encoding)
5180 {
5181 case eEncodingT1:
5182 Rd = Bits32(opcode, 11, 8);
5183 Rn = Bits32(opcode, 19, 16);
5184 setflags = BitIsSet(opcode, 20);
5185 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5186 if (BadReg(Rd) || BadReg(Rn))
5187 return false;
5188 break;
5189 case eEncodingA1:
5190 Rd = Bits32(opcode, 15, 12);
5191 Rn = Bits32(opcode, 19, 16);
5192 setflags = BitIsSet(opcode, 20);
5193 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005194
Johnny Chen157b9592011-02-18 21:13:05 +00005195 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005196 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005197 break;
5198 default:
5199 return false;
5200 }
5201
5202 // Read the first operand.
5203 int32_t val1 = ReadCoreReg(Rn, &success);
5204 if (!success)
5205 return false;
5206
5207 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5208
5209 EmulateInstruction::Context context;
5210 context.type = EmulateInstruction::eContextImmediate;
5211 context.SetNoArgs ();
5212
5213 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5214 return false;
5215 }
5216 return true;
5217}
5218
5219// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5220// register value, and writes the result to the destination register. It can optionally update the
5221// condition flags based on the result.
5222bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005223EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005224{
5225#if 0
5226 // ARM pseudo code...
5227 if ConditionPassed() then
5228 EncodingSpecificOperations();
5229 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5230 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5231 if d == 15 then // Can only occur for ARM encoding
5232 ALUWritePC(result); // setflags is always FALSE here
5233 else
5234 R[d] = result;
5235 if setflags then
5236 APSR.N = result<31>;
5237 APSR.Z = IsZeroBit(result);
5238 APSR.C = carry;
5239 APSR.V = overflow;
5240#endif
5241
5242 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005243
Greg Clayton7bc39082011-03-24 23:53:38 +00005244 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005245 {
5246 uint32_t Rd, Rn, Rm;
5247 ARM_ShifterType shift_t;
5248 uint32_t shift_n; // the shift applied to the value read from Rm
5249 bool setflags;
5250 switch (encoding)
5251 {
5252 case eEncodingT1:
5253 Rd = Rn = Bits32(opcode, 2, 0);
5254 Rm = Bits32(opcode, 5, 3);
5255 setflags = !InITBlock();
5256 shift_t = SRType_LSL;
5257 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005258 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005259 case eEncodingT2:
5260 Rd = Bits32(opcode, 11, 8);
5261 Rn = Bits32(opcode, 19, 16);
5262 Rm = Bits32(opcode, 3, 0);
5263 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005264 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005265 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5266 return false;
5267 break;
5268 case eEncodingA1:
5269 Rd = Bits32(opcode, 15, 12);
5270 Rn = Bits32(opcode, 19, 16);
5271 Rm = Bits32(opcode, 3, 0);
5272 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005273 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005274
Johnny Chen157b9592011-02-18 21:13:05 +00005275 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005276 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005277 break;
5278 default:
5279 return false;
5280 }
5281
5282 // Read the first operand.
5283 int32_t val1 = ReadCoreReg(Rn, &success);
5284 if (!success)
5285 return false;
5286
5287 // Read the second operand.
5288 int32_t val2 = ReadCoreReg(Rm, &success);
5289 if (!success)
5290 return false;
5291
5292 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5293 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5294
5295 EmulateInstruction::Context context;
5296 context.type = EmulateInstruction::eContextImmediate;
5297 context.SetNoArgs ();
5298
5299 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5300 return false;
5301 }
5302 return true;
5303}
5304
Johnny Chena695f952011-02-23 21:24:25 +00005305// This instruction adds an immediate value to the PC value to form a PC-relative address,
5306// and writes the result to the destination register.
5307bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005308EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005309{
5310#if 0
5311 // ARM pseudo code...
5312 if ConditionPassed() then
5313 EncodingSpecificOperations();
5314 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5315 if d == 15 then // Can only occur for ARM encodings
5316 ALUWritePC(result);
5317 else
5318 R[d] = result;
5319#endif
5320
5321 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005322
Greg Clayton7bc39082011-03-24 23:53:38 +00005323 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005324 {
5325 uint32_t Rd;
5326 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5327 bool add;
5328 switch (encoding)
5329 {
5330 case eEncodingT1:
5331 Rd = Bits32(opcode, 10, 8);
5332 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5333 break;
5334 case eEncodingT2:
5335 case eEncodingT3:
5336 Rd = Bits32(opcode, 11, 8);
5337 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5338 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5339 if (BadReg(Rd))
5340 return false;
5341 break;
5342 case eEncodingA1:
5343 case eEncodingA2:
5344 Rd = Bits32(opcode, 15, 12);
5345 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5346 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5347 break;
5348 default:
5349 return false;
5350 }
5351
5352 // Read the PC value.
5353 uint32_t pc = ReadCoreReg(PC_REG, &success);
5354 if (!success)
5355 return false;
5356
5357 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5358
5359 EmulateInstruction::Context context;
5360 context.type = EmulateInstruction::eContextImmediate;
5361 context.SetNoArgs ();
5362
5363 if (!WriteCoreReg(context, result, Rd))
5364 return false;
5365 }
5366 return true;
5367}
5368
Johnny Chene97c0d52011-02-18 19:32:20 +00005369// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5370// to the destination register. It can optionally update the condition flags based on the result.
5371bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005372EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005373{
5374#if 0
5375 // ARM pseudo code...
5376 if ConditionPassed() then
5377 EncodingSpecificOperations();
5378 result = R[n] AND imm32;
5379 if d == 15 then // Can only occur for ARM encoding
5380 ALUWritePC(result); // setflags is always FALSE here
5381 else
5382 R[d] = result;
5383 if setflags then
5384 APSR.N = result<31>;
5385 APSR.Z = IsZeroBit(result);
5386 APSR.C = carry;
5387 // APSR.V unchanged
5388#endif
5389
5390 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005391
Greg Clayton7bc39082011-03-24 23:53:38 +00005392 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005393 {
5394 uint32_t Rd, Rn;
5395 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5396 bool setflags;
5397 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5398 switch (encoding)
5399 {
5400 case eEncodingT1:
5401 Rd = Bits32(opcode, 11, 8);
5402 Rn = Bits32(opcode, 19, 16);
5403 setflags = BitIsSet(opcode, 20);
5404 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005405 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005406 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005407 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005408 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5409 return false;
5410 break;
5411 case eEncodingA1:
5412 Rd = Bits32(opcode, 15, 12);
5413 Rn = Bits32(opcode, 19, 16);
5414 setflags = BitIsSet(opcode, 20);
5415 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005416
Johnny Chene97c0d52011-02-18 19:32:20 +00005417 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005418 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005419 break;
5420 default:
5421 return false;
5422 }
5423
Johnny Chene97c0d52011-02-18 19:32:20 +00005424 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005425 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005426 if (!success)
5427 return false;
5428
5429 uint32_t result = val1 & imm32;
5430
5431 EmulateInstruction::Context context;
5432 context.type = EmulateInstruction::eContextImmediate;
5433 context.SetNoArgs ();
5434
5435 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5436 return false;
5437 }
5438 return true;
5439}
5440
5441// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5442// and writes the result to the destination register. It can optionally update the condition flags
5443// based on the result.
5444bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005445EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005446{
5447#if 0
5448 // ARM pseudo code...
5449 if ConditionPassed() then
5450 EncodingSpecificOperations();
5451 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5452 result = R[n] AND shifted;
5453 if d == 15 then // Can only occur for ARM encoding
5454 ALUWritePC(result); // setflags is always FALSE here
5455 else
5456 R[d] = result;
5457 if setflags then
5458 APSR.N = result<31>;
5459 APSR.Z = IsZeroBit(result);
5460 APSR.C = carry;
5461 // APSR.V unchanged
5462#endif
5463
5464 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005465
Greg Clayton7bc39082011-03-24 23:53:38 +00005466 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005467 {
5468 uint32_t Rd, Rn, Rm;
5469 ARM_ShifterType shift_t;
5470 uint32_t shift_n; // the shift applied to the value read from Rm
5471 bool setflags;
5472 uint32_t carry;
5473 switch (encoding)
5474 {
5475 case eEncodingT1:
5476 Rd = Rn = Bits32(opcode, 2, 0);
5477 Rm = Bits32(opcode, 5, 3);
5478 setflags = !InITBlock();
5479 shift_t = SRType_LSL;
5480 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005481 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005482 case eEncodingT2:
5483 Rd = Bits32(opcode, 11, 8);
5484 Rn = Bits32(opcode, 19, 16);
5485 Rm = Bits32(opcode, 3, 0);
5486 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005487 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005488 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005489 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005490 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005491 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5492 return false;
5493 break;
5494 case eEncodingA1:
5495 Rd = Bits32(opcode, 15, 12);
5496 Rn = Bits32(opcode, 19, 16);
5497 Rm = Bits32(opcode, 3, 0);
5498 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005499 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005500
Johnny Chene97c0d52011-02-18 19:32:20 +00005501 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005502 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005503 break;
5504 default:
5505 return false;
5506 }
5507
Johnny Chene97c0d52011-02-18 19:32:20 +00005508 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005509 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005510 if (!success)
5511 return false;
5512
5513 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005514 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005515 if (!success)
5516 return false;
5517
5518 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5519 uint32_t result = val1 & shifted;
5520
5521 EmulateInstruction::Context context;
5522 context.type = EmulateInstruction::eContextImmediate;
5523 context.SetNoArgs ();
5524
5525 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5526 return false;
5527 }
5528 return true;
5529}
5530
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005531// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5532// immediate value, and writes the result to the destination register. It can optionally update the
5533// condition flags based on the result.
5534bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005535EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005536{
5537#if 0
5538 // ARM pseudo code...
5539 if ConditionPassed() then
5540 EncodingSpecificOperations();
5541 result = R[n] AND NOT(imm32);
5542 if d == 15 then // Can only occur for ARM encoding
5543 ALUWritePC(result); // setflags is always FALSE here
5544 else
5545 R[d] = result;
5546 if setflags then
5547 APSR.N = result<31>;
5548 APSR.Z = IsZeroBit(result);
5549 APSR.C = carry;
5550 // APSR.V unchanged
5551#endif
5552
5553 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005554
Greg Clayton7bc39082011-03-24 23:53:38 +00005555 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005556 {
5557 uint32_t Rd, Rn;
5558 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5559 bool setflags;
5560 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5561 switch (encoding)
5562 {
5563 case eEncodingT1:
5564 Rd = Bits32(opcode, 11, 8);
5565 Rn = Bits32(opcode, 19, 16);
5566 setflags = BitIsSet(opcode, 20);
5567 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5568 if (BadReg(Rd) || BadReg(Rn))
5569 return false;
5570 break;
5571 case eEncodingA1:
5572 Rd = Bits32(opcode, 15, 12);
5573 Rn = Bits32(opcode, 19, 16);
5574 setflags = BitIsSet(opcode, 20);
5575 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005576
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005577 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005578 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005579 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005580 break;
5581 default:
5582 return false;
5583 }
5584
5585 // Read the first operand.
5586 uint32_t val1 = ReadCoreReg(Rn, &success);
5587 if (!success)
5588 return false;
5589
5590 uint32_t result = val1 & ~imm32;
5591
5592 EmulateInstruction::Context context;
5593 context.type = EmulateInstruction::eContextImmediate;
5594 context.SetNoArgs ();
5595
5596 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5597 return false;
5598 }
5599 return true;
5600}
5601
5602// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5603// optionally-shifted register value, and writes the result to the destination register.
5604// It can optionally update the condition flags based on the result.
5605bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005606EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005607{
5608#if 0
5609 // ARM pseudo code...
5610 if ConditionPassed() then
5611 EncodingSpecificOperations();
5612 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5613 result = R[n] AND NOT(shifted);
5614 if d == 15 then // Can only occur for ARM encoding
5615 ALUWritePC(result); // setflags is always FALSE here
5616 else
5617 R[d] = result;
5618 if setflags then
5619 APSR.N = result<31>;
5620 APSR.Z = IsZeroBit(result);
5621 APSR.C = carry;
5622 // APSR.V unchanged
5623#endif
5624
5625 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005626
Greg Clayton7bc39082011-03-24 23:53:38 +00005627 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005628 {
5629 uint32_t Rd, Rn, Rm;
5630 ARM_ShifterType shift_t;
5631 uint32_t shift_n; // the shift applied to the value read from Rm
5632 bool setflags;
5633 uint32_t carry;
5634 switch (encoding)
5635 {
5636 case eEncodingT1:
5637 Rd = Rn = Bits32(opcode, 2, 0);
5638 Rm = Bits32(opcode, 5, 3);
5639 setflags = !InITBlock();
5640 shift_t = SRType_LSL;
5641 shift_n = 0;
5642 break;
5643 case eEncodingT2:
5644 Rd = Bits32(opcode, 11, 8);
5645 Rn = Bits32(opcode, 19, 16);
5646 Rm = Bits32(opcode, 3, 0);
5647 setflags = BitIsSet(opcode, 20);
5648 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5649 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5650 return false;
5651 break;
5652 case eEncodingA1:
5653 Rd = Bits32(opcode, 15, 12);
5654 Rn = Bits32(opcode, 19, 16);
5655 Rm = Bits32(opcode, 3, 0);
5656 setflags = BitIsSet(opcode, 20);
5657 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005658
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005659 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005660 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005661 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005662 break;
5663 default:
5664 return false;
5665 }
5666
5667 // Read the first operand.
5668 uint32_t val1 = ReadCoreReg(Rn, &success);
5669 if (!success)
5670 return false;
5671
5672 // Read the second operand.
5673 uint32_t val2 = ReadCoreReg(Rm, &success);
5674 if (!success)
5675 return false;
5676
5677 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5678 uint32_t result = val1 & ~shifted;
5679
5680 EmulateInstruction::Context context;
5681 context.type = EmulateInstruction::eContextImmediate;
5682 context.SetNoArgs ();
5683
5684 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5685 return false;
5686 }
5687 return true;
5688}
5689
Caroline Tice4d729c52011-02-18 00:55:53 +00005690// 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 +00005691// 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 +00005692bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005693EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005694{
5695#if 0
5696 if ConditionPassed() then
5697 EncodingSpecificOperations();
5698 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5699 address = if index then offset_addr else R[n];
5700 data = MemU[address,4];
5701 if wback then R[n] = offset_addr;
5702 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005703 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5704 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005705 R[t] = data;
5706 else // Can only apply before ARMv7
5707 R[t] = ROR(data, 8*UInt(address<1:0>));
5708#endif
5709
5710 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005711
Greg Clayton7bc39082011-03-24 23:53:38 +00005712 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005713 {
5714 const uint32_t addr_byte_size = GetAddressByteSize();
5715
5716 uint32_t t;
5717 uint32_t n;
5718 uint32_t imm32;
5719 bool index;
5720 bool add;
5721 bool wback;
5722
5723 switch (encoding)
5724 {
5725 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005726 // if Rn == '1111' then SEE LDR (literal);
5727 // if P == '0' && W == '1' then SEE LDRT;
5728 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005729 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5730 t = Bits32 (opcode, 15, 12);
5731 n = Bits32 (opcode, 19, 16);
5732 imm32 = Bits32 (opcode, 11, 0);
5733
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005734 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5735 index = BitIsSet (opcode, 24);
5736 add = BitIsSet (opcode, 23);
5737 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005738
5739 // if wback && n == t then UNPREDICTABLE;
5740 if (wback && (n == t))
5741 return false;
5742
5743 break;
5744
5745 default:
5746 return false;
5747 }
5748
5749 addr_t address;
5750 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005751 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005752 if (!success)
5753 return false;
5754
5755 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5756 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005757 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005758 else
5759 offset_addr = base_address - imm32;
5760
5761 // address = if index then offset_addr else R[n];
5762 if (index)
5763 address = offset_addr;
5764 else
5765 address = base_address;
5766
5767 // data = MemU[address,4];
5768
Greg Claytonc07d4512011-04-26 23:48:45 +00005769 RegisterInfo base_reg;
5770 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4d729c52011-02-18 00:55:53 +00005771
5772 EmulateInstruction::Context context;
5773 context.type = eContextRegisterLoad;
5774 context.SetRegisterPlusOffset (base_reg, address - base_address);
5775
5776 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5777 if (!success)
5778 return false;
5779
5780 // if wback then R[n] = offset_addr;
5781 if (wback)
5782 {
5783 context.type = eContextAdjustBaseRegister;
5784 context.SetAddress (offset_addr);
5785 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5786 return false;
5787 }
5788
5789 // if t == 15 then
5790 if (t == 15)
5791 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005792 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005793 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5794 {
5795 // LoadWritePC (data);
5796 context.type = eContextRegisterLoad;
5797 context.SetRegisterPlusOffset (base_reg, address - base_address);
5798 LoadWritePC (context, data);
5799 }
5800 else
5801 return false;
5802 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005803 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005804 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5805 {
5806 // R[t] = data;
5807 context.type = eContextRegisterLoad;
5808 context.SetRegisterPlusOffset (base_reg, address - base_address);
5809 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5810 return false;
5811 }
5812 // else // Can only apply before ARMv7
5813 else
5814 {
5815 // R[t] = ROR(data, 8*UInt(address<1:0>));
5816 data = ROR (data, Bits32 (address, 1, 0));
5817 context.type = eContextRegisterLoad;
5818 context.SetImmediate (data);
5819 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5820 return false;
5821 }
5822
5823 }
5824 return true;
5825}
5826
Caroline Ticefe479112011-02-18 18:52:37 +00005827// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5828// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5829bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005830EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005831{
5832#if 0
5833 if ConditionPassed() then
5834 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5835 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5836 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5837 address = if index then offset_addr else R[n];
5838 data = MemU[address,4];
5839 if wback then R[n] = offset_addr;
5840 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005841 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5842 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005843 R[t] = data;
5844 else // Can only apply before ARMv7
5845 if CurrentInstrSet() == InstrSet_ARM then
5846 R[t] = ROR(data, 8*UInt(address<1:0>));
5847 else
5848 R[t] = bits(32) UNKNOWN;
5849#endif
5850
5851 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005852
Greg Clayton7bc39082011-03-24 23:53:38 +00005853 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005854 {
5855 const uint32_t addr_byte_size = GetAddressByteSize();
5856
5857 uint32_t t;
5858 uint32_t n;
5859 uint32_t m;
5860 bool index;
5861 bool add;
5862 bool wback;
5863 ARM_ShifterType shift_t;
5864 uint32_t shift_n;
5865
5866 switch (encoding)
5867 {
5868 case eEncodingT1:
5869 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5870 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5871 t = Bits32 (opcode, 2, 0);
5872 n = Bits32 (opcode, 5, 3);
5873 m = Bits32 (opcode, 8, 6);
5874
5875 // index = TRUE; add = TRUE; wback = FALSE;
5876 index = true;
5877 add = true;
5878 wback = false;
5879
5880 // (shift_t, shift_n) = (SRType_LSL, 0);
5881 shift_t = SRType_LSL;
5882 shift_n = 0;
5883
5884 break;
5885
5886 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005887 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005888 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5889 t = Bits32 (opcode, 15, 12);
5890 n = Bits32 (opcode, 19, 16);
5891 m = Bits32 (opcode, 3, 0);
5892
5893 // index = TRUE; add = TRUE; wback = FALSE;
5894 index = true;
5895 add = true;
5896 wback = false;
5897
5898 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5899 shift_t = SRType_LSL;
5900 shift_n = Bits32 (opcode, 5, 4);
5901
5902 // if BadReg(m) then UNPREDICTABLE;
5903 if (BadReg (m))
5904 return false;
5905
5906 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5907 if ((t == 15) && InITBlock() && !LastInITBlock())
5908 return false;
5909
5910 break;
5911
5912 case eEncodingA1:
5913 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005914 // if P == '0' && W == '1' then SEE LDRT;
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
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005920 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005921 index = BitIsSet (opcode, 24);
5922 add = BitIsSet (opcode, 23);
5923 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5924
5925 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5926 uint32_t type = Bits32 (opcode, 6, 5);
5927 uint32_t imm5 = Bits32 (opcode, 11, 7);
5928 shift_n = DecodeImmShift (type, imm5, shift_t);
5929
5930 // if m == 15 then UNPREDICTABLE;
5931 if (m == 15)
5932 return false;
5933
5934 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5935 if (wback && ((n == 15) || (n == t)))
5936 return false;
5937 }
5938 break;
5939
5940
5941 default:
5942 return false;
5943 }
5944
5945 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5946 if (!success)
5947 return false;
5948
5949 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5950 if (!success)
5951 return false;
5952
5953 addr_t offset_addr;
5954 addr_t address;
5955
5956 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Greg Claytonb3448432011-03-24 21:19:54 +00005957 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005958
5959 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5960 if (add)
5961 offset_addr = Rn + offset;
5962 else
5963 offset_addr = Rn - offset;
5964
5965 // address = if index then offset_addr else R[n];
5966 if (index)
5967 address = offset_addr;
5968 else
5969 address = Rn;
5970
5971 // data = MemU[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +00005972 RegisterInfo base_reg;
5973 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefe479112011-02-18 18:52:37 +00005974
5975 EmulateInstruction::Context context;
5976 context.type = eContextRegisterLoad;
5977 context.SetRegisterPlusOffset (base_reg, address - Rn);
5978
5979 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5980 if (!success)
5981 return false;
5982
5983 // if wback then R[n] = offset_addr;
5984 if (wback)
5985 {
5986 context.type = eContextAdjustBaseRegister;
5987 context.SetAddress (offset_addr);
5988 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5989 return false;
5990 }
5991
5992 // if t == 15 then
5993 if (t == 15)
5994 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005995 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005996 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5997 {
5998 context.type = eContextRegisterLoad;
5999 context.SetRegisterPlusOffset (base_reg, address - Rn);
6000 LoadWritePC (context, data);
6001 }
6002 else
6003 return false;
6004 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006005 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00006006 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
6007 {
6008 // R[t] = data;
6009 context.type = eContextRegisterLoad;
6010 context.SetRegisterPlusOffset (base_reg, address - Rn);
6011 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6012 return false;
6013 }
6014 else // Can only apply before ARMv7
6015 {
6016 // if CurrentInstrSet() == InstrSet_ARM then
6017 if (CurrentInstrSet () == eModeARM)
6018 {
6019 // R[t] = ROR(data, 8*UInt(address<1:0>));
6020 data = ROR (data, Bits32 (address, 1, 0));
6021 context.type = eContextRegisterLoad;
6022 context.SetImmediate (data);
6023 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6024 return false;
6025 }
6026 else
6027 {
6028 // R[t] = bits(32) UNKNOWN;
6029 WriteBits32Unknown (t);
6030 }
6031 }
6032 }
6033 return true;
6034}
Caroline Tice21b604b2011-02-18 21:06:04 +00006035
6036// LDRB (immediate, Thumb)
6037bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006038EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00006039{
6040#if 0
6041 if ConditionPassed() then
6042 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6043 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6044 address = if index then offset_addr else R[n];
6045 R[t] = ZeroExtend(MemU[address,1], 32);
6046 if wback then R[n] = offset_addr;
6047#endif
6048
6049 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00006050
Greg Clayton7bc39082011-03-24 23:53:38 +00006051 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00006052 {
6053 uint32_t t;
6054 uint32_t n;
6055 uint32_t imm32;
6056 bool index;
6057 bool add;
6058 bool wback;
6059
6060 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6061 switch (encoding)
6062 {
6063 case eEncodingT1:
6064 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6065 t = Bits32 (opcode, 2, 0);
6066 n = Bits32 (opcode, 5, 3);
6067 imm32 = Bits32 (opcode, 10, 6);
6068
6069 // index = TRUE; add = TRUE; wback = FALSE;
6070 index = true;
6071 add = true;
6072 wback= false;
6073
6074 break;
6075
6076 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006077 // if Rt == '1111' then SEE PLD;
6078 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006079 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6080 t = Bits32 (opcode, 15, 12);
6081 n = Bits32 (opcode, 19, 16);
6082 imm32 = Bits32 (opcode, 11, 0);
6083
6084 // index = TRUE; add = TRUE; wback = FALSE;
6085 index = true;
6086 add = true;
6087 wback = false;
6088
6089 // if t == 13 then UNPREDICTABLE;
6090 if (t == 13)
6091 return false;
6092
6093 break;
6094
6095 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006096 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6097 // if Rn == '1111' then SEE LDRB (literal);
6098 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6099 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006100 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6101 return false;
6102
6103 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6104 t = Bits32 (opcode, 15, 12);
6105 n = Bits32 (opcode, 19, 16);
6106 imm32 = Bits32 (opcode, 7, 0);
6107
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006108 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006109 index = BitIsSet (opcode, 10);
6110 add = BitIsSet (opcode, 9);
6111 wback = BitIsSet (opcode, 8);
6112
6113 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6114 if (BadReg (t) || (wback && (n == t)))
6115 return false;
6116
6117 break;
6118
6119 default:
6120 return false;
6121 }
6122
6123 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6124 if (!success)
6125 return false;
6126
6127 addr_t address;
6128 addr_t offset_addr;
6129
6130 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6131 if (add)
6132 offset_addr = Rn + imm32;
6133 else
6134 offset_addr = Rn - imm32;
6135
6136 // address = if index then offset_addr else R[n];
6137 if (index)
6138 address = offset_addr;
6139 else
6140 address = Rn;
6141
6142 // R[t] = ZeroExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006143 RegisterInfo base_reg;
6144 RegisterInfo data_reg;
6145 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6146 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice21b604b2011-02-18 21:06:04 +00006147
6148 EmulateInstruction::Context context;
6149 context.type = eContextRegisterLoad;
6150 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6151
6152 uint64_t data = MemURead (context, address, 1, 0, &success);
6153 if (!success)
6154 return false;
6155
6156 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6157 return false;
6158
6159 // if wback then R[n] = offset_addr;
6160 if (wback)
6161 {
6162 context.type = eContextAdjustBaseRegister;
6163 context.SetAddress (offset_addr);
6164 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6165 return false;
6166 }
6167 }
6168 return true;
6169}
Caroline Ticef55261f2011-02-18 22:24:22 +00006170
6171// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6172// zero-extends it to form a 32-bit word and writes it to a register.
6173bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006174EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006175{
6176#if 0
6177 if ConditionPassed() then
6178 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6179 base = Align(PC,4);
6180 address = if add then (base + imm32) else (base - imm32);
6181 R[t] = ZeroExtend(MemU[address,1], 32);
6182#endif
6183
6184 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006185
Greg Clayton7bc39082011-03-24 23:53:38 +00006186 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006187 {
6188 uint32_t t;
6189 uint32_t imm32;
6190 bool add;
6191 switch (encoding)
6192 {
6193 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006194 // if Rt == '1111' then SEE PLD;
6195 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006196 t = Bits32 (opcode, 15, 12);
6197 imm32 = Bits32 (opcode, 11, 0);
6198 add = BitIsSet (opcode, 23);
6199
6200 // if t == 13 then UNPREDICTABLE;
6201 if (t == 13)
6202 return false;
6203
6204 break;
6205
6206 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006207 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006208 t = Bits32 (opcode, 15, 12);
6209 imm32 = Bits32 (opcode, 11, 0);
6210 add = BitIsSet (opcode, 23);
6211
6212 // if t == 15 then UNPREDICTABLE;
6213 if (t == 15)
6214 return false;
6215 break;
6216
6217 default:
6218 return false;
6219 }
6220
6221 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006222 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006223 if (!success)
6224 return false;
6225
6226 uint32_t base = AlignPC (pc_val);
6227
6228 addr_t address;
6229 // address = if add then (base + imm32) else (base - imm32);
6230 if (add)
6231 address = base + imm32;
6232 else
6233 address = base - imm32;
6234
6235 // R[t] = ZeroExtend(MemU[address,1], 32);
6236 EmulateInstruction::Context context;
6237 context.type = eContextRelativeBranchImmediate;
6238 context.SetImmediate (address - base);
6239
6240 uint64_t data = MemURead (context, address, 1, 0, &success);
6241 if (!success)
6242 return false;
6243
6244 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6245 return false;
6246 }
6247 return true;
6248}
Caroline Tice30fec122011-02-18 23:52:21 +00006249
6250// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6251// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6252// optionally be shifted.
6253bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006254EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006255{
6256#if 0
6257 if ConditionPassed() then
6258 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6259 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6260 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6261 address = if index then offset_addr else R[n];
6262 R[t] = ZeroExtend(MemU[address,1],32);
6263 if wback then R[n] = offset_addr;
6264#endif
6265
6266 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006267
Greg Clayton7bc39082011-03-24 23:53:38 +00006268 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006269 {
6270 uint32_t t;
6271 uint32_t n;
6272 uint32_t m;
6273 bool index;
6274 bool add;
6275 bool wback;
6276 ARM_ShifterType shift_t;
6277 uint32_t shift_n;
6278
6279 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6280 switch (encoding)
6281 {
6282 case eEncodingT1:
6283 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6284 t = Bits32 (opcode, 2, 0);
6285 n = Bits32 (opcode, 5, 3);
6286 m = Bits32 (opcode, 8, 6);
6287
6288 // index = TRUE; add = TRUE; wback = FALSE;
6289 index = true;
6290 add = true;
6291 wback = false;
6292
6293 // (shift_t, shift_n) = (SRType_LSL, 0);
6294 shift_t = SRType_LSL;
6295 shift_n = 0;
6296 break;
6297
6298 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006299 // if Rt == '1111' then SEE PLD;
6300 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006301 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6302 t = Bits32 (opcode, 15, 12);
6303 n = Bits32 (opcode, 19, 16);
6304 m = Bits32 (opcode, 3, 0);
6305
6306 // index = TRUE; add = TRUE; wback = FALSE;
6307 index = true;
6308 add = true;
6309 wback = false;
6310
6311 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6312 shift_t = SRType_LSL;
6313 shift_n = Bits32 (opcode, 5, 4);
6314
6315 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6316 if ((t == 13) || BadReg (m))
6317 return false;
6318 break;
6319
6320 case eEncodingA1:
6321 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006322 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006323 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6324 t = Bits32 (opcode, 15, 12);
6325 n = Bits32 (opcode, 19, 16);
6326 m = Bits32 (opcode, 3, 0);
6327
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006328 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006329 index = BitIsSet (opcode, 24);
6330 add = BitIsSet (opcode, 23);
6331 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6332
6333 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6334 uint32_t type = Bits32 (opcode, 6, 5);
6335 uint32_t imm5 = Bits32 (opcode, 11, 7);
6336 shift_n = DecodeImmShift (type, imm5, shift_t);
6337
6338 // if t == 15 || m == 15 then UNPREDICTABLE;
6339 if ((t == 15) || (m == 15))
6340 return false;
6341
6342 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6343 if (wback && ((n == 15) || (n == t)))
6344 return false;
6345 }
6346 break;
6347
6348 default:
6349 return false;
6350 }
6351
6352 addr_t offset_addr;
6353 addr_t address;
6354
6355 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6356 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6357 if (!success)
6358 return false;
6359
6360 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6361
6362 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6363 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6364 if (!success)
6365 return false;
6366
6367 if (add)
6368 offset_addr = Rn + offset;
6369 else
6370 offset_addr = Rn - offset;
6371
6372 // address = if index then offset_addr else R[n];
6373 if (index)
6374 address = offset_addr;
6375 else
6376 address = Rn;
6377
6378 // R[t] = ZeroExtend(MemU[address,1],32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006379 RegisterInfo base_reg;
6380 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice30fec122011-02-18 23:52:21 +00006381
6382 EmulateInstruction::Context context;
6383 context.type = eContextRegisterLoad;
6384 context.SetRegisterPlusOffset (base_reg, address - Rn);
6385
6386 uint64_t data = MemURead (context, address, 1, 0, &success);
6387 if (!success)
6388 return false;
6389
6390 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6391 return false;
6392
6393 // if wback then R[n] = offset_addr;
6394 if (wback)
6395 {
6396 context.type = eContextAdjustBaseRegister;
6397 context.SetAddress (offset_addr);
6398 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6399 return false;
6400 }
6401 }
6402 return true;
6403}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006404
6405// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6406// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6407// post-indexed, or pre-indexed addressing.
6408bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006409EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006410{
6411#if 0
6412 if ConditionPassed() then
6413 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6414 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6415 address = if index then offset_addr else R[n];
6416 data = MemU[address,2];
6417 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006418 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006419 R[t] = ZeroExtend(data, 32);
6420 else // Can only apply before ARMv7
6421 R[t] = bits(32) UNKNOWN;
6422#endif
6423
6424
6425 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006426
Greg Clayton7bc39082011-03-24 23:53:38 +00006427 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006428 {
6429 uint32_t t;
6430 uint32_t n;
6431 uint32_t imm32;
6432 bool index;
6433 bool add;
6434 bool wback;
6435
6436 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6437 switch (encoding)
6438 {
6439 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006440 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006441 t = Bits32 (opcode, 2, 0);
6442 n = Bits32 (opcode, 5, 3);
6443 imm32 = Bits32 (opcode, 10, 6) << 1;
6444
6445 // index = TRUE; add = TRUE; wback = FALSE;
6446 index = true;
6447 add = true;
6448 wback = false;
6449
6450 break;
6451
6452 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006453 // if Rt == '1111' then SEE "Unallocated memory hints";
6454 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006455 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6456 t = Bits32 (opcode, 15, 12);
6457 n = Bits32 (opcode, 19, 16);
6458 imm32 = Bits32 (opcode, 11, 0);
6459
6460 // index = TRUE; add = TRUE; wback = FALSE;
6461 index = true;
6462 add = true;
6463 wback = false;
6464
6465 // if t == 13 then UNPREDICTABLE;
6466 if (t == 13)
6467 return false;
6468 break;
6469
6470 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006471 // if Rn == '1111' then SEE LDRH (literal);
6472 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6473 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6474 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006475 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6476 return false;
6477
6478 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6479 t = Bits32 (opcode, 15, 12);
6480 n = Bits32 (opcode, 19, 16);
6481 imm32 = Bits32 (opcode, 7, 0);
6482
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006483 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006484 index = BitIsSet (opcode, 10);
6485 add = BitIsSet (opcode, 9);
6486 wback = BitIsSet (opcode, 8);
6487
6488 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6489 if (BadReg (t) || (wback && (n == t)))
6490 return false;
6491 break;
6492
6493 default:
6494 return false;
6495 }
6496
6497 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6498 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6499 if (!success)
6500 return false;
6501
6502 addr_t offset_addr;
6503 addr_t address;
6504
6505 if (add)
6506 offset_addr = Rn + imm32;
6507 else
6508 offset_addr = Rn - imm32;
6509
6510 // address = if index then offset_addr else R[n];
6511 if (index)
6512 address = offset_addr;
6513 else
6514 address = Rn;
6515
6516 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006517 RegisterInfo base_reg;
6518 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006519
6520 EmulateInstruction::Context context;
6521 context.type = eContextRegisterLoad;
6522 context.SetRegisterPlusOffset (base_reg, address - Rn);
6523
6524 uint64_t data = MemURead (context, address, 2, 0, &success);
6525 if (!success)
6526 return false;
6527
6528 // if wback then R[n] = offset_addr;
6529 if (wback)
6530 {
6531 context.type = eContextAdjustBaseRegister;
6532 context.SetAddress (offset_addr);
6533 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6534 return false;
6535 }
6536
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006537 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006538 if (UnalignedSupport () || BitIsClear (address, 0))
6539 {
6540 // R[t] = ZeroExtend(data, 32);
6541 context.type = eContextRegisterLoad;
6542 context.SetRegisterPlusOffset (base_reg, address - Rn);
6543 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6544 return false;
6545 }
6546 else // Can only apply before ARMv7
6547 {
6548 // R[t] = bits(32) UNKNOWN;
6549 WriteBits32Unknown (t);
6550 }
6551 }
6552 return true;
6553}
Caroline Ticefe479112011-02-18 18:52:37 +00006554
Caroline Tice952b5382011-02-28 23:15:24 +00006555// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6556// zero-extends it to form a 32-bit word, and writes it to a register.
6557bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006558EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006559{
6560#if 0
6561 if ConditionPassed() then
6562 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6563 base = Align(PC,4);
6564 address = if add then (base + imm32) else (base - imm32);
6565 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006566 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006567 R[t] = ZeroExtend(data, 32);
6568 else // Can only apply before ARMv7
6569 R[t] = bits(32) UNKNOWN;
6570#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006571
Caroline Tice952b5382011-02-28 23:15:24 +00006572 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006573
Greg Clayton7bc39082011-03-24 23:53:38 +00006574 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006575 {
6576 uint32_t t;
6577 uint32_t imm32;
6578 bool add;
6579
6580 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6581 switch (encoding)
6582 {
6583 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006584 // if Rt == '1111' then SEE "Unallocated memory hints";
6585 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006586 t = Bits32 (opcode, 15, 12);
6587 imm32 = Bits32 (opcode, 11, 0);
6588 add = BitIsSet (opcode, 23);
6589
6590 // if t == 13 then UNPREDICTABLE;
6591 if (t == 13)
6592 return false;
6593
6594 break;
6595
6596 case eEncodingA1:
6597 {
6598 uint32_t imm4H = Bits32 (opcode, 11, 8);
6599 uint32_t imm4L = Bits32 (opcode, 3, 0);
6600
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006601 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006602 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006603 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006604 add = BitIsSet (opcode, 23);
6605
6606 // if t == 15 then UNPREDICTABLE;
6607 if (t == 15)
6608 return false;
6609 break;
6610 }
6611
6612 default:
6613 return false;
6614 }
6615
6616 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006617 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006618 if (!success)
6619 return false;
6620
6621 addr_t base = AlignPC (pc_value);
6622 addr_t address;
6623
6624 // address = if add then (base + imm32) else (base - imm32);
6625 if (add)
6626 address = base + imm32;
6627 else
6628 address = base - imm32;
6629
6630 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006631 RegisterInfo base_reg;
6632 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice952b5382011-02-28 23:15:24 +00006633
6634 EmulateInstruction::Context context;
6635 context.type = eContextRegisterLoad;
6636 context.SetRegisterPlusOffset (base_reg, address - base);
6637
6638 uint64_t data = MemURead (context, address, 2, 0, &success);
6639 if (!success)
6640 return false;
6641
6642
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006643 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006644 if (UnalignedSupport () || BitIsClear (address, 0))
6645 {
6646 // R[t] = ZeroExtend(data, 32);
6647 context.type = eContextRegisterLoad;
6648 context.SetRegisterPlusOffset (base_reg, address - base);
6649 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6650 return false;
6651
6652 }
6653 else // Can only apply before ARMv7
6654 {
6655 // R[t] = bits(32) UNKNOWN;
6656 WriteBits32Unknown (t);
6657 }
6658 }
6659 return true;
6660}
6661
Caroline Tice0e6bc952011-03-01 18:00:42 +00006662// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6663// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6664// be shifted left by 0, 1, 2, or 3 bits.
6665bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006666EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006667{
6668#if 0
6669 if ConditionPassed() then
6670 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6671 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6672 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6673 address = if index then offset_addr else R[n];
6674 data = MemU[address,2];
6675 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006676 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006677 R[t] = ZeroExtend(data, 32);
6678 else // Can only apply before ARMv7
6679 R[t] = bits(32) UNKNOWN;
6680#endif
6681
6682 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006683
Greg Clayton7bc39082011-03-24 23:53:38 +00006684 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006685 {
6686 uint32_t t;
6687 uint32_t n;
6688 uint32_t m;
6689 bool index;
6690 bool add;
6691 bool wback;
6692 ARM_ShifterType shift_t;
6693 uint32_t shift_n;
6694
6695 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6696 switch (encoding)
6697 {
6698 case eEncodingT1:
6699 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6700 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6701 t = Bits32 (opcode, 2, 0);
6702 n = Bits32 (opcode, 5, 3);
6703 m = Bits32 (opcode, 8, 6);
6704
6705 // index = TRUE; add = TRUE; wback = FALSE;
6706 index = true;
6707 add = true;
6708 wback = false;
6709
6710 // (shift_t, shift_n) = (SRType_LSL, 0);
6711 shift_t = SRType_LSL;
6712 shift_n = 0;
6713
6714 break;
6715
6716 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006717 // if Rn == '1111' then SEE LDRH (literal);
6718 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006719 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6720 t = Bits32 (opcode, 15, 12);
6721 n = Bits32 (opcode, 19, 16);
6722 m = Bits32 (opcode, 3, 0);
6723
6724 // index = TRUE; add = TRUE; wback = FALSE;
6725 index = true;
6726 add = true;
6727 wback = false;
6728
6729 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6730 shift_t = SRType_LSL;
6731 shift_n = Bits32 (opcode, 5, 4);
6732
6733 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6734 if ((t == 13) || BadReg (m))
6735 return false;
6736 break;
6737
6738 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006739 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006740 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6741 t = Bits32 (opcode, 15, 12);
6742 n = Bits32 (opcode, 19, 16);
6743 m = Bits32 (opcode, 3, 0);
6744
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006745 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006746 index = BitIsSet (opcode, 24);
6747 add = BitIsSet (opcode, 23);
6748 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6749
6750 // (shift_t, shift_n) = (SRType_LSL, 0);
6751 shift_t = SRType_LSL;
6752 shift_n = 0;
6753
6754 // if t == 15 || m == 15 then UNPREDICTABLE;
6755 if ((t == 15) || (m == 15))
6756 return false;
6757
6758 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6759 if (wback && ((n == 15) || (n == t)))
6760 return false;
6761
6762 break;
6763
6764 default:
6765 return false;
6766 }
6767
6768 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6769
6770 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6771 if (!success)
6772 return false;
6773
6774 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6775
6776 addr_t offset_addr;
6777 addr_t address;
6778
6779 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6780 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6781 if (!success)
6782 return false;
6783
6784 if (add)
6785 offset_addr = Rn + offset;
6786 else
6787 offset_addr = Rn - offset;
6788
6789 // address = if index then offset_addr else R[n];
6790 if (index)
6791 address = offset_addr;
6792 else
6793 address = Rn;
6794
6795 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006796 RegisterInfo base_reg;
6797 RegisterInfo offset_reg;
6798 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6799 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice0e6bc952011-03-01 18:00:42 +00006800
6801 EmulateInstruction::Context context;
6802 context.type = eContextRegisterLoad;
6803 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6804 uint64_t data = MemURead (context, address, 2, 0, &success);
6805 if (!success)
6806 return false;
6807
6808 // if wback then R[n] = offset_addr;
6809 if (wback)
6810 {
6811 context.type = eContextAdjustBaseRegister;
6812 context.SetAddress (offset_addr);
6813 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6814 return false;
6815 }
6816
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006817 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006818 if (UnalignedSupport() || BitIsClear (address, 0))
6819 {
6820 // R[t] = ZeroExtend(data, 32);
6821 context.type = eContextRegisterLoad;
6822 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6823 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6824 return false;
6825 }
6826 else // Can only apply before ARMv7
6827 {
6828 // R[t] = bits(32) UNKNOWN;
6829 WriteBits32Unknown (t);
6830 }
6831 }
6832 return true;
6833}
6834
Caroline Ticea5e28af2011-03-01 21:53:03 +00006835// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6836// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6837// or pre-indexed addressing.
6838bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006839EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006840{
6841#if 0
6842 if ConditionPassed() then
6843 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6844 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6845 address = if index then offset_addr else R[n];
6846 R[t] = SignExtend(MemU[address,1], 32);
6847 if wback then R[n] = offset_addr;
6848#endif
6849
6850 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006851
Greg Clayton7bc39082011-03-24 23:53:38 +00006852 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006853 {
6854 uint32_t t;
6855 uint32_t n;
6856 uint32_t imm32;
6857 bool index;
6858 bool add;
6859 bool wback;
6860
6861 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6862 switch (encoding)
6863 {
6864 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006865 // if Rt == '1111' then SEE PLI;
6866 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006867 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6868 t = Bits32 (opcode, 15, 12);
6869 n = Bits32 (opcode, 19, 16);
6870 imm32 = Bits32 (opcode, 11, 0);
6871
6872 // index = TRUE; add = TRUE; wback = FALSE;
6873 index = true;
6874 add = true;
6875 wback = false;
6876
6877 // if t == 13 then UNPREDICTABLE;
6878 if (t == 13)
6879 return false;
6880
6881 break;
6882
6883 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006884 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6885 // if Rn == '1111' then SEE LDRSB (literal);
6886 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6887 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006888 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6889 return false;
6890
6891 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6892 t = Bits32 (opcode, 15, 12);
6893 n = Bits32 (opcode, 19, 16);
6894 imm32 = Bits32 (opcode, 7, 0);
6895
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006896 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006897 index = BitIsSet (opcode, 10);
6898 add = BitIsSet (opcode, 9);
6899 wback = BitIsSet (opcode, 8);
6900
6901 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006902 if (((t == 13) || ((t == 15)
6903 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6904 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006905 return false;
6906
6907 break;
6908
6909 case eEncodingA1:
6910 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006911 // if Rn == '1111' then SEE LDRSB (literal);
6912 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006913 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6914 t = Bits32 (opcode, 15, 12);
6915 n = Bits32 (opcode, 19, 16);
6916
6917 uint32_t imm4H = Bits32 (opcode, 11, 8);
6918 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006919 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006920
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006921 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006922 index = BitIsSet (opcode, 24);
6923 add = BitIsSet (opcode, 23);
6924 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6925
6926 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6927 if ((t == 15) || (wback && (n == t)))
6928 return false;
6929
6930 break;
6931 }
6932
6933 default:
6934 return false;
6935 }
6936
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006937 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006938 if (!success)
6939 return false;
6940
6941 addr_t offset_addr;
6942 addr_t address;
6943
6944 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6945 if (add)
6946 offset_addr = Rn + imm32;
6947 else
6948 offset_addr = Rn - imm32;
6949
6950 // address = if index then offset_addr else R[n];
6951 if (index)
6952 address = offset_addr;
6953 else
6954 address = Rn;
6955
6956 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006957 RegisterInfo base_reg;
6958 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006959
6960 EmulateInstruction::Context context;
6961 context.type = eContextRegisterLoad;
6962 context.SetRegisterPlusOffset (base_reg, address - Rn);
6963
6964 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6965 if (!success)
6966 return false;
6967
6968 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6969 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6970 return false;
6971
6972 // if wback then R[n] = offset_addr;
6973 if (wback)
6974 {
6975 context.type = eContextAdjustBaseRegister;
6976 context.SetAddress (offset_addr);
6977 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6978 return false;
6979 }
6980 }
6981
6982 return true;
6983}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006984
Caroline Tice5f593912011-03-01 22:25:17 +00006985// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6986// sign-extends it to form a 32-bit word, and writes tit to a register.
6987bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006988EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006989{
6990#if 0
6991 if ConditionPassed() then
6992 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6993 base = Align(PC,4);
6994 address = if add then (base + imm32) else (base - imm32);
6995 R[t] = SignExtend(MemU[address,1], 32);
6996#endif
6997
6998 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006999
Greg Clayton7bc39082011-03-24 23:53:38 +00007000 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00007001 {
7002 uint32_t t;
7003 uint32_t imm32;
7004 bool add;
7005
7006 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7007 switch (encoding)
7008 {
7009 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007010 // if Rt == '1111' then SEE PLI;
7011 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007012 t = Bits32 (opcode, 15, 12);
7013 imm32 = Bits32 (opcode, 11, 0);
7014 add = BitIsSet (opcode, 23);
7015
7016 // if t == 13 then UNPREDICTABLE;
7017 if (t == 13)
7018 return false;
7019
7020 break;
7021
7022 case eEncodingA1:
7023 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007024 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007025 t = Bits32 (opcode, 15, 12);
7026 uint32_t imm4H = Bits32 (opcode, 11, 8);
7027 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007028 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00007029 add = BitIsSet (opcode, 23);
7030
7031 // if t == 15 then UNPREDICTABLE;
7032 if (t == 15)
7033 return false;
7034
7035 break;
7036 }
7037
7038 default:
7039 return false;
7040 }
7041
7042 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007043 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007044 if (!success)
7045 return false;
7046 uint64_t base = AlignPC (pc_value);
7047
7048 // address = if add then (base + imm32) else (base - imm32);
7049 addr_t address;
7050 if (add)
7051 address = base + imm32;
7052 else
7053 address = base - imm32;
7054
7055 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007056 RegisterInfo base_reg;
7057 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice5f593912011-03-01 22:25:17 +00007058
7059 EmulateInstruction::Context context;
7060 context.type = eContextRegisterLoad;
7061 context.SetRegisterPlusOffset (base_reg, address - base);
7062
7063 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7064 if (!success)
7065 return false;
7066
7067 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7068 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7069 return false;
7070 }
7071 return true;
7072}
7073
Caroline Tice672f3112011-03-01 23:55:59 +00007074// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7075// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7076// shifted left by 0, 1, 2, or 3 bits.
7077bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007078EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007079{
7080#if 0
7081 if ConditionPassed() then
7082 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7083 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7084 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7085 address = if index then offset_addr else R[n];
7086 R[t] = SignExtend(MemU[address,1], 32);
7087 if wback then R[n] = offset_addr;
7088#endif
7089
7090 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007091
Greg Clayton7bc39082011-03-24 23:53:38 +00007092 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007093 {
7094 uint32_t t;
7095 uint32_t n;
7096 uint32_t m;
7097 bool index;
7098 bool add;
7099 bool wback;
7100 ARM_ShifterType shift_t;
7101 uint32_t shift_n;
7102
7103 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7104 switch (encoding)
7105 {
7106 case eEncodingT1:
7107 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7108 t = Bits32 (opcode, 2, 0);
7109 n = Bits32 (opcode, 5, 3);
7110 m = Bits32 (opcode, 8, 6);
7111
7112 // index = TRUE; add = TRUE; wback = FALSE;
7113 index = true;
7114 add = true;
7115 wback = false;
7116
7117 // (shift_t, shift_n) = (SRType_LSL, 0);
7118 shift_t = SRType_LSL;
7119 shift_n = 0;
7120
7121 break;
7122
7123 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007124 // if Rt == '1111' then SEE PLI;
7125 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007126 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7127 t = Bits32 (opcode, 15, 12);
7128 n = Bits32 (opcode, 19, 16);
7129 m = Bits32 (opcode, 3, 0);
7130
7131 // index = TRUE; add = TRUE; wback = FALSE;
7132 index = true;
7133 add = true;
7134 wback = false;
7135
7136 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7137 shift_t = SRType_LSL;
7138 shift_n = Bits32 (opcode, 5, 4);
7139
7140 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7141 if ((t == 13) || BadReg (m))
7142 return false;
7143 break;
7144
7145 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007146 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007147 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7148 t = Bits32 (opcode, 15, 12);
7149 n = Bits32 (opcode, 19, 16);
7150 m = Bits32 (opcode, 3, 0);
7151
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007152 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007153 index = BitIsSet (opcode, 24);
7154 add = BitIsSet (opcode, 23);
7155 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7156
7157 // (shift_t, shift_n) = (SRType_LSL, 0);
7158 shift_t = SRType_LSL;
7159 shift_n = 0;
7160
7161 // if t == 15 || m == 15 then UNPREDICTABLE;
7162 if ((t == 15) || (m == 15))
7163 return false;
7164
7165 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7166 if (wback && ((n == 15) || (n == t)))
7167 return false;
7168 break;
7169
7170 default:
7171 return false;
7172 }
7173
7174 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7175 if (!success)
7176 return false;
7177
7178 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7179 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7180
7181 addr_t offset_addr;
7182 addr_t address;
7183
7184 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7185 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7186 if (!success)
7187 return false;
7188
7189 if (add)
7190 offset_addr = Rn + offset;
7191 else
7192 offset_addr = Rn - offset;
7193
7194 // address = if index then offset_addr else R[n];
7195 if (index)
7196 address = offset_addr;
7197 else
7198 address = Rn;
7199
7200 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007201 RegisterInfo base_reg;
7202 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7203 RegisterInfo offset_reg;
7204 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice672f3112011-03-01 23:55:59 +00007205
7206 EmulateInstruction::Context context;
7207 context.type = eContextRegisterLoad;
7208 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7209
7210 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7211 if (!success)
7212 return false;
7213
7214 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7215 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7216 return false;
7217
7218 // if wback then R[n] = offset_addr;
7219 if (wback)
7220 {
7221 context.type = eContextAdjustBaseRegister;
7222 context.SetAddress (offset_addr);
7223 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7224 return false;
7225 }
7226 }
7227 return true;
7228}
7229
Caroline Tice78fb5632011-03-02 00:39:42 +00007230// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7231// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7232// pre-indexed addressing.
7233bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007234EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007235{
7236#if 0
7237 if ConditionPassed() then
7238 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7239 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7240 address = if index then offset_addr else R[n];
7241 data = MemU[address,2];
7242 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007243 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007244 R[t] = SignExtend(data, 32);
7245 else // Can only apply before ARMv7
7246 R[t] = bits(32) UNKNOWN;
7247#endif
7248
7249 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007250
Greg Clayton7bc39082011-03-24 23:53:38 +00007251 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007252 {
7253 uint32_t t;
7254 uint32_t n;
7255 uint32_t imm32;
7256 bool index;
7257 bool add;
7258 bool wback;
7259
7260 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7261 switch (encoding)
7262 {
7263 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007264 // if Rn == '1111' then SEE LDRSH (literal);
7265 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007266 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7267 t = Bits32 (opcode, 15, 12);
7268 n = Bits32 (opcode, 19, 16);
7269 imm32 = Bits32 (opcode, 11, 0);
7270
7271 // index = TRUE; add = TRUE; wback = FALSE;
7272 index = true;
7273 add = true;
7274 wback = false;
7275
7276 // if t == 13 then UNPREDICTABLE;
7277 if (t == 13)
7278 return false;
7279
7280 break;
7281
7282 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007283 // if Rn == '1111' then SEE LDRSH (literal);
7284 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7285 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7286 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007287 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7288 return false;
7289
7290 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7291 t = Bits32 (opcode, 15, 12);
7292 n = Bits32 (opcode, 19, 16);
7293 imm32 = Bits32 (opcode, 7, 0);
7294
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007295 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007296 index = BitIsSet (opcode, 10);
7297 add = BitIsSet (opcode, 9);
7298 wback = BitIsSet (opcode, 8);
7299
7300 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7301 if (BadReg (t) || (wback && (n == t)))
7302 return false;
7303
7304 break;
7305
7306 case eEncodingA1:
7307 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007308 // if Rn == '1111' then SEE LDRSH (literal);
7309 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007310 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7311 t = Bits32 (opcode, 15, 12);
7312 n = Bits32 (opcode, 19, 16);
7313 uint32_t imm4H = Bits32 (opcode, 11,8);
7314 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007315 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007316
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007317 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007318 index = BitIsSet (opcode, 24);
7319 add = BitIsSet (opcode, 23);
7320 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7321
7322 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7323 if ((t == 15) || (wback && (n == t)))
7324 return false;
7325
7326 break;
7327 }
7328
7329 default:
7330 return false;
7331 }
7332
7333 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7334 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7335 if (!success)
7336 return false;
7337
7338 addr_t offset_addr;
7339 if (add)
7340 offset_addr = Rn + imm32;
7341 else
7342 offset_addr = Rn - imm32;
7343
7344 // address = if index then offset_addr else R[n];
7345 addr_t address;
7346 if (index)
7347 address = offset_addr;
7348 else
7349 address = Rn;
7350
7351 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007352 RegisterInfo base_reg;
7353 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice78fb5632011-03-02 00:39:42 +00007354
7355 EmulateInstruction::Context context;
7356 context.type = eContextRegisterLoad;
7357 context.SetRegisterPlusOffset (base_reg, address - Rn);
7358
7359 uint64_t data = MemURead (context, address, 2, 0, &success);
7360 if (!success)
7361 return false;
7362
7363 // if wback then R[n] = offset_addr;
7364 if (wback)
7365 {
7366 context.type = eContextAdjustBaseRegister;
7367 context.SetAddress (offset_addr);
7368 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7369 return false;
7370 }
7371
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007372 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007373 if (UnalignedSupport() || BitIsClear (address, 0))
7374 {
7375 // R[t] = SignExtend(data, 32);
7376 int64_t signed_data = llvm::SignExtend64<16>(data);
7377 context.type = eContextRegisterLoad;
7378 context.SetRegisterPlusOffset (base_reg, address - Rn);
7379 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7380 return false;
7381 }
7382 else // Can only apply before ARMv7
7383 {
7384 // R[t] = bits(32) UNKNOWN;
7385 WriteBits32Unknown (t);
7386 }
7387 }
7388 return true;
7389}
7390
Caroline Ticed2fac092011-03-02 19:45:34 +00007391// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7392// sign-extends it to from a 32-bit word, and writes it to a register.
7393bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007394EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007395{
7396#if 0
7397 if ConditionPassed() then
7398 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7399 base = Align(PC,4);
7400 address = if add then (base + imm32) else (base - imm32);
7401 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007402 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007403 R[t] = SignExtend(data, 32);
7404 else // Can only apply before ARMv7
7405 R[t] = bits(32) UNKNOWN;
7406#endif
7407
7408 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007409
Greg Clayton7bc39082011-03-24 23:53:38 +00007410 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007411 {
7412 uint32_t t;
7413 uint32_t imm32;
7414 bool add;
7415
7416 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7417 switch (encoding)
7418 {
7419 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007420 // if Rt == '1111' then SEE "Unallocated memory hints";
7421 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007422 t = Bits32 (opcode, 15, 12);
7423 imm32 = Bits32 (opcode, 11, 0);
7424 add = BitIsSet (opcode, 23);
7425
7426 // if t == 13 then UNPREDICTABLE;
7427 if (t == 13)
7428 return false;
7429
7430 break;
7431
7432 case eEncodingA1:
7433 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007434 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007435 t = Bits32 (opcode, 15, 12);
7436 uint32_t imm4H = Bits32 (opcode, 11, 8);
7437 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007438 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007439 add = BitIsSet (opcode, 23);
7440
7441 // if t == 15 then UNPREDICTABLE;
7442 if (t == 15)
7443 return false;
7444
7445 break;
7446 }
7447 default:
7448 return false;
7449 }
7450
7451 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007452 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007453 if (!success)
7454 return false;
7455
7456 uint64_t base = AlignPC (pc_value);
7457
7458 addr_t address;
7459 // address = if add then (base + imm32) else (base - imm32);
7460 if (add)
7461 address = base + imm32;
7462 else
7463 address = base - imm32;
7464
7465 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007466 RegisterInfo base_reg;
7467 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Ticed2fac092011-03-02 19:45:34 +00007468
7469 EmulateInstruction::Context context;
7470 context.type = eContextRegisterLoad;
7471 context.SetRegisterPlusOffset (base_reg, imm32);
7472
7473 uint64_t data = MemURead (context, address, 2, 0, &success);
7474 if (!success)
7475 return false;
7476
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007477 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007478 if (UnalignedSupport() || BitIsClear (address, 0))
7479 {
7480 // R[t] = SignExtend(data, 32);
7481 int64_t signed_data = llvm::SignExtend64<16>(data);
7482 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7483 return false;
7484 }
7485 else // Can only apply before ARMv7
7486 {
7487 // R[t] = bits(32) UNKNOWN;
7488 WriteBits32Unknown (t);
7489 }
7490 }
7491 return true;
7492}
7493
Caroline Tice291a3e92011-03-02 21:13:44 +00007494// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7495// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7496// shifted left by 0, 1, 2, or 3 bits.
7497bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007498EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007499{
7500#if 0
7501 if ConditionPassed() then
7502 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7503 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7504 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7505 address = if index then offset_addr else R[n];
7506 data = MemU[address,2];
7507 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007508 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007509 R[t] = SignExtend(data, 32);
7510 else // Can only apply before ARMv7
7511 R[t] = bits(32) UNKNOWN;
7512#endif
7513
7514 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007515
Greg Clayton7bc39082011-03-24 23:53:38 +00007516 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007517 {
7518 uint32_t t;
7519 uint32_t n;
7520 uint32_t m;
7521 bool index;
7522 bool add;
7523 bool wback;
7524 ARM_ShifterType shift_t;
7525 uint32_t shift_n;
7526
7527 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7528 switch (encoding)
7529 {
7530 case eEncodingT1:
7531 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7532 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7533 t = Bits32 (opcode, 2, 0);
7534 n = Bits32 (opcode, 5, 3);
7535 m = Bits32 (opcode, 8, 6);
7536
7537 // index = TRUE; add = TRUE; wback = FALSE;
7538 index = true;
7539 add = true;
7540 wback = false;
7541
7542 // (shift_t, shift_n) = (SRType_LSL, 0);
7543 shift_t = SRType_LSL;
7544 shift_n = 0;
7545
7546 break;
7547
7548 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007549 // if Rn == '1111' then SEE LDRSH (literal);
7550 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007551 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7552 t = Bits32 (opcode, 15, 12);
7553 n = Bits32 (opcode, 19, 16);
7554 m = Bits32 (opcode, 3, 0);
7555
7556 // index = TRUE; add = TRUE; wback = FALSE;
7557 index = true;
7558 add = true;
7559 wback = false;
7560
7561 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7562 shift_t = SRType_LSL;
7563 shift_n = Bits32 (opcode, 5, 4);
7564
7565 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7566 if ((t == 13) || BadReg (m))
7567 return false;
7568
7569 break;
7570
7571 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007572 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007573 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7574 t = Bits32 (opcode, 15, 12);
7575 n = Bits32 (opcode, 19, 16);
7576 m = Bits32 (opcode, 3, 0);
7577
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007578 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007579 index = BitIsSet (opcode, 24);
7580 add = BitIsSet (opcode, 23);
7581 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7582
7583 // (shift_t, shift_n) = (SRType_LSL, 0);
7584 shift_t = SRType_LSL;
7585 shift_n = 0;
7586
7587 // if t == 15 || m == 15 then UNPREDICTABLE;
7588 if ((t == 15) || (m == 15))
7589 return false;
7590
7591 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7592 if (wback && ((n == 15) || (n == t)))
7593 return false;
7594
7595 break;
7596
7597 default:
7598 break;
7599 }
7600
7601 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7602 if (!success)
7603 return false;
7604
7605 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7606 if (!success)
7607 return false;
7608
7609 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7610 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7611
7612 addr_t offset_addr;
7613 addr_t address;
7614
7615 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7616 if (add)
7617 offset_addr = Rn + offset;
7618 else
7619 offset_addr = Rn - offset;
7620
7621 // address = if index then offset_addr else R[n];
7622 if (index)
7623 address = offset_addr;
7624 else
7625 address = Rn;
7626
7627 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007628 RegisterInfo base_reg;
7629 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007630
Greg Claytonc07d4512011-04-26 23:48:45 +00007631 RegisterInfo offset_reg;
7632 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007633
7634 EmulateInstruction::Context context;
7635 context.type = eContextRegisterLoad;
7636 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7637
7638 uint64_t data = MemURead (context, address, 2, 0, &success);
7639 if (!success)
7640 return false;
7641
7642 // if wback then R[n] = offset_addr;
7643 if (wback)
7644 {
7645 context.type = eContextAdjustBaseRegister;
7646 context.SetAddress (offset_addr);
7647 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7648 return false;
7649 }
7650
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007651 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007652 if (UnalignedSupport() || BitIsClear (address, 0))
7653 {
7654 // R[t] = SignExtend(data, 32);
7655 context.type = eContextRegisterLoad;
7656 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7657
7658 int64_t signed_data = llvm::SignExtend64<16>(data);
7659 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7660 return false;
7661 }
7662 else // Can only apply before ARMv7
7663 {
7664 // R[t] = bits(32) UNKNOWN;
7665 WriteBits32Unknown (t);
7666 }
7667 }
7668 return true;
7669}
Caroline Tice6bf65162011-03-03 17:42:58 +00007670
7671// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7672// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7673bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007674EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007675{
7676#if 0
7677 if ConditionPassed() then
7678 EncodingSpecificOperations();
7679 rotated = ROR(R[m], rotation);
7680 R[d] = SignExtend(rotated<7:0>, 32);
7681#endif
7682
7683 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007684
Greg Clayton7bc39082011-03-24 23:53:38 +00007685 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007686 {
7687 uint32_t d;
7688 uint32_t m;
7689 uint32_t rotation;
7690
7691 // EncodingSpecificOperations();
7692 switch (encoding)
7693 {
7694 case eEncodingT1:
7695 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7696 d = Bits32 (opcode, 2, 0);
7697 m = Bits32 (opcode, 5, 3);
7698 rotation = 0;
7699
7700 break;
7701
7702 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007703 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007704 d = Bits32 (opcode, 11, 8);
7705 m = Bits32 (opcode, 3, 0);
7706 rotation = Bits32 (opcode, 5, 4) << 3;
7707
7708 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7709 if (BadReg (d) || BadReg (m))
7710 return false;
7711
7712 break;
7713
7714 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007715 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007716 d = Bits32 (opcode, 15, 12);
7717 m = Bits32 (opcode, 3, 0);
7718 rotation = Bits32 (opcode, 11, 10) << 3;
7719
7720 // if d == 15 || m == 15 then UNPREDICTABLE;
7721 if ((d == 15) || (m == 15))
7722 return false;
7723
7724 break;
7725
7726 default:
7727 return false;
7728 }
7729
Caroline Tice868198b2011-03-03 18:04:49 +00007730 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7731 if (!success)
7732 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007733
7734 // rotated = ROR(R[m], rotation);
7735 uint64_t rotated = ROR (Rm, rotation);
7736
7737 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007738 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007739
Greg Claytonc07d4512011-04-26 23:48:45 +00007740 RegisterInfo source_reg;
7741 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice6bf65162011-03-03 17:42:58 +00007742
7743 EmulateInstruction::Context context;
7744 context.type = eContextRegisterLoad;
7745 context.SetRegister (source_reg);
7746
Caroline Tice8ce96d92011-03-03 18:27:17 +00007747 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007748 return false;
7749 }
7750 return true;
7751}
Caroline Tice291a3e92011-03-02 21:13:44 +00007752
Caroline Tice868198b2011-03-03 18:04:49 +00007753// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7754// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7755bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007756EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007757{
7758#if 0
7759 if ConditionPassed() then
7760 EncodingSpecificOperations();
7761 rotated = ROR(R[m], rotation);
7762 R[d] = SignExtend(rotated<15:0>, 32);
7763#endif
7764
7765 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007766
Greg Clayton7bc39082011-03-24 23:53:38 +00007767 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007768 {
7769 uint32_t d;
7770 uint32_t m;
7771 uint32_t rotation;
7772
7773 // EncodingSpecificOperations();
7774 switch (encoding)
7775 {
7776 case eEncodingT1:
7777 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7778 d = Bits32 (opcode, 2, 0);
7779 m = Bits32 (opcode, 5, 3);
7780 rotation = 0;
7781
7782 break;
7783
7784 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007785 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007786 d = Bits32 (opcode, 11, 8);
7787 m = Bits32 (opcode, 3, 0);
7788 rotation = Bits32 (opcode, 5, 4) << 3;
7789
7790 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7791 if (BadReg (d) || BadReg (m))
7792 return false;
7793
7794 break;
7795
7796 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007797 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007798 d = Bits32 (opcode, 15, 12);
7799 m = Bits32 (opcode, 3, 0);
7800 rotation = Bits32 (opcode, 11, 10) << 3;
7801
7802 // if d == 15 || m == 15 then UNPREDICTABLE;
7803 if ((d == 15) || (m == 15))
7804 return false;
7805
7806 break;
7807
7808 default:
7809 return false;
7810 }
7811
7812 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7813 if (!success)
7814 return false;
7815
7816 // rotated = ROR(R[m], rotation);
7817 uint64_t rotated = ROR (Rm, rotation);
7818
7819 // R[d] = SignExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007820 RegisterInfo source_reg;
7821 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice868198b2011-03-03 18:04:49 +00007822
7823 EmulateInstruction::Context context;
7824 context.type = eContextRegisterLoad;
7825 context.SetRegister (source_reg);
7826
Caroline Tice8ce96d92011-03-03 18:27:17 +00007827 int64_t data = llvm::SignExtend64<16> (rotated);
7828 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007829 return false;
7830 }
7831
7832 return true;
7833}
7834
Caroline Tice8ce96d92011-03-03 18:27:17 +00007835// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7836// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7837bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007838EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007839{
7840#if 0
7841 if ConditionPassed() then
7842 EncodingSpecificOperations();
7843 rotated = ROR(R[m], rotation);
7844 R[d] = ZeroExtend(rotated<7:0>, 32);
7845#endif
7846
7847 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007848
Greg Clayton7bc39082011-03-24 23:53:38 +00007849 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007850 {
7851 uint32_t d;
7852 uint32_t m;
7853 uint32_t rotation;
7854
7855 // EncodingSpecificOperations();
7856 switch (encoding)
7857 {
7858 case eEncodingT1:
7859 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7860 d = Bits32 (opcode, 2, 0);
7861 m = Bits32 (opcode, 5, 3);
7862 rotation = 0;
7863
7864 break;
7865
7866 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007867 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007868 d = Bits32 (opcode, 11, 8);
7869 m = Bits32 (opcode, 3, 0);
7870 rotation = Bits32 (opcode, 5, 4) << 3;
7871
7872 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7873 if (BadReg (d) || BadReg (m))
7874 return false;
7875
7876 break;
7877
7878 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007879 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007880 d = Bits32 (opcode, 15, 12);
7881 m = Bits32 (opcode, 3, 0);
7882 rotation = Bits32 (opcode, 11, 10) << 3;
7883
7884 // if d == 15 || m == 15 then UNPREDICTABLE;
7885 if ((d == 15) || (m == 15))
7886 return false;
7887
7888 break;
7889
7890 default:
7891 return false;
7892 }
7893
7894 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7895 if (!success)
7896 return false;
7897
7898 // rotated = ROR(R[m], rotation);
7899 uint64_t rotated = ROR (Rm, rotation);
7900
7901 // R[d] = ZeroExtend(rotated<7:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007902 RegisterInfo source_reg;
7903 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007904
7905 EmulateInstruction::Context context;
7906 context.type = eContextRegisterLoad;
7907 context.SetRegister (source_reg);
7908
7909 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7910 return false;
7911 }
7912 return true;
7913}
7914
Caroline Tice11555f22011-03-03 18:48:58 +00007915// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7916// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7917bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007918EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007919{
7920#if 0
7921 if ConditionPassed() then
7922 EncodingSpecificOperations();
7923 rotated = ROR(R[m], rotation);
7924 R[d] = ZeroExtend(rotated<15:0>, 32);
7925#endif
7926
7927 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007928
Greg Clayton7bc39082011-03-24 23:53:38 +00007929 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007930 {
7931 uint32_t d;
7932 uint32_t m;
7933 uint32_t rotation;
7934
7935 switch (encoding)
7936 {
7937 case eEncodingT1:
7938 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7939 d = Bits32 (opcode, 2, 0);
7940 m = Bits32 (opcode, 5, 3);
7941 rotation = 0;
7942
7943 break;
7944
7945 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007946 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007947 d = Bits32 (opcode, 11, 8);
7948 m = Bits32 (opcode, 3, 0);
7949 rotation = Bits32 (opcode, 5, 4) << 3;
7950
7951 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7952 if (BadReg (d) || BadReg (m))
7953 return false;
7954
7955 break;
7956
7957 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007958 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007959 d = Bits32 (opcode, 15, 12);
7960 m = Bits32 (opcode, 3, 0);
7961 rotation = Bits32 (opcode, 11, 10) << 3;
7962
7963 // if d == 15 || m == 15 then UNPREDICTABLE;
7964 if ((d == 15) || (m == 15))
7965 return false;
7966
7967 break;
7968
7969 default:
7970 return false;
7971 }
7972
7973 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7974 if (!success)
7975 return false;
7976
7977 // rotated = ROR(R[m], rotation);
7978 uint64_t rotated = ROR (Rm, rotation);
7979
7980 // R[d] = ZeroExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007981 RegisterInfo source_reg;
7982 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice11555f22011-03-03 18:48:58 +00007983
7984 EmulateInstruction::Context context;
7985 context.type = eContextRegisterLoad;
7986 context.SetRegister (source_reg);
7987
7988 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7989 return false;
7990 }
7991 return true;
7992}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007993
7994// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7995// word respectively.
7996bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007997EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007998{
7999#if 0
8000 if ConditionPassed() then
8001 EncodingSpecificOperations();
8002 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8003 UNPREDICTABLE;
8004 else
8005 address = if increment then R[n] else R[n]-8;
8006 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008007 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008008 BranchWritePC(MemA[address,4]);
8009 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8010#endif
8011
8012 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008013
Greg Clayton7bc39082011-03-24 23:53:38 +00008014 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00008015 {
8016 uint32_t n;
8017 bool wback;
8018 bool increment;
8019 bool wordhigher;
8020
8021 // EncodingSpecificOperations();
8022 switch (encoding)
8023 {
8024 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008025 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008026 n = Bits32 (opcode, 19, 16);
8027 wback = BitIsSet (opcode, 21);
8028 increment = false;
8029 wordhigher = false;
8030
8031 // if n == 15 then UNPREDICTABLE;
8032 if (n == 15)
8033 return false;
8034
8035 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8036 if (InITBlock() && !LastInITBlock())
8037 return false;
8038
8039 break;
8040
8041 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008042 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008043 n = Bits32 (opcode, 19, 16);
8044 wback = BitIsSet (opcode, 21);
8045 increment = true;
8046 wordhigher = false;
8047
8048 // if n == 15 then UNPREDICTABLE;
8049 if (n == 15)
8050 return false;
8051
8052 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8053 if (InITBlock() && !LastInITBlock())
8054 return false;
8055
8056 break;
8057
8058 case eEncodingA1:
8059 // n = UInt(Rn);
8060 n = Bits32 (opcode, 19, 16);
8061
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008062 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008063 wback = BitIsSet (opcode, 21);
8064 increment = BitIsSet (opcode, 23);
8065 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8066
8067 // if n == 15 then UNPREDICTABLE;
8068 if (n == 15)
8069 return false;
8070
8071 break;
8072
8073 default:
8074 return false;
8075 }
8076
8077 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8078 if (!CurrentModeIsPrivileged ())
8079 // UNPREDICTABLE;
8080 return false;
8081 else
8082 {
8083 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8084 if (!success)
8085 return false;
8086
8087 addr_t address;
8088 // address = if increment then R[n] else R[n]-8;
8089 if (increment)
8090 address = Rn;
8091 else
8092 address = Rn - 8;
8093
8094 // if wordhigher then address = address+4;
8095 if (wordhigher)
8096 address = address + 4;
8097
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008098 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Greg Claytonc07d4512011-04-26 23:48:45 +00008099 RegisterInfo base_reg;
8100 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008101
8102 EmulateInstruction::Context context;
8103 context.type = eContextReturnFromException;
8104 context.SetRegisterPlusOffset (base_reg, address - Rn);
8105
8106 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8107 if (!success)
8108 return false;
8109
8110 CPSRWriteByInstr (data, 15, true);
8111
8112 // BranchWritePC(MemA[address,4]);
8113 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8114 if (!success)
8115 return false;
8116
8117 BranchWritePC (context, data2);
8118
8119 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8120 if (wback)
8121 {
8122 context.type = eContextAdjustBaseRegister;
8123 if (increment)
8124 {
8125 context.SetOffset (8);
8126 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8127 return false;
8128 }
8129 else
8130 {
8131 context.SetOffset (-8);
8132 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8133 return false;
8134 }
8135 } // if wback
8136 }
8137 } // if ConditionPassed()
8138 return true;
8139}
Caroline Tice11555f22011-03-03 18:48:58 +00008140
Johnny Chen2115b412011-02-21 23:42:44 +00008141// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8142// and writes the result to the destination register. It can optionally update the condition flags based on
8143// the result.
8144bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008145EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008146{
8147#if 0
8148 // ARM pseudo code...
8149 if ConditionPassed() then
8150 EncodingSpecificOperations();
8151 result = R[n] EOR imm32;
8152 if d == 15 then // Can only occur for ARM encoding
8153 ALUWritePC(result); // setflags is always FALSE here
8154 else
8155 R[d] = result;
8156 if setflags then
8157 APSR.N = result<31>;
8158 APSR.Z = IsZeroBit(result);
8159 APSR.C = carry;
8160 // APSR.V unchanged
8161#endif
8162
8163 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008164
Greg Clayton7bc39082011-03-24 23:53:38 +00008165 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008166 {
8167 uint32_t Rd, Rn;
8168 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8169 bool setflags;
8170 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8171 switch (encoding)
8172 {
8173 case eEncodingT1:
8174 Rd = Bits32(opcode, 11, 8);
8175 Rn = Bits32(opcode, 19, 16);
8176 setflags = BitIsSet(opcode, 20);
8177 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8178 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8179 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008180 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008181 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8182 return false;
8183 break;
8184 case eEncodingA1:
8185 Rd = Bits32(opcode, 15, 12);
8186 Rn = Bits32(opcode, 19, 16);
8187 setflags = BitIsSet(opcode, 20);
8188 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008189
Johnny Chen2115b412011-02-21 23:42:44 +00008190 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008191 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008192 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008193 break;
8194 default:
8195 return false;
8196 }
8197
8198 // Read the first operand.
8199 uint32_t val1 = ReadCoreReg(Rn, &success);
8200 if (!success)
8201 return false;
8202
8203 uint32_t result = val1 ^ imm32;
8204
8205 EmulateInstruction::Context context;
8206 context.type = EmulateInstruction::eContextImmediate;
8207 context.SetNoArgs ();
8208
8209 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8210 return false;
8211 }
8212 return true;
8213}
8214
8215// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8216// optionally-shifted register value, and writes the result to the destination register.
8217// It can optionally update the condition flags based on the result.
8218bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008219EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008220{
8221#if 0
8222 // ARM pseudo code...
8223 if ConditionPassed() then
8224 EncodingSpecificOperations();
8225 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8226 result = R[n] EOR shifted;
8227 if d == 15 then // Can only occur for ARM encoding
8228 ALUWritePC(result); // setflags is always FALSE here
8229 else
8230 R[d] = result;
8231 if setflags then
8232 APSR.N = result<31>;
8233 APSR.Z = IsZeroBit(result);
8234 APSR.C = carry;
8235 // APSR.V unchanged
8236#endif
8237
8238 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008239
Greg Clayton7bc39082011-03-24 23:53:38 +00008240 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008241 {
8242 uint32_t Rd, Rn, Rm;
8243 ARM_ShifterType shift_t;
8244 uint32_t shift_n; // the shift applied to the value read from Rm
8245 bool setflags;
8246 uint32_t carry;
8247 switch (encoding)
8248 {
8249 case eEncodingT1:
8250 Rd = Rn = Bits32(opcode, 2, 0);
8251 Rm = Bits32(opcode, 5, 3);
8252 setflags = !InITBlock();
8253 shift_t = SRType_LSL;
8254 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008255 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008256 case eEncodingT2:
8257 Rd = Bits32(opcode, 11, 8);
8258 Rn = Bits32(opcode, 19, 16);
8259 Rm = Bits32(opcode, 3, 0);
8260 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008261 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8262 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008263 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008264 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008265 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8266 return false;
8267 break;
8268 case eEncodingA1:
8269 Rd = Bits32(opcode, 15, 12);
8270 Rn = Bits32(opcode, 19, 16);
8271 Rm = Bits32(opcode, 3, 0);
8272 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008273 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008274
Johnny Chen2115b412011-02-21 23:42:44 +00008275 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008276 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008277 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008278 break;
8279 default:
8280 return false;
8281 }
8282
8283 // Read the first operand.
8284 uint32_t val1 = ReadCoreReg(Rn, &success);
8285 if (!success)
8286 return false;
8287
8288 // Read the second operand.
8289 uint32_t val2 = ReadCoreReg(Rm, &success);
8290 if (!success)
8291 return false;
8292
8293 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8294 uint32_t result = val1 ^ shifted;
8295
8296 EmulateInstruction::Context context;
8297 context.type = EmulateInstruction::eContextImmediate;
8298 context.SetNoArgs ();
8299
8300 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8301 return false;
8302 }
8303 return true;
8304}
8305
Johnny Chen7c5234d2011-02-18 23:41:11 +00008306// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8307// writes the result to the destination register. It can optionally update the condition flags based
8308// on the result.
8309bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008310EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008311{
8312#if 0
8313 // ARM pseudo code...
8314 if ConditionPassed() then
8315 EncodingSpecificOperations();
8316 result = R[n] OR imm32;
8317 if d == 15 then // Can only occur for ARM encoding
8318 ALUWritePC(result); // setflags is always FALSE here
8319 else
8320 R[d] = result;
8321 if setflags then
8322 APSR.N = result<31>;
8323 APSR.Z = IsZeroBit(result);
8324 APSR.C = carry;
8325 // APSR.V unchanged
8326#endif
8327
8328 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008329
Greg Clayton7bc39082011-03-24 23:53:38 +00008330 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008331 {
8332 uint32_t Rd, Rn;
8333 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8334 bool setflags;
8335 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8336 switch (encoding)
8337 {
8338 case eEncodingT1:
8339 Rd = Bits32(opcode, 11, 8);
8340 Rn = Bits32(opcode, 19, 16);
8341 setflags = BitIsSet(opcode, 20);
8342 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008343 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008344 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008345 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008346 if (BadReg(Rd) || Rn == 13)
8347 return false;
8348 break;
8349 case eEncodingA1:
8350 Rd = Bits32(opcode, 15, 12);
8351 Rn = Bits32(opcode, 19, 16);
8352 setflags = BitIsSet(opcode, 20);
8353 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008354
Johnny Chen7c5234d2011-02-18 23:41:11 +00008355 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008356 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008357 break;
8358 default:
8359 return false;
8360 }
8361
8362 // Read the first operand.
8363 uint32_t val1 = ReadCoreReg(Rn, &success);
8364 if (!success)
8365 return false;
8366
8367 uint32_t result = val1 | imm32;
8368
8369 EmulateInstruction::Context context;
8370 context.type = EmulateInstruction::eContextImmediate;
8371 context.SetNoArgs ();
8372
8373 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8374 return false;
8375 }
8376 return true;
8377}
8378
8379// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8380// value, and writes the result to the destination register. It can optionally update the condition flags based
8381// on the result.
8382bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008383EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008384{
8385#if 0
8386 // ARM pseudo code...
8387 if ConditionPassed() then
8388 EncodingSpecificOperations();
8389 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8390 result = R[n] OR shifted;
8391 if d == 15 then // Can only occur for ARM encoding
8392 ALUWritePC(result); // setflags is always FALSE here
8393 else
8394 R[d] = result;
8395 if setflags then
8396 APSR.N = result<31>;
8397 APSR.Z = IsZeroBit(result);
8398 APSR.C = carry;
8399 // APSR.V unchanged
8400#endif
8401
8402 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008403
Greg Clayton7bc39082011-03-24 23:53:38 +00008404 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008405 {
8406 uint32_t Rd, Rn, Rm;
8407 ARM_ShifterType shift_t;
8408 uint32_t shift_n; // the shift applied to the value read from Rm
8409 bool setflags;
8410 uint32_t carry;
8411 switch (encoding)
8412 {
8413 case eEncodingT1:
8414 Rd = Rn = Bits32(opcode, 2, 0);
8415 Rm = Bits32(opcode, 5, 3);
8416 setflags = !InITBlock();
8417 shift_t = SRType_LSL;
8418 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008419 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008420 case eEncodingT2:
8421 Rd = Bits32(opcode, 11, 8);
8422 Rn = Bits32(opcode, 19, 16);
8423 Rm = Bits32(opcode, 3, 0);
8424 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008425 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8426 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008427 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008428 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008429 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8430 return false;
8431 break;
8432 case eEncodingA1:
8433 Rd = Bits32(opcode, 15, 12);
8434 Rn = Bits32(opcode, 19, 16);
8435 Rm = Bits32(opcode, 3, 0);
8436 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008437 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008438
Johnny Chen7c5234d2011-02-18 23:41:11 +00008439 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008440 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008441 break;
8442 default:
8443 return false;
8444 }
8445
8446 // Read the first operand.
8447 uint32_t val1 = ReadCoreReg(Rn, &success);
8448 if (!success)
8449 return false;
8450
8451 // Read the second operand.
8452 uint32_t val2 = ReadCoreReg(Rm, &success);
8453 if (!success)
8454 return false;
8455
8456 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008457 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008458
8459 EmulateInstruction::Context context;
8460 context.type = EmulateInstruction::eContextImmediate;
8461 context.SetNoArgs ();
8462
8463 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8464 return false;
8465 }
8466 return true;
8467}
8468
Johnny Chened32e7c2011-02-22 23:42:58 +00008469// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8470// the destination register. It can optionally update the condition flags based on the result.
8471bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008472EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008473{
8474#if 0
8475 // ARM pseudo code...
8476 if ConditionPassed() then
8477 EncodingSpecificOperations();
8478 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8479 if d == 15 then // Can only occur for ARM encoding
8480 ALUWritePC(result); // setflags is always FALSE here
8481 else
8482 R[d] = result;
8483 if setflags then
8484 APSR.N = result<31>;
8485 APSR.Z = IsZeroBit(result);
8486 APSR.C = carry;
8487 APSR.V = overflow;
8488#endif
8489
8490 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008491
8492 uint32_t Rd; // the destination register
8493 uint32_t Rn; // the first operand
8494 bool setflags;
8495 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8496 switch (encoding) {
8497 case eEncodingT1:
8498 Rd = Bits32(opcode, 2, 0);
8499 Rn = Bits32(opcode, 5, 3);
8500 setflags = !InITBlock();
8501 imm32 = 0;
8502 break;
8503 case eEncodingT2:
8504 Rd = Bits32(opcode, 11, 8);
8505 Rn = Bits32(opcode, 19, 16);
8506 setflags = BitIsSet(opcode, 20);
8507 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8508 if (BadReg(Rd) || BadReg(Rn))
8509 return false;
8510 break;
8511 case eEncodingA1:
8512 Rd = Bits32(opcode, 15, 12);
8513 Rn = Bits32(opcode, 19, 16);
8514 setflags = BitIsSet(opcode, 20);
8515 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008516
Johnny Chened32e7c2011-02-22 23:42:58 +00008517 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008518 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008519 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008520 break;
8521 default:
8522 return false;
8523 }
8524 // Read the register value from the operand register Rn.
8525 uint32_t reg_val = ReadCoreReg(Rn, &success);
8526 if (!success)
8527 return false;
8528
8529 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8530
8531 EmulateInstruction::Context context;
8532 context.type = EmulateInstruction::eContextImmediate;
8533 context.SetNoArgs ();
8534
8535 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8536 return false;
8537
8538 return true;
8539}
8540
8541// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8542// result to the destination register. It can optionally update the condition flags based on the result.
8543bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008544EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008545{
8546#if 0
8547 // ARM pseudo code...
8548 if ConditionPassed() then
8549 EncodingSpecificOperations();
8550 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8551 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8552 if d == 15 then // Can only occur for ARM encoding
8553 ALUWritePC(result); // setflags is always FALSE here
8554 else
8555 R[d] = result;
8556 if setflags then
8557 APSR.N = result<31>;
8558 APSR.Z = IsZeroBit(result);
8559 APSR.C = carry;
8560 APSR.V = overflow;
8561#endif
8562
8563 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008564
8565 uint32_t Rd; // the destination register
8566 uint32_t Rn; // the first operand
8567 uint32_t Rm; // the second operand
8568 bool setflags;
8569 ARM_ShifterType shift_t;
8570 uint32_t shift_n; // the shift applied to the value read from Rm
8571 switch (encoding) {
8572 case eEncodingT1:
8573 Rd = Bits32(opcode, 11, 8);
8574 Rn = Bits32(opcode, 19, 16);
8575 Rm = Bits32(opcode, 3, 0);
8576 setflags = BitIsSet(opcode, 20);
8577 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8578 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8579 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8580 return false;
8581 break;
8582 case eEncodingA1:
8583 Rd = Bits32(opcode, 15, 12);
8584 Rn = Bits32(opcode, 19, 16);
8585 Rm = Bits32(opcode, 3, 0);
8586 setflags = BitIsSet(opcode, 20);
8587 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008588
Johnny Chened32e7c2011-02-22 23:42:58 +00008589 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008590 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008591 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008592 break;
8593 default:
8594 return false;
8595 }
8596 // Read the register value from register Rn.
8597 uint32_t val1 = ReadCoreReg(Rn, &success);
8598 if (!success)
8599 return false;
8600
8601 // Read the register value from register Rm.
8602 uint32_t val2 = ReadCoreReg(Rm, &success);
8603 if (!success)
8604 return false;
8605
8606 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8607 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8608
8609 EmulateInstruction::Context context;
8610 context.type = EmulateInstruction::eContextImmediate;
8611 context.SetNoArgs();
8612 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8613 return false;
8614
8615 return true;
8616}
8617
Johnny Chen90e607b2011-02-23 00:07:09 +00008618// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8619// an immediate value, and writes the result to the destination register. It can optionally update the condition
8620// flags based on the result.
8621bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008622EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008623{
8624#if 0
8625 // ARM pseudo code...
8626 if ConditionPassed() then
8627 EncodingSpecificOperations();
8628 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8629 if d == 15 then
8630 ALUWritePC(result); // setflags is always FALSE here
8631 else
8632 R[d] = result;
8633 if setflags then
8634 APSR.N = result<31>;
8635 APSR.Z = IsZeroBit(result);
8636 APSR.C = carry;
8637 APSR.V = overflow;
8638#endif
8639
8640 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008641
8642 uint32_t Rd; // the destination register
8643 uint32_t Rn; // the first operand
8644 bool setflags;
8645 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8646 switch (encoding) {
8647 case eEncodingA1:
8648 Rd = Bits32(opcode, 15, 12);
8649 Rn = Bits32(opcode, 19, 16);
8650 setflags = BitIsSet(opcode, 20);
8651 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008652
Johnny Chen90e607b2011-02-23 00:07:09 +00008653 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008654 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008655 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008656 break;
8657 default:
8658 return false;
8659 }
8660 // Read the register value from the operand register Rn.
8661 uint32_t reg_val = ReadCoreReg(Rn, &success);
8662 if (!success)
8663 return false;
8664
8665 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8666
8667 EmulateInstruction::Context context;
8668 context.type = EmulateInstruction::eContextImmediate;
8669 context.SetNoArgs ();
8670
8671 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8672 return false;
8673
8674 return true;
8675}
8676
8677// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8678// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8679// condition flags based on the result.
8680bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008681EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008682{
8683#if 0
8684 // ARM pseudo code...
8685 if ConditionPassed() then
8686 EncodingSpecificOperations();
8687 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8688 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8689 if d == 15 then
8690 ALUWritePC(result); // setflags is always FALSE here
8691 else
8692 R[d] = result;
8693 if setflags then
8694 APSR.N = result<31>;
8695 APSR.Z = IsZeroBit(result);
8696 APSR.C = carry;
8697 APSR.V = overflow;
8698#endif
8699
8700 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008701
8702 uint32_t Rd; // the destination register
8703 uint32_t Rn; // the first operand
8704 uint32_t Rm; // the second operand
8705 bool setflags;
8706 ARM_ShifterType shift_t;
8707 uint32_t shift_n; // the shift applied to the value read from Rm
8708 switch (encoding) {
8709 case eEncodingA1:
8710 Rd = Bits32(opcode, 15, 12);
8711 Rn = Bits32(opcode, 19, 16);
8712 Rm = Bits32(opcode, 3, 0);
8713 setflags = BitIsSet(opcode, 20);
8714 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008715
Johnny Chen90e607b2011-02-23 00:07:09 +00008716 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008717 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008718 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008719 break;
8720 default:
8721 return false;
8722 }
8723 // Read the register value from register Rn.
8724 uint32_t val1 = ReadCoreReg(Rn, &success);
8725 if (!success)
8726 return false;
8727
8728 // Read the register value from register Rm.
8729 uint32_t val2 = ReadCoreReg(Rm, &success);
8730 if (!success)
8731 return false;
8732
8733 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8734 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8735
8736 EmulateInstruction::Context context;
8737 context.type = EmulateInstruction::eContextImmediate;
8738 context.SetNoArgs();
8739 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8740 return false;
8741
8742 return true;
8743}
8744
Johnny Chen9b381772011-02-23 01:01:21 +00008745// Subtract with Carry (immediate) subtracts an immediate value and the value of
8746// NOT (Carry flag) from a register value, and writes the result to the destination register.
8747// It can optionally update the condition flags based on the result.
8748bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008749EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008750{
8751#if 0
8752 // ARM pseudo code...
8753 if ConditionPassed() then
8754 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008755 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008756 if d == 15 then // Can only occur for ARM encoding
8757 ALUWritePC(result); // setflags is always FALSE here
8758 else
8759 R[d] = result;
8760 if setflags then
8761 APSR.N = result<31>;
8762 APSR.Z = IsZeroBit(result);
8763 APSR.C = carry;
8764 APSR.V = overflow;
8765#endif
8766
8767 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008768
8769 uint32_t Rd; // the destination register
8770 uint32_t Rn; // the first operand
8771 bool setflags;
8772 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8773 switch (encoding) {
8774 case eEncodingT1:
8775 Rd = Bits32(opcode, 11, 8);
8776 Rn = Bits32(opcode, 19, 16);
8777 setflags = BitIsSet(opcode, 20);
8778 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8779 if (BadReg(Rd) || BadReg(Rn))
8780 return false;
8781 break;
8782 case eEncodingA1:
8783 Rd = Bits32(opcode, 15, 12);
8784 Rn = Bits32(opcode, 19, 16);
8785 setflags = BitIsSet(opcode, 20);
8786 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008787
Johnny Chen9b381772011-02-23 01:01:21 +00008788 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008789 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008790 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008791 break;
8792 default:
8793 return false;
8794 }
8795 // Read the register value from the operand register Rn.
8796 uint32_t reg_val = ReadCoreReg(Rn, &success);
8797 if (!success)
8798 return false;
8799
8800 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8801
8802 EmulateInstruction::Context context;
8803 context.type = EmulateInstruction::eContextImmediate;
8804 context.SetNoArgs ();
8805
8806 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8807 return false;
8808
8809 return true;
8810}
8811
8812// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8813// NOT (Carry flag) from a register value, and writes the result to the destination register.
8814// It can optionally update the condition flags based on the result.
8815bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008816EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008817{
8818#if 0
8819 // ARM pseudo code...
8820 if ConditionPassed() then
8821 EncodingSpecificOperations();
8822 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8823 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8824 if d == 15 then // Can only occur for ARM encoding
8825 ALUWritePC(result); // setflags is always FALSE here
8826 else
8827 R[d] = result;
8828 if setflags then
8829 APSR.N = result<31>;
8830 APSR.Z = IsZeroBit(result);
8831 APSR.C = carry;
8832 APSR.V = overflow;
8833#endif
8834
8835 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008836
8837 uint32_t Rd; // the destination register
8838 uint32_t Rn; // the first operand
8839 uint32_t Rm; // the second operand
8840 bool setflags;
8841 ARM_ShifterType shift_t;
8842 uint32_t shift_n; // the shift applied to the value read from Rm
8843 switch (encoding) {
8844 case eEncodingT1:
8845 Rd = Rn = Bits32(opcode, 2, 0);
8846 Rm = Bits32(opcode, 5, 3);
8847 setflags = !InITBlock();
8848 shift_t = SRType_LSL;
8849 shift_n = 0;
8850 break;
8851 case eEncodingT2:
8852 Rd = Bits32(opcode, 11, 8);
8853 Rn = Bits32(opcode, 19, 16);
8854 Rm = Bits32(opcode, 3, 0);
8855 setflags = BitIsSet(opcode, 20);
8856 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8857 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8858 return false;
8859 break;
8860 case eEncodingA1:
8861 Rd = Bits32(opcode, 15, 12);
8862 Rn = Bits32(opcode, 19, 16);
8863 Rm = Bits32(opcode, 3, 0);
8864 setflags = BitIsSet(opcode, 20);
8865 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008866
Johnny Chen9b381772011-02-23 01:01:21 +00008867 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008868 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008869 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008870 break;
8871 default:
8872 return false;
8873 }
8874 // Read the register value from register Rn.
8875 uint32_t val1 = ReadCoreReg(Rn, &success);
8876 if (!success)
8877 return false;
8878
8879 // Read the register value from register Rm.
8880 uint32_t val2 = ReadCoreReg(Rm, &success);
8881 if (!success)
8882 return false;
8883
8884 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8885 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8886
8887 EmulateInstruction::Context context;
8888 context.type = EmulateInstruction::eContextImmediate;
8889 context.SetNoArgs();
8890 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8891 return false;
8892
8893 return true;
8894}
8895
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008896// This instruction subtracts an immediate value from a register value, and writes the result
8897// to the destination register. It can optionally update the condition flags based on the result.
8898bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008899EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008900{
8901#if 0
8902 // ARM pseudo code...
8903 if ConditionPassed() then
8904 EncodingSpecificOperations();
8905 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8906 R[d] = result;
8907 if setflags then
8908 APSR.N = result<31>;
8909 APSR.Z = IsZeroBit(result);
8910 APSR.C = carry;
8911 APSR.V = overflow;
8912#endif
8913
8914 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008915
8916 uint32_t Rd; // the destination register
8917 uint32_t Rn; // the first operand
8918 bool setflags;
8919 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8920 switch (encoding) {
8921 case eEncodingT1:
8922 Rd = Bits32(opcode, 2, 0);
8923 Rn = Bits32(opcode, 5, 3);
8924 setflags = !InITBlock();
8925 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8926 break;
8927 case eEncodingT2:
8928 Rd = Rn = Bits32(opcode, 10, 8);
8929 setflags = !InITBlock();
8930 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8931 break;
8932 case eEncodingT3:
8933 Rd = Bits32(opcode, 11, 8);
8934 Rn = Bits32(opcode, 19, 16);
8935 setflags = BitIsSet(opcode, 20);
8936 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8937
8938 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8939 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008940 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008941
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008942 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008943 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008944 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008945
8946 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8947 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8948 return false;
8949 break;
8950 case eEncodingT4:
8951 Rd = Bits32(opcode, 11, 8);
8952 Rn = Bits32(opcode, 19, 16);
8953 setflags = BitIsSet(opcode, 20);
8954 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8955
8956 // if Rn == '1111' then SEE ADR;
8957 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008958 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008959
8960 // if Rn == '1101' then SEE SUB (SP minus immediate);
8961 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008962 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008963
8964 if (BadReg(Rd))
8965 return false;
8966 break;
8967 default:
8968 return false;
8969 }
8970 // Read the register value from the operand register Rn.
8971 uint32_t reg_val = ReadCoreReg(Rn, &success);
8972 if (!success)
8973 return false;
8974
8975 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8976
8977 EmulateInstruction::Context context;
8978 context.type = EmulateInstruction::eContextImmediate;
8979 context.SetNoArgs ();
8980
8981 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8982 return false;
8983
8984 return true;
8985}
8986
8987// This instruction subtracts an immediate value from a register value, and writes the result
8988// to the destination register. It can optionally update the condition flags based on the result.
8989bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008990EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008991{
8992#if 0
8993 // ARM pseudo code...
8994 if ConditionPassed() then
8995 EncodingSpecificOperations();
8996 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8997 if d == 15 then
8998 ALUWritePC(result); // setflags is always FALSE here
8999 else
9000 R[d] = result;
9001 if setflags then
9002 APSR.N = result<31>;
9003 APSR.Z = IsZeroBit(result);
9004 APSR.C = carry;
9005 APSR.V = overflow;
9006#endif
9007
9008 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009009
9010 uint32_t Rd; // the destination register
9011 uint32_t Rn; // the first operand
9012 bool setflags;
9013 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9014 switch (encoding) {
9015 case eEncodingA1:
9016 Rd = Bits32(opcode, 15, 12);
9017 Rn = Bits32(opcode, 19, 16);
9018 setflags = BitIsSet(opcode, 20);
9019 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9020
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009021 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009022 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00009023 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009024
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009025 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009026 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009027 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009028
9029 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009030 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00009031 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009032 break;
9033 default:
9034 return false;
9035 }
9036 // Read the register value from the operand register Rn.
9037 uint32_t reg_val = ReadCoreReg(Rn, &success);
9038 if (!success)
9039 return false;
9040
9041 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9042
9043 EmulateInstruction::Context context;
9044 context.type = EmulateInstruction::eContextImmediate;
9045 context.SetNoArgs ();
9046
9047 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9048 return false;
9049
9050 return true;
9051}
9052
Johnny Chen2115b412011-02-21 23:42:44 +00009053// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9054// immediate value. It updates the condition flags based on the result, and discards the result.
9055bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009056EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009057{
9058#if 0
9059 // ARM pseudo code...
9060 if ConditionPassed() then
9061 EncodingSpecificOperations();
9062 result = R[n] EOR imm32;
9063 APSR.N = result<31>;
9064 APSR.Z = IsZeroBit(result);
9065 APSR.C = carry;
9066 // APSR.V unchanged
9067#endif
9068
9069 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009070
Greg Clayton7bc39082011-03-24 23:53:38 +00009071 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009072 {
9073 uint32_t Rn;
9074 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9075 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9076 switch (encoding)
9077 {
9078 case eEncodingT1:
9079 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009080 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009081 if (BadReg(Rn))
9082 return false;
9083 break;
9084 case eEncodingA1:
9085 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009086 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009087 break;
9088 default:
9089 return false;
9090 }
9091
9092 // Read the first operand.
9093 uint32_t val1 = ReadCoreReg(Rn, &success);
9094 if (!success)
9095 return false;
9096
9097 uint32_t result = val1 ^ imm32;
9098
9099 EmulateInstruction::Context context;
9100 context.type = EmulateInstruction::eContextImmediate;
9101 context.SetNoArgs ();
9102
9103 if (!WriteFlags(context, result, carry))
9104 return false;
9105 }
9106 return true;
9107}
9108
9109// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9110// optionally-shifted register value. It updates the condition flags based on the result, and discards
9111// the result.
9112bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009113EmulateInstructionARM::EmulateTEQReg (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 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9120 result = R[n] EOR shifted;
9121 APSR.N = result<31>;
9122 APSR.Z = IsZeroBit(result);
9123 APSR.C = carry;
9124 // APSR.V unchanged
9125#endif
9126
9127 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009128
Greg Clayton7bc39082011-03-24 23:53:38 +00009129 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009130 {
9131 uint32_t Rn, Rm;
9132 ARM_ShifterType shift_t;
9133 uint32_t shift_n; // the shift applied to the value read from Rm
9134 uint32_t carry;
9135 switch (encoding)
9136 {
9137 case eEncodingT1:
9138 Rn = Bits32(opcode, 19, 16);
9139 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009140 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009141 if (BadReg(Rn) || BadReg(Rm))
9142 return false;
9143 break;
9144 case eEncodingA1:
9145 Rn = Bits32(opcode, 19, 16);
9146 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009147 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009148 break;
9149 default:
9150 return false;
9151 }
9152
9153 // Read the first operand.
9154 uint32_t val1 = ReadCoreReg(Rn, &success);
9155 if (!success)
9156 return false;
9157
9158 // Read the second operand.
9159 uint32_t val2 = ReadCoreReg(Rm, &success);
9160 if (!success)
9161 return false;
9162
9163 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9164 uint32_t result = val1 ^ shifted;
9165
9166 EmulateInstruction::Context context;
9167 context.type = EmulateInstruction::eContextImmediate;
9168 context.SetNoArgs ();
9169
9170 if (!WriteFlags(context, result, carry))
9171 return false;
9172 }
9173 return true;
9174}
9175
Johnny Chende3cce32011-02-21 21:24:49 +00009176// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9177// It updates the condition flags based on the result, and discards the result.
9178bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009179EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009180{
9181#if 0
9182 // ARM pseudo code...
9183 if ConditionPassed() then
9184 EncodingSpecificOperations();
9185 result = R[n] AND imm32;
9186 APSR.N = result<31>;
9187 APSR.Z = IsZeroBit(result);
9188 APSR.C = carry;
9189 // APSR.V unchanged
9190#endif
9191
9192 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009193
Greg Clayton7bc39082011-03-24 23:53:38 +00009194 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009195 {
9196 uint32_t Rn;
9197 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9198 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9199 switch (encoding)
9200 {
9201 case eEncodingT1:
9202 Rn = Bits32(opcode, 19, 16);
9203 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9204 if (BadReg(Rn))
9205 return false;
9206 break;
9207 case eEncodingA1:
9208 Rn = Bits32(opcode, 19, 16);
9209 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9210 break;
9211 default:
9212 return false;
9213 }
9214
9215 // Read the first operand.
9216 uint32_t val1 = ReadCoreReg(Rn, &success);
9217 if (!success)
9218 return false;
9219
9220 uint32_t result = val1 & imm32;
9221
9222 EmulateInstruction::Context context;
9223 context.type = EmulateInstruction::eContextImmediate;
9224 context.SetNoArgs ();
9225
9226 if (!WriteFlags(context, result, carry))
9227 return false;
9228 }
9229 return true;
9230}
9231
9232// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9233// It updates the condition flags based on the result, and discards the result.
9234bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009235EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009236{
9237#if 0
9238 // ARM pseudo code...
9239 if ConditionPassed() then
9240 EncodingSpecificOperations();
9241 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9242 result = R[n] AND shifted;
9243 APSR.N = result<31>;
9244 APSR.Z = IsZeroBit(result);
9245 APSR.C = carry;
9246 // APSR.V unchanged
9247#endif
9248
9249 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009250
Greg Clayton7bc39082011-03-24 23:53:38 +00009251 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009252 {
9253 uint32_t Rn, Rm;
9254 ARM_ShifterType shift_t;
9255 uint32_t shift_n; // the shift applied to the value read from Rm
9256 uint32_t carry;
9257 switch (encoding)
9258 {
9259 case eEncodingT1:
9260 Rn = Bits32(opcode, 2, 0);
9261 Rm = Bits32(opcode, 5, 3);
9262 shift_t = SRType_LSL;
9263 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009264 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009265 case eEncodingT2:
9266 Rn = Bits32(opcode, 19, 16);
9267 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009268 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009269 if (BadReg(Rn) || BadReg(Rm))
9270 return false;
9271 break;
9272 case eEncodingA1:
9273 Rn = Bits32(opcode, 19, 16);
9274 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009275 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009276 break;
9277 default:
9278 return false;
9279 }
9280
9281 // Read the first operand.
9282 uint32_t val1 = ReadCoreReg(Rn, &success);
9283 if (!success)
9284 return false;
9285
9286 // Read the second operand.
9287 uint32_t val2 = ReadCoreReg(Rm, &success);
9288 if (!success)
9289 return false;
9290
9291 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9292 uint32_t result = val1 & shifted;
9293
9294 EmulateInstruction::Context context;
9295 context.type = EmulateInstruction::eContextImmediate;
9296 context.SetNoArgs ();
9297
9298 if (!WriteFlags(context, result, carry))
9299 return false;
9300 }
9301 return true;
9302}
Caroline Ticed05b4902011-03-29 21:24:06 +00009303
9304// A8.6.216 SUB (SP minus register)
9305bool
9306EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9307{
9308#if 0
9309 if ConditionPassed() then
9310 EncodingSpecificOperations();
9311 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009312 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009313 if d == 15 then // Can only occur for ARM encoding
9314 ALUWritePC(result); // setflags is always FALSE here
9315 else
9316 R[d] = result;
9317 if setflags then
9318 APSR.N = result<31>;
9319 APSR.Z = IsZeroBit(result);
9320 APSR.C = carry;
9321 APSR.V = overflow;
9322#endif
9323
9324 bool success = false;
9325
9326 if (ConditionPassed(opcode))
9327 {
9328 uint32_t d;
9329 uint32_t m;
9330 bool setflags;
9331 ARM_ShifterType shift_t;
9332 uint32_t shift_n;
9333
9334 switch (encoding)
9335 {
9336 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009337 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009338 d = Bits32 (opcode, 11, 8);
9339 m = Bits32 (opcode, 3, 0);
9340 setflags = BitIsSet (opcode, 20);
9341
9342 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9343 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9344
9345 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9346 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9347 return false;
9348
9349 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9350 if ((d == 15) || BadReg (m))
9351 return false;
9352 break;
9353
9354 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009355 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009356 d = Bits32 (opcode, 15, 12);
9357 m = Bits32 (opcode, 3, 0);
9358 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009359
Greg Clayton061b79d2011-05-09 20:18:18 +00009360 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009361 if (d == 15 && setflags)
9362 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009363
9364 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9365 shift_n = DecodeImmShiftARM (opcode, shift_t);
9366 break;
9367
9368 default:
9369 return false;
9370 }
9371
9372 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9373 uint32_t Rm = ReadCoreReg (m, &success);
9374 if (!success)
9375 return false;
9376
9377 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9378
Greg Clayton061b79d2011-05-09 20:18:18 +00009379 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009380 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9381 if (!success)
9382 return false;
9383
9384 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9385
9386 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009387 context.type = eContextArithmetic;
9388 RegisterInfo sp_reg;
9389 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9390 RegisterInfo dwarf_reg;
9391 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +00009392 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9393
Caroline Ticeef440002011-03-30 05:40:56 +00009394 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009395 return false;
9396 }
9397 return true;
9398}
9399
9400
9401// A8.6.7 ADD (register-shifted register)
9402bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009403EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009404{
9405#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009406 if ConditionPassed() then
9407 EncodingSpecificOperations();
9408 shift_n = UInt(R[s]<7:0>);
9409 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009410 (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009411 R[d] = result;
9412 if setflags then
9413 APSR.N = result<31>;
9414 APSR.Z = IsZeroBit(result);
9415 APSR.C = carry;
9416 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009417#endif
9418
Caroline Ticec08ed382011-03-29 23:03:16 +00009419 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009420
9421 if (ConditionPassed(opcode))
9422 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009423 uint32_t d;
9424 uint32_t n;
9425 uint32_t m;
9426 uint32_t s;
9427 bool setflags;
9428 ARM_ShifterType shift_t;
9429
Caroline Ticed05b4902011-03-29 21:24:06 +00009430 switch (encoding)
9431 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009432 case eEncodingA1:
9433 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9434 d = Bits32 (opcode, 15, 12);
9435 n = Bits32 (opcode, 19, 16);
9436 m = Bits32 (opcode, 3, 0);
9437 s = Bits32 (opcode, 11, 8);
9438
Greg Clayton061b79d2011-05-09 20:18:18 +00009439 // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
Caroline Ticec08ed382011-03-29 23:03:16 +00009440 setflags = BitIsSet (opcode, 20);
9441 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9442
9443 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9444 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9445 return false;
9446 break;
9447
9448 default:
9449 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009450 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009451
9452 // shift_n = UInt(R[s]<7:0>);
9453 uint32_t Rs = ReadCoreReg (s, &success);
9454 if (!success)
9455 return false;
9456
9457 uint32_t shift_n = Bits32 (Rs, 7, 0);
9458
9459 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9460 uint32_t Rm = ReadCoreReg (m, &success);
9461 if (!success)
9462 return false;
9463
9464 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9465
Greg Clayton061b79d2011-05-09 20:18:18 +00009466 // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009467 uint32_t Rn = ReadCoreReg (n, &success);
9468 if (!success)
9469 return false;
9470
9471 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9472
9473 // R[d] = result;
9474 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009475 context.type = eContextArithmetic;
9476 RegisterInfo reg_n;
9477 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9478 RegisterInfo reg_m;
9479 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009480
9481 context.SetRegisterRegisterOperands (reg_n, reg_m);
9482
9483 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9484 return false;
9485
9486 // if setflags then
9487 // APSR.N = result<31>;
9488 // APSR.Z = IsZeroBit(result);
9489 // APSR.C = carry;
9490 // APSR.V = overflow;
9491 if (setflags)
9492 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009493 }
9494 return true;
9495}
9496
9497// A8.6.213 SUB (register)
9498bool
9499EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9500{
9501#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009502 if ConditionPassed() then
9503 EncodingSpecificOperations();
9504 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009505 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009506 if d == 15 then // Can only occur for ARM encoding
9507 ALUWritePC(result); // setflags is always FALSE here
9508 else
9509 R[d] = result;
9510 if setflags then
9511 APSR.N = result<31>;
9512 APSR.Z = IsZeroBit(result);
9513 APSR.C = carry;
9514 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009515#endif
9516
Caroline Tice4cccd532011-03-29 23:44:20 +00009517 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009518
9519 if (ConditionPassed(opcode))
9520 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009521 uint32_t d;
9522 uint32_t n;
9523 uint32_t m;
9524 bool setflags;
9525 ARM_ShifterType shift_t;
9526 uint32_t shift_n;
9527
Caroline Ticed05b4902011-03-29 21:24:06 +00009528 switch (encoding)
9529 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009530 case eEncodingT1:
9531 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9532 d = Bits32 (opcode, 2, 0);
9533 n = Bits32 (opcode, 5, 3);
9534 m = Bits32 (opcode, 8, 6);
9535 setflags = !InITBlock();
9536
9537 // (shift_t, shift_n) = (SRType_LSL, 0);
9538 shift_t = SRType_LSL;
9539 shift_n = 0;
9540
9541 break;
9542
9543 case eEncodingT2:
Greg Clayton061b79d2011-05-09 20:18:18 +00009544 // if Rd == Ô1111Õ && S == Ô1Õ then SEE CMP (register);
9545 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9546 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009547 d = Bits32 (opcode, 11, 8);
9548 n = Bits32 (opcode, 19, 16);
9549 m = Bits32 (opcode, 3, 0);
9550 setflags = BitIsSet (opcode, 20);
9551
9552 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9553 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9554
9555 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9556 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9557 return false;
9558
9559 break;
9560
9561 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009562 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9563 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009564 d = Bits32 (opcode, 15, 12);
9565 n = Bits32 (opcode, 19, 16);
9566 m = Bits32 (opcode, 3, 0);
9567 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009568
Greg Clayton061b79d2011-05-09 20:18:18 +00009569 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009570 if ((d == 15) && setflags)
9571 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009572
9573 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9574 shift_n = DecodeImmShiftARM (opcode, shift_t);
9575
9576 break;
9577
9578 default:
9579 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009580 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009581
9582 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9583 uint32_t Rm = ReadCoreReg (m, &success);
9584 if (!success)
9585 return false;
9586
9587 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9588
Greg Clayton061b79d2011-05-09 20:18:18 +00009589 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009590 uint32_t Rn = ReadCoreReg (n, &success);
9591 if (!success)
9592 return false;
9593
9594 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9595
9596 // if d == 15 then // Can only occur for ARM encoding
9597 // ALUWritePC(result); // setflags is always FALSE here
9598 // else
9599 // R[d] = result;
9600 // if setflags then
9601 // APSR.N = result<31>;
9602 // APSR.Z = IsZeroBit(result);
9603 // APSR.C = carry;
9604 // APSR.V = overflow;
9605
9606 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009607 context.type = eContextArithmetic;
9608 RegisterInfo reg_n;
9609 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9610 RegisterInfo reg_m;
9611 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009612 context.SetRegisterRegisterOperands (reg_n, reg_m);
9613
Caroline Ticeef440002011-03-30 05:40:56 +00009614 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009615 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009616 }
9617 return true;
9618}
Caroline Tice4cccd532011-03-29 23:44:20 +00009619
Caroline Ticed05b4902011-03-29 21:24:06 +00009620// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009621// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9622// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009623bool
9624EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9625{
9626#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009627 if ConditionPassed() then
9628 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9629 address = R[n] + imm32;
9630 if ExclusiveMonitorsPass(address,4) then
9631 MemA[address,4] = R[t];
9632 R[d] = 0;
9633 else
9634 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009635#endif
9636
Caroline Tice5168b6c2011-03-30 05:15:46 +00009637 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009638
9639 if (ConditionPassed(opcode))
9640 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009641 uint32_t d;
9642 uint32_t t;
9643 uint32_t n;
9644 uint32_t imm32;
9645 const uint32_t addr_byte_size = GetAddressByteSize();
9646
Caroline Ticed05b4902011-03-29 21:24:06 +00009647 switch (encoding)
9648 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009649 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009650 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009651 d = Bits32 (opcode, 11, 8);
9652 t = Bits32 (opcode, 15, 12);
9653 n = Bits32 (opcode, 19, 16);
9654 imm32 = Bits32 (opcode, 7, 0) << 2;
9655
9656 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9657 if (BadReg (d) || BadReg (t) || (n == 15))
9658 return false;
9659
9660 // if d == n || d == t then UNPREDICTABLE;
9661 if ((d == n) || (d == t))
9662 return false;
9663
9664 break;
9665
9666 case eEncodingA1:
9667 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9668 d = Bits32 (opcode, 15, 12);
9669 t = Bits32 (opcode, 3, 0);
9670 n = Bits32 (opcode, 19, 16);
9671 imm32 = 0;
9672
9673 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9674 if ((d == 15) || (t == 15) || (n == 15))
9675 return false;
9676
9677 // if d == n || d == t then UNPREDICTABLE;
9678 if ((d == n) || (d == t))
9679 return false;
9680
9681 break;
9682
9683 default:
9684 return false;
9685 }
9686
9687 // address = R[n] + imm32;
9688 uint32_t Rn = ReadCoreReg (n, &success);
9689 if (!success)
9690 return false;
9691
9692 addr_t address = Rn + imm32;
9693
Greg Claytonc07d4512011-04-26 23:48:45 +00009694 RegisterInfo base_reg;
9695 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9696 RegisterInfo data_reg;
9697 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009698 EmulateInstruction::Context context;
9699 context.type = eContextRegisterStore;
9700 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9701
9702 // if ExclusiveMonitorsPass(address,4) then
9703 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9704 // always return true.
9705 if (true)
9706 {
9707 // MemA[address,4] = R[t];
9708 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9709 if (!success)
9710 return false;
9711
9712 if (!MemAWrite (context, address, Rt, addr_byte_size))
9713 return false;
9714
9715 // R[d] = 0;
9716 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9717 return false;
9718 }
9719 else
9720 {
9721 // R[d] = 1;
9722 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9723 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009724 }
9725 }
9726 return true;
9727}
9728
9729// A8.6.197 STRB (immediate, ARM)
9730bool
9731EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9732{
9733#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009734 if ConditionPassed() then
9735 EncodingSpecificOperations();
9736 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9737 address = if index then offset_addr else R[n];
9738 MemU[address,1] = R[t]<7:0>;
9739 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009740#endif
9741
Caroline Ticeef440002011-03-30 05:40:56 +00009742 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009743
9744 if (ConditionPassed(opcode))
9745 {
Caroline Ticeef440002011-03-30 05:40:56 +00009746 uint32_t t;
9747 uint32_t n;
9748 uint32_t imm32;
9749 bool index;
9750 bool add;
9751 bool wback;
9752
Caroline Ticed05b4902011-03-29 21:24:06 +00009753 switch (encoding)
9754 {
Caroline Ticeef440002011-03-30 05:40:56 +00009755 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009756 // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
Caroline Ticeef440002011-03-30 05:40:56 +00009757 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9758 t = Bits32 (opcode, 15, 12);
9759 n = Bits32 (opcode, 19, 16);
9760 imm32 = Bits32 (opcode, 11, 0);
9761
Greg Clayton061b79d2011-05-09 20:18:18 +00009762 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeef440002011-03-30 05:40:56 +00009763 index = BitIsSet (opcode, 24);
9764 add = BitIsSet (opcode, 23);
9765 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9766
9767 // if t == 15 then UNPREDICTABLE;
9768 if (t == 15)
9769 return false;
9770
9771 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9772 if (wback && ((n == 15) || (n == t)))
9773 return false;
9774
9775 break;
9776
9777 default:
9778 return false;
9779 }
9780
9781 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9782 uint32_t Rn = ReadCoreReg (n, &success);
9783 if (!success)
9784 return false;
9785
9786 addr_t offset_addr;
9787 if (add)
9788 offset_addr = Rn + imm32;
9789 else
9790 offset_addr = Rn - imm32;
9791
9792 // address = if index then offset_addr else R[n];
9793 addr_t address;
9794 if (index)
9795 address = offset_addr;
9796 else
9797 address = Rn;
9798
9799 // MemU[address,1] = R[t]<7:0>;
9800 uint32_t Rt = ReadCoreReg (t, &success);
9801 if (!success)
9802 return false;
9803
Greg Claytonc07d4512011-04-26 23:48:45 +00009804 RegisterInfo base_reg;
9805 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9806 RegisterInfo data_reg;
9807 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticeef440002011-03-30 05:40:56 +00009808 EmulateInstruction::Context context;
9809 context.type = eContextRegisterStore;
9810 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9811
9812 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9813 return false;
9814
9815 // if wback then R[n] = offset_addr;
9816 if (wback)
9817 {
Caroline Tice523c5542011-04-13 00:42:12 +00009818 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009819 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009820 }
9821 }
9822 return true;
9823}
9824
9825// A8.6.194 STR (immediate, ARM)
9826bool
9827EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9828{
9829#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009830 if ConditionPassed() then
9831 EncodingSpecificOperations();
9832 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9833 address = if index then offset_addr else R[n];
9834 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9835 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009836#endif
9837
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009838 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009839
9840 if (ConditionPassed(opcode))
9841 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009842 uint32_t t;
9843 uint32_t n;
9844 uint32_t imm32;
9845 bool index;
9846 bool add;
9847 bool wback;
9848
9849 const uint32_t addr_byte_size = GetAddressByteSize();
9850
Caroline Ticed05b4902011-03-29 21:24:06 +00009851 switch (encoding)
9852 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009853 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009854 // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
9855 // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009856 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9857 t = Bits32 (opcode, 15, 12);
9858 n = Bits32 (opcode, 19, 16);
9859 imm32 = Bits32 (opcode, 11, 0);
9860
Greg Clayton061b79d2011-05-09 20:18:18 +00009861 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009862 index = BitIsSet (opcode, 24);
9863 add = BitIsSet (opcode, 23);
9864 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9865
9866 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9867 if (wback && ((n == 15) || (n == t)))
9868 return false;
9869
9870 break;
9871
9872 default:
9873 return false;
9874 }
9875
9876 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9877 uint32_t Rn = ReadCoreReg (n, &success);
9878 if (!success)
9879 return false;
9880
9881 addr_t offset_addr;
9882 if (add)
9883 offset_addr = Rn + imm32;
9884 else
9885 offset_addr = Rn - imm32;
9886
9887 // address = if index then offset_addr else R[n];
9888 addr_t address;
9889 if (index)
9890 address = offset_addr;
9891 else
9892 address = Rn;
9893
Greg Claytonc07d4512011-04-26 23:48:45 +00009894 RegisterInfo base_reg;
9895 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9896 RegisterInfo data_reg;
9897 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009898 EmulateInstruction::Context context;
9899 context.type = eContextRegisterStore;
9900 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9901
9902 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9903 uint32_t Rt = ReadCoreReg (t, &success);
9904 if (!success)
9905 return false;
9906
9907 if (t == 15)
9908 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009909 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009910 if (!success)
9911 return false;
9912
9913 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9914 return false;
9915 }
9916 else
9917 {
9918 if (!MemUWrite (context, address, Rt, addr_byte_size))
9919 return false;
9920 }
9921
9922 // if wback then R[n] = offset_addr;
9923 if (wback)
9924 {
9925 context.type = eContextAdjustBaseRegister;
9926 context.SetImmediate (offset_addr);
9927
9928 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9929 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009930 }
9931 }
9932 return true;
9933}
9934
Caroline Ticed05b4902011-03-29 21:24:06 +00009935// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009936// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9937// 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 +00009938bool
9939EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9940{
9941#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009942 if ConditionPassed() then
9943 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9944 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9945 address = if index then offset_addr else R[n];
9946 R[t] = MemA[address,4];
9947 R[t2] = MemA[address+4,4];
9948 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009949#endif
9950
Caroline Tice1697dd72011-03-30 17:11:45 +00009951 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009952
9953 if (ConditionPassed(opcode))
9954 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009955 uint32_t t;
9956 uint32_t t2;
9957 uint32_t n;
9958 uint32_t imm32;
9959 bool index;
9960 bool add;
9961 bool wback;
9962
Caroline Ticed05b4902011-03-29 21:24:06 +00009963 switch (encoding)
9964 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009965 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009966 //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
9967 //if Rn == Ô1111Õ then SEE LDRD (literal);
9968 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice1697dd72011-03-30 17:11:45 +00009969 t = Bits32 (opcode, 15, 12);
9970 t2 = Bits32 (opcode, 11, 8);
9971 n = Bits32 (opcode, 19, 16);
9972 imm32 = Bits32 (opcode, 7, 0) << 2;
9973
Greg Clayton061b79d2011-05-09 20:18:18 +00009974 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +00009975 index = BitIsSet (opcode, 24);
9976 add = BitIsSet (opcode, 23);
9977 wback = BitIsSet (opcode, 21);
9978
9979 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9980 if (wback && ((n == t) || (n == t2)))
9981 return false;
9982
9983 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9984 if (BadReg (t) || BadReg (t2) || (t == t2))
9985 return false;
9986
9987 break;
9988
9989 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009990 //if Rn == Ô1111Õ then SEE LDRD (literal);
9991 //if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +00009992 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9993 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009994 if (BitIsSet (t, 0))
9995 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009996 t2 = t + 1;
9997 n = Bits32 (opcode, 19, 16);
9998 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9999
Greg Clayton061b79d2011-05-09 20:18:18 +000010000 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +000010001 index = BitIsSet (opcode, 24);
10002 add = BitIsSet (opcode, 23);
10003 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10004
Greg Clayton061b79d2011-05-09 20:18:18 +000010005 //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010006 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10007 return false;
10008
10009 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10010 if (wback && ((n == t) || (n == t2)))
10011 return false;
10012
10013 //if t2 == 15 then UNPREDICTABLE;
10014 if (t2 == 15)
10015 return false;
10016
10017 break;
10018
10019 default:
10020 return false;
10021 }
10022
10023 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10024 uint32_t Rn = ReadCoreReg (n, &success);
10025 if (!success)
10026 return false;
10027
10028 addr_t offset_addr;
10029 if (add)
10030 offset_addr = Rn + imm32;
10031 else
10032 offset_addr = Rn - imm32;
10033
10034 //address = if index then offset_addr else R[n];
10035 addr_t address;
10036 if (index)
10037 address = offset_addr;
10038 else
10039 address = Rn;
10040
10041 //R[t] = MemA[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +000010042 RegisterInfo base_reg;
10043 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1697dd72011-03-30 17:11:45 +000010044
10045 EmulateInstruction::Context context;
10046 context.type = eContextRegisterLoad;
10047 context.SetRegisterPlusOffset (base_reg, address - Rn);
10048
10049 const uint32_t addr_byte_size = GetAddressByteSize();
10050 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10051 if (!success)
10052 return false;
10053
10054 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10055 return false;
10056
10057 //R[t2] = MemA[address+4,4];
10058
10059 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10060 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10061 if (!success)
10062 return false;
10063
10064 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10065 return false;
10066
10067 //if wback then R[n] = offset_addr;
10068 if (wback)
10069 {
10070 context.type = eContextAdjustBaseRegister;
10071 context.SetAddress (offset_addr);
10072
10073 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10074 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010075 }
10076 }
10077 return true;
10078}
10079
Caroline Ticed05b4902011-03-29 21:24:06 +000010080// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010081// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10082// 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 +000010083bool
10084EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10085{
10086#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010087 if ConditionPassed() then
10088 EncodingSpecificOperations();
10089 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10090 address = if index then offset_addr else R[n];
10091 R[t] = MemA[address,4];
10092 R[t2] = MemA[address+4,4];
10093 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010094#endif
10095
Caroline Ticeeab301f2011-03-30 17:54:52 +000010096 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010097
10098 if (ConditionPassed(opcode))
10099 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010100 uint32_t t;
10101 uint32_t t2;
10102 uint32_t n;
10103 uint32_t m;
10104 bool index;
10105 bool add;
10106 bool wback;
10107
Caroline Ticed05b4902011-03-29 21:24:06 +000010108 switch (encoding)
10109 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010110 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010111 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010112 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10113 t = Bits32 (opcode, 15, 12);
10114 if (BitIsSet (t, 0))
10115 return false;
10116 t2 = t + 1;
10117 n = Bits32 (opcode, 19, 16);
10118 m = Bits32 (opcode, 3, 0);
10119
Greg Clayton061b79d2011-05-09 20:18:18 +000010120 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010121 index = BitIsSet (opcode, 24);
10122 add = BitIsSet (opcode, 23);
10123 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10124
Greg Clayton061b79d2011-05-09 20:18:18 +000010125 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010126 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10127 return false;
10128
10129 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10130 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10131 return false;
10132
10133 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10134 if (wback && ((n == 15) || (n == t) || (n == t2)))
10135 return false;
10136
10137 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10138 if ((ArchVersion() < 6) && wback && (m == n))
10139 return false;
10140 break;
10141
10142 default:
10143 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010144 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010145
Caroline Ticeeab301f2011-03-30 17:54:52 +000010146 uint32_t Rn = ReadCoreReg (n, &success);
10147 if (!success)
10148 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010149 RegisterInfo base_reg;
10150 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010151
Caroline Ticeeab301f2011-03-30 17:54:52 +000010152 uint32_t Rm = ReadCoreReg (m, &success);
10153 if (!success)
10154 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010155 RegisterInfo offset_reg;
10156 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010157
Caroline Ticeeab301f2011-03-30 17:54:52 +000010158 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10159 addr_t offset_addr;
10160 if (add)
10161 offset_addr = Rn + Rm;
10162 else
10163 offset_addr = Rn - Rm;
10164
10165 // address = if index then offset_addr else R[n];
10166 addr_t address;
10167 if (index)
10168 address = offset_addr;
10169 else
10170 address = Rn;
10171
10172 EmulateInstruction::Context context;
10173 context.type = eContextRegisterLoad;
10174 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10175
10176 // R[t] = MemA[address,4];
10177 const uint32_t addr_byte_size = GetAddressByteSize();
10178 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10179 if (!success)
10180 return false;
10181
10182 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10183 return false;
10184
10185 // R[t2] = MemA[address+4,4];
10186
10187 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10188 if (!success)
10189 return false;
10190
10191 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10192 return false;
10193
10194 // if wback then R[n] = offset_addr;
10195 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010196 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010197 context.type = eContextAdjustBaseRegister;
10198 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010199
Caroline Ticeeab301f2011-03-30 17:54:52 +000010200 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10201 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010202 }
10203 }
10204 return true;
10205}
Caroline Ticed05b4902011-03-29 21:24:06 +000010206
10207// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010208// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10209// 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 +000010210bool
10211EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10212{
10213#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010214 if ConditionPassed() then
10215 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10216 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10217 address = if index then offset_addr else R[n];
10218 MemA[address,4] = R[t];
10219 MemA[address+4,4] = R[t2];
10220 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010221#endif
10222
Caroline Tice74467fe2011-03-30 19:02:56 +000010223 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010224
Caroline Tice74467fe2011-03-30 19:02:56 +000010225 if (ConditionPassed(opcode))
10226 {
10227 uint32_t t;
10228 uint32_t t2;
10229 uint32_t n;
10230 uint32_t imm32;
10231 bool index;
10232 bool add;
10233 bool wback;
10234
10235 switch (encoding)
10236 {
10237 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010238 // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10239 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice74467fe2011-03-30 19:02:56 +000010240 t = Bits32 (opcode, 15, 12);
10241 t2 = Bits32 (opcode, 11, 8);
10242 n = Bits32 (opcode, 19, 16);
10243 imm32 = Bits32 (opcode, 7, 0) << 2;
10244
Greg Clayton061b79d2011-05-09 20:18:18 +000010245 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010246 index = BitIsSet (opcode, 24);
10247 add = BitIsSet (opcode, 23);
10248 wback = BitIsSet (opcode, 21);
10249
10250 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10251 if (wback && ((n == t) || (n == t2)))
10252 return false;
10253
10254 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10255 if ((n == 15) || BadReg (t) || BadReg (t2))
10256 return false;
10257
10258 break;
10259
10260 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010261 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010262 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10263 t = Bits32 (opcode, 15, 12);
10264 if (BitIsSet (t, 0))
10265 return false;
10266
10267 t2 = t + 1;
10268 n = Bits32 (opcode, 19, 16);
10269 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10270
Greg Clayton061b79d2011-05-09 20:18:18 +000010271 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010272 index = BitIsSet (opcode, 24);
10273 add = BitIsSet (opcode, 23);
10274 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10275
Greg Clayton061b79d2011-05-09 20:18:18 +000010276 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010277 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10278 return false;
10279
10280 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10281 if (wback && ((n == 15) || (n == t) || (n == t2)))
10282 return false;
10283
10284 // if t2 == 15 then UNPREDICTABLE;
10285 if (t2 == 15)
10286 return false;
10287
10288 break;
10289
10290 default:
10291 return false;
10292 }
10293
Greg Claytonc07d4512011-04-26 23:48:45 +000010294 RegisterInfo base_reg;
10295 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010296
10297 uint32_t Rn = ReadCoreReg (n, &success);
10298 if (!success)
10299 return false;
10300
10301 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10302 addr_t offset_addr;
10303 if (add)
10304 offset_addr = Rn + imm32;
10305 else
10306 offset_addr = Rn - imm32;
10307
10308 //address = if index then offset_addr else R[n];
10309 addr_t address;
10310 if (index)
10311 address = offset_addr;
10312 else
10313 address = Rn;
10314
10315 //MemA[address,4] = R[t];
Greg Claytonc07d4512011-04-26 23:48:45 +000010316 RegisterInfo data_reg;
10317 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010318
10319 uint32_t data = ReadCoreReg (t, &success);
10320 if (!success)
10321 return false;
10322
10323 EmulateInstruction::Context context;
10324 context.type = eContextRegisterStore;
10325 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10326
10327 const uint32_t addr_byte_size = GetAddressByteSize();
10328
10329 if (!MemAWrite (context, address, data, addr_byte_size))
10330 return false;
10331
10332 //MemA[address+4,4] = R[t2];
Greg Claytonc07d4512011-04-26 23:48:45 +000010333 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010334 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10335
10336 data = ReadCoreReg (t2, &success);
10337 if (!success)
10338 return false;
10339
10340 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10341 return false;
10342
10343 //if wback then R[n] = offset_addr;
10344 if (wback)
10345 {
10346 context.type = eContextAdjustBaseRegister;
10347 context.SetAddress (offset_addr);
10348
10349 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10350 return false;
10351 }
10352 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010353 return true;
10354}
10355
10356
10357// A8.6.201 STRD (register)
10358bool
10359EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10360{
10361#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010362 if ConditionPassed() then
10363 EncodingSpecificOperations();
10364 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10365 address = if index then offset_addr else R[n];
10366 MemA[address,4] = R[t];
10367 MemA[address+4,4] = R[t2];
10368 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010369#endif
10370
Caroline Tice74467fe2011-03-30 19:02:56 +000010371 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010372
Caroline Tice74467fe2011-03-30 19:02:56 +000010373 if (ConditionPassed(opcode))
10374 {
10375 uint32_t t;
10376 uint32_t t2;
10377 uint32_t n;
10378 uint32_t m;
10379 bool index;
10380 bool add;
10381 bool wback;
10382
10383 switch (encoding)
10384 {
10385 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010386 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010387 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10388 t = Bits32 (opcode, 15, 12);
10389 if (BitIsSet (t, 0))
10390 return false;
10391
10392 t2 = t+1;
10393 n = Bits32 (opcode, 19, 16);
10394 m = Bits32 (opcode, 3, 0);
10395
Greg Clayton061b79d2011-05-09 20:18:18 +000010396 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010397 index = BitIsSet (opcode, 24);
10398 add = BitIsSet (opcode, 23);
10399 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10400
Greg Clayton061b79d2011-05-09 20:18:18 +000010401 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010402 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10403 return false;
10404
10405 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10406 if ((t2 == 15) || (m == 15))
10407 return false;
10408
10409 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10410 if (wback && ((n == 15) || (n == t) || (n == t2)))
10411 return false;
10412
10413 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010414 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010415 return false;
10416
10417 break;
10418
10419 default:
10420 return false;
10421 }
10422
Greg Claytonc07d4512011-04-26 23:48:45 +000010423 RegisterInfo base_reg;
10424 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10425 RegisterInfo offset_reg;
10426 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10427 RegisterInfo data_reg;
Caroline Tice74467fe2011-03-30 19:02:56 +000010428
10429 uint32_t Rn = ReadCoreReg (n, &success);
10430 if (!success)
10431 return false;
10432
10433 uint32_t Rm = ReadCoreReg (m, &success);
10434 if (!success)
10435 return false;
10436
10437 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10438 addr_t offset_addr;
10439 if (add)
10440 offset_addr = Rn + Rm;
10441 else
10442 offset_addr = Rn - Rm;
10443
10444 // address = if index then offset_addr else R[n];
10445 addr_t address;
10446 if (index)
10447 address = offset_addr;
10448 else
10449 address = Rn;
10450 // MemA[address,4] = R[t];
10451 uint32_t Rt = ReadCoreReg (t, &success);
10452 if (!success)
10453 return false;
10454
10455 EmulateInstruction::Context context;
10456 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +000010457 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010458 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10459
10460 const uint32_t addr_byte_size = GetAddressByteSize();
10461
10462 if (!MemAWrite (context, address, Rt, addr_byte_size))
10463 return false;
10464
10465 // MemA[address+4,4] = R[t2];
10466 uint32_t Rt2 = ReadCoreReg (t2, &success);
10467 if (!success)
10468 return false;
10469
Greg Claytonc07d4512011-04-26 23:48:45 +000010470 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010471
10472 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10473
10474 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10475 return false;
10476
10477 // if wback then R[n] = offset_addr;
10478 if (wback)
10479 {
10480 context.type = eContextAdjustBaseRegister;
10481 context.SetAddress (offset_addr);
10482
10483 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10484 return false;
10485
10486 }
10487 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010488 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010489}
10490
Caroline Tice4f605582011-03-31 00:02:51 +000010491// A8.6.319 VLDM
10492// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10493// an ARM core register.
10494bool
10495EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10496{
10497#if 0
10498 if ConditionPassed() then
10499 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10500 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010501 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010502 for r = 0 to regs-1
10503 if single_regs then
10504 S[d+r] = MemA[address,4]; address = address+4;
10505 else
10506 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10507 // Combine the word-aligned words in the correct order for current endianness.
10508 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10509#endif
10510
10511 bool success = false;
10512
10513 if (ConditionPassed(opcode))
10514 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010515 bool single_regs;
10516 bool add;
10517 bool wback;
10518 uint32_t d;
10519 uint32_t n;
10520 uint32_t imm32;
10521 uint32_t regs;
10522
Caroline Tice4f605582011-03-31 00:02:51 +000010523 switch (encoding)
10524 {
10525 case eEncodingT1:
10526 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010527 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10528 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10529 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10530 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010531 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10532 return false;
10533
10534 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010535 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice4f605582011-03-31 00:02:51 +000010536 single_regs = false;
10537 add = BitIsSet (opcode, 23);
10538 wback = BitIsSet (opcode, 21);
10539
Greg Clayton061b79d2011-05-09 20:18:18 +000010540 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice4f605582011-03-31 00:02:51 +000010541 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10542 n = Bits32 (opcode, 19, 16);
10543 imm32 = Bits32 (opcode, 7, 0) << 2;
10544
Greg Clayton061b79d2011-05-09 20:18:18 +000010545 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
Caroline Tice4f605582011-03-31 00:02:51 +000010546 regs = Bits32 (opcode, 7, 0) / 2;
10547
10548 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10549 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10550 return false;
10551
10552 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10553 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10554 return false;
10555
10556 break;
10557
10558 case eEncodingT2:
10559 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010560 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10561 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10562 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10563 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010564 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10565 return false;
10566
10567 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010568 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Tice4f605582011-03-31 00:02:51 +000010569 single_regs = true;
10570 add = BitIsSet (opcode, 23);
10571 wback = BitIsSet (opcode, 21);
10572 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10573 n = Bits32 (opcode, 19, 16);
10574
Greg Clayton061b79d2011-05-09 20:18:18 +000010575 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Tice4f605582011-03-31 00:02:51 +000010576 imm32 = Bits32 (opcode, 7, 0) << 2;
10577 regs = Bits32 (opcode, 7, 0);
10578
10579 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10580 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10581 return false;
10582
10583 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10584 if ((regs == 0) || ((d + regs) > 32))
10585 return false;
10586 break;
10587
10588 default:
10589 return false;
10590 }
10591
Greg Claytonc07d4512011-04-26 23:48:45 +000010592 RegisterInfo base_reg;
10593 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4f605582011-03-31 00:02:51 +000010594
10595 uint32_t Rn = ReadCoreReg (n, &success);
10596 if (!success)
10597 return false;
10598
10599 // address = if add then R[n] else R[n]-imm32;
10600 addr_t address;
10601 if (add)
10602 address = Rn;
10603 else
10604 address = Rn - imm32;
10605
Greg Claytonc07d4512011-04-26 23:48:45 +000010606 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010607 EmulateInstruction::Context context;
10608
10609 if (wback)
10610 {
10611 uint32_t value;
10612 if (add)
10613 value = Rn + imm32;
10614 else
10615 value = Rn - imm32;
10616
10617 context.type = eContextAdjustBaseRegister;
10618 context.SetImmediateSigned (value - Rn);
10619 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10620 return false;
10621
10622 }
10623
10624 const uint32_t addr_byte_size = GetAddressByteSize();
10625 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10626
10627 context.type = eContextRegisterLoad;
10628
10629 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010630 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010631 {
10632 if (single_regs)
10633 {
10634 // S[d+r] = MemA[address,4]; address = address+4;
10635 context.SetRegisterPlusOffset (base_reg, address - Rn);
10636
10637 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10638 if (!success)
10639 return false;
10640
10641 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10642 return false;
10643
10644 address = address + 4;
10645 }
10646 else
10647 {
10648 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10649 context.SetRegisterPlusOffset (base_reg, address - Rn);
10650 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10651 if (!success)
10652 return false;
10653
10654 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10655 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10656 if (!success)
10657 return false;
10658
10659 address = address + 8;
10660 // // Combine the word-aligned words in the correct order for current endianness.
10661 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10662 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010663 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010664 {
10665 data = word1;
10666 data = (data << 32) | word2;
10667 }
10668 else
10669 {
10670 data = word2;
10671 data = (data << 32) | word1;
10672 }
10673
10674 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10675 return false;
10676 }
10677 }
10678 }
10679 return true;
10680}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010681
10682// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010683// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10684// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010685bool
10686EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10687{
10688#if 0
10689 if ConditionPassed() then
10690 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10691 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010692 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010693 for r = 0 to regs-1
10694 if single_regs then
10695 MemA[address,4] = S[d+r]; address = address+4;
10696 else
10697 // Store as two word-aligned words in the correct order for current endianness.
10698 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10699 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10700 address = address+8;
10701#endif
10702
10703 bool success = false;
10704
10705 if (ConditionPassed (opcode))
10706 {
10707 bool single_regs;
10708 bool add;
10709 bool wback;
10710 uint32_t d;
10711 uint32_t n;
10712 uint32_t imm32;
10713 uint32_t regs;
10714
10715 switch (encoding)
10716 {
10717 case eEncodingT1:
10718 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010719 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10720 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10721 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10722 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010723 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10724 return false;
10725
10726 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010727 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010728 single_regs = false;
10729 add = BitIsSet (opcode, 23);
10730 wback = BitIsSet (opcode, 21);
10731
Greg Clayton061b79d2011-05-09 20:18:18 +000010732 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010733 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10734 n = Bits32 (opcode, 19, 16);
10735 imm32 = Bits32 (opcode, 7, 0) << 2;
10736
Greg Clayton061b79d2011-05-09 20:18:18 +000010737 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010738 regs = Bits32 (opcode, 7, 0) / 2;
10739
10740 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10741 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10742 return false;
10743
10744 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10745 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10746 return false;
10747
10748 break;
10749
10750 case eEncodingT2:
10751 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010752 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10753 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10754 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10755 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010756 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10757 return false;
10758
10759 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010760 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010761 single_regs = true;
10762 add = BitIsSet (opcode, 23);
10763 wback = BitIsSet (opcode, 21);
10764 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10765 n = Bits32 (opcode, 19, 16);
10766
Greg Clayton061b79d2011-05-09 20:18:18 +000010767 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010768 imm32 = Bits32 (opcode, 7, 0) << 2;
10769 regs = Bits32 (opcode, 7, 0);
10770
10771 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10772 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10773 return false;
10774
10775 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10776 if ((regs == 0) || ((d + regs) > 32))
10777 return false;
10778
10779 break;
10780
10781 default:
10782 return false;
10783 }
10784
Greg Claytonc07d4512011-04-26 23:48:45 +000010785 RegisterInfo base_reg;
10786 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010787
10788 uint32_t Rn = ReadCoreReg (n, &success);
10789 if (!success)
10790 return false;
10791
10792 // address = if add then R[n] else R[n]-imm32;
10793 addr_t address;
10794 if (add)
10795 address = Rn;
10796 else
10797 address = Rn - imm32;
10798
10799 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +000010800 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010801 if (wback)
10802 {
10803 uint32_t value;
10804 if (add)
10805 value = Rn + imm32;
10806 else
10807 value = Rn - imm32;
10808
10809 context.type = eContextAdjustBaseRegister;
10810 context.SetRegisterPlusOffset (base_reg, value - Rn);
10811
10812 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10813 return false;
10814 }
10815
10816 const uint32_t addr_byte_size = GetAddressByteSize();
10817 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10818
10819 context.type = eContextRegisterStore;
10820 // for r = 0 to regs-1
10821 for (int r = 0; r < regs; ++r)
10822 {
Greg Claytonc07d4512011-04-26 23:48:45 +000010823
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010824 if (single_regs)
10825 {
10826 // MemA[address,4] = S[d+r]; address = address+4;
10827 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10828 if (!success)
10829 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010830
10831 RegisterInfo data_reg;
10832 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010833 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10834 if (!MemAWrite (context, address, data, addr_byte_size))
10835 return false;
10836
10837 address = address + 4;
10838 }
10839 else
10840 {
10841 // // Store as two word-aligned words in the correct order for current endianness.
10842 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10843 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10844 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10845 if (!success)
10846 return false;
10847
Greg Claytonc07d4512011-04-26 23:48:45 +000010848 RegisterInfo data_reg;
10849 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010850
Greg Clayton888a7332011-04-26 04:39:08 +000010851 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010852 {
10853 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10854 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10855 return false;
10856
10857 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10858 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10859 return false;
10860 }
10861 else
10862 {
10863 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10864 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10865 return false;
10866
10867 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10868 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10869 return false;
10870 }
10871 // address = address+8;
10872 address = address + 8;
10873 }
10874 }
10875 }
10876 return true;
10877}
10878
Caroline Tice917ad352011-03-31 05:05:30 +000010879// A8.6.320
10880// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10881// an optional offset.
10882bool
10883EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10884{
10885#if 0
10886 if ConditionPassed() then
10887 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10888 base = if n == 15 then Align(PC,4) else R[n];
10889 address = if add then (base + imm32) else (base - imm32);
10890 if single_reg then
10891 S[d] = MemA[address,4];
10892 else
10893 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10894 // Combine the word-aligned words in the correct order for current endianness.
10895 D[d] = if BigEndian() then word1:word2 else word2:word1;
10896#endif
10897
10898 bool success = false;
10899
10900 if (ConditionPassed (opcode))
10901 {
10902 bool single_reg;
10903 bool add;
10904 uint32_t imm32;
10905 uint32_t d;
10906 uint32_t n;
10907
10908 switch (encoding)
10909 {
10910 case eEncodingT1:
10911 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010912 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010913 single_reg = false;
10914 add = BitIsSet (opcode, 23);
10915 imm32 = Bits32 (opcode, 7, 0) << 2;
10916
10917 // d = UInt(D:Vd); n = UInt(Rn);
10918 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10919 n = Bits32 (opcode, 19, 16);
10920
10921 break;
10922
10923 case eEncodingT2:
10924 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010925 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010926 single_reg = true;
10927 add = BitIsSet (opcode, 23);
10928 imm32 = Bits32 (opcode, 7, 0) << 2;
10929
10930 // d = UInt(Vd:D); n = UInt(Rn);
10931 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10932 n = Bits32 (opcode, 19, 16);
10933
10934 break;
10935
10936 default:
10937 return false;
10938 }
Greg Claytonc07d4512011-04-26 23:48:45 +000010939 RegisterInfo base_reg;
10940 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice917ad352011-03-31 05:05:30 +000010941
10942 uint32_t Rn = ReadCoreReg (n, &success);
10943 if (!success)
10944 return false;
10945
10946 // base = if n == 15 then Align(PC,4) else R[n];
10947 uint32_t base;
10948 if (n == 15)
10949 base = AlignPC (Rn);
10950 else
10951 base = Rn;
10952
10953 // address = if add then (base + imm32) else (base - imm32);
10954 addr_t address;
10955 if (add)
10956 address = base + imm32;
10957 else
10958 address = base - imm32;
10959
10960 const uint32_t addr_byte_size = GetAddressByteSize();
10961 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
10962
10963 EmulateInstruction::Context context;
10964 context.type = eContextRegisterLoad;
10965 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010966
Caroline Tice917ad352011-03-31 05:05:30 +000010967 if (single_reg)
10968 {
10969 // S[d] = MemA[address,4];
10970 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10971 if (!success)
10972 return false;
10973
10974 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
10975 return false;
10976 }
10977 else
10978 {
10979 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
10980 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10981 if (!success)
10982 return false;
10983
10984 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
10985 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10986 if (!success)
10987 return false;
10988 // // Combine the word-aligned words in the correct order for current endianness.
10989 // D[d] = if BigEndian() then word1:word2 else word2:word1;
10990 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000010991 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000010992 {
10993 data64 = word1;
10994 data64 = (data64 << 32) | word2;
10995 }
10996 else
10997 {
10998 data64 = word2;
10999 data64 = (data64 << 32) | word1;
11000 }
11001
11002 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
11003 return false;
11004 }
11005 }
11006 return true;
11007}
Caroline Tice424652f2011-03-31 05:38:36 +000011008
11009// A8.6.400 VSTR
11010// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
11011// optional offset.
11012bool
11013EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
11014{
11015#if 0
11016 if ConditionPassed() then
11017 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11018 address = if add then (R[n] + imm32) else (R[n] - imm32);
11019 if single_reg then
11020 MemA[address,4] = S[d];
11021 else
11022 // Store as two word-aligned words in the correct order for current endianness.
11023 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11024 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11025#endif
11026
11027 bool success = false;
11028
11029 if (ConditionPassed (opcode))
11030 {
11031 bool single_reg;
11032 bool add;
11033 uint32_t imm32;
11034 uint32_t d;
11035 uint32_t n;
11036
11037 switch (encoding)
11038 {
11039 case eEncodingT1:
11040 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011041 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011042 single_reg = false;
11043 add = BitIsSet (opcode, 23);
11044 imm32 = Bits32 (opcode, 7, 0) << 2;
11045
11046 // d = UInt(D:Vd); n = UInt(Rn);
11047 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11048 n = Bits32 (opcode, 19, 16);
11049
11050 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11051 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11052 return false;
11053
11054 break;
11055
11056 case eEncodingT2:
11057 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011058 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011059 single_reg = true;
11060 add = BitIsSet (opcode, 23);
11061 imm32 = Bits32 (opcode, 7, 0) << 2;
11062
11063 // d = UInt(Vd:D); n = UInt(Rn);
11064 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11065 n = Bits32 (opcode, 19, 16);
11066
11067 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11068 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11069 return false;
11070
11071 break;
11072
11073 default:
11074 return false;
11075 }
11076
Greg Claytonc07d4512011-04-26 23:48:45 +000011077 RegisterInfo base_reg;
11078 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011079
11080 uint32_t Rn = ReadCoreReg (n, &success);
11081 if (!success)
11082 return false;
11083
11084 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11085 addr_t address;
11086 if (add)
11087 address = Rn + imm32;
11088 else
11089 address = Rn - imm32;
11090
11091 const uint32_t addr_byte_size = GetAddressByteSize();
11092 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11093
Greg Claytonc07d4512011-04-26 23:48:45 +000011094 RegisterInfo data_reg;
11095 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011096 EmulateInstruction::Context context;
11097 context.type = eContextRegisterStore;
11098 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11099
11100 if (single_reg)
11101 {
11102 // MemA[address,4] = S[d];
11103 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11104 if (!success)
11105 return false;
11106
11107 if (!MemAWrite (context, address, data, addr_byte_size))
11108 return false;
11109 }
11110 else
11111 {
11112 // // Store as two word-aligned words in the correct order for current endianness.
11113 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11114 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11115 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11116 if (!success)
11117 return false;
11118
Greg Clayton888a7332011-04-26 04:39:08 +000011119 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011120 {
11121 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11122 return false;
11123
11124 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11125 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11126 return false;
11127 }
11128 else
11129 {
11130 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11131 return false;
11132
11133 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11134 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11135 return false;
11136 }
11137 }
11138 }
11139 return true;
11140}
Caroline Tice9121b352011-03-31 16:41:19 +000011141
11142// A8.6.307 VLDI1 (multiple single elements)
11143// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11144// element of each register is loaded.
11145bool
11146EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11147{
11148#if 0
11149 if ConditionPassed() then
11150 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11151 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11152 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11153 for r = 0 to regs-1
11154 for e = 0 to elements-1
11155 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11156 address = address + ebytes;
11157#endif
11158
11159 bool success = false;
11160
11161 if (ConditionPassed (opcode))
11162 {
11163 uint32_t regs;
11164 uint32_t alignment;
11165 uint32_t ebytes;
11166 uint32_t esize;
11167 uint32_t elements;
11168 uint32_t d;
11169 uint32_t n;
11170 uint32_t m;
11171 bool wback;
11172 bool register_index;
11173
11174 switch (encoding)
11175 {
11176 case eEncodingT1:
11177 case eEncodingA1:
11178 {
11179 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011180 // when Ô0111Õ
11181 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
11182 // when Ô1010Õ
11183 // regs = 2; if align == Ô11Õ then UNDEFINED;
11184 // when Ô0110Õ
11185 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
11186 // when Ô0010Õ
Caroline Tice9121b352011-03-31 16:41:19 +000011187 // regs = 4;
11188 // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011189 // SEE ÒRelated encodingsÓ;
Caroline Tice9121b352011-03-31 16:41:19 +000011190 uint32_t type = Bits32 (opcode, 11, 8);
11191 uint32_t align = Bits32 (opcode, 5, 4);
11192 if (type == 7) // '0111'
11193 {
11194 regs = 1;
11195 if (BitIsSet (align, 1))
11196 return false;
11197 }
11198 else if (type == 10) // '1010'
11199 {
11200 regs = 2;
11201 if (align == 3)
11202 return false;
11203
11204 }
11205 else if (type == 6) // '0110'
11206 {
11207 regs = 3;
11208 if (BitIsSet (align, 1))
11209 return false;
11210 }
11211 else if (type == 2) // '0010'
11212 {
11213 regs = 4;
11214 }
11215 else
11216 return false;
11217
Greg Clayton061b79d2011-05-09 20:18:18 +000011218 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice9121b352011-03-31 16:41:19 +000011219 if (align == 0)
11220 alignment = 1;
11221 else
11222 alignment = 4 << align;
11223
11224 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11225 ebytes = 1 << Bits32 (opcode, 7, 6);
11226 esize = 8 * ebytes;
11227 elements = 8 / ebytes;
11228
11229 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11230 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11231 n = Bits32 (opcode, 19, 15);
11232 m = Bits32 (opcode, 3, 0);
11233
11234 // wback = (m != 15); register_index = (m != 15 && m != 13);
11235 wback = (m != 15);
11236 register_index = ((m != 15) && (m != 13));
11237
11238 // if d+regs > 32 then UNPREDICTABLE;
11239 if ((d + regs) > 32)
11240 return false;
11241 }
11242 break;
11243
11244 default:
11245 return false;
11246 }
11247
Greg Claytonc07d4512011-04-26 23:48:45 +000011248 RegisterInfo base_reg;
11249 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice9121b352011-03-31 16:41:19 +000011250
11251 uint32_t Rn = ReadCoreReg (n, &success);
11252 if (!success)
11253 return false;
11254
11255 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11256 addr_t address = Rn;
11257 if ((address % alignment) != 0)
11258 return false;
11259
11260 EmulateInstruction::Context context;
11261 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11262 if (wback)
11263 {
11264 uint32_t Rm = ReadCoreReg (m, &success);
11265 if (!success)
11266 return false;
11267
11268 uint32_t offset;
11269 if (register_index)
11270 offset = Rm;
11271 else
11272 offset = 8 * regs;
11273
11274 uint32_t value = Rn + offset;
11275 context.type = eContextAdjustBaseRegister;
11276 context.SetRegisterPlusOffset (base_reg, offset);
11277
11278 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11279 return false;
11280
11281 }
11282
11283 // for r = 0 to regs-1
11284 for (int r = 0; r < regs; ++r)
11285 {
11286 // for e = 0 to elements-1
11287 uint64_t assembled_data = 0;
11288 for (int e = 0; e < elements; ++e)
11289 {
11290 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11291 context.type = eContextRegisterLoad;
11292 context.SetRegisterPlusOffset (base_reg, address - Rn);
11293 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11294 if (!success)
11295 return false;
11296
11297 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11298
11299 // address = address + ebytes;
11300 address = address + ebytes;
11301 }
11302 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11303 return false;
11304 }
11305 }
11306 return true;
11307}
11308
Caroline Ticeb6281b12011-03-31 17:58:23 +000011309// A8.6.308 VLD1 (single element to one lane)
11310//
11311bool
11312EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11313{
11314#if 0
11315 if ConditionPassed() then
11316 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11317 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11318 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11319 Elem[D[d],index,esize] = MemU[address,ebytes];
11320#endif
11321
11322 bool success = false;
11323
11324 if (ConditionPassed (opcode))
11325 {
11326 uint32_t ebytes;
11327 uint32_t esize;
11328 uint32_t index;
11329 uint32_t alignment;
11330 uint32_t d;
11331 uint32_t n;
11332 uint32_t m;
11333 bool wback;
11334 bool register_index;
11335
11336 switch (encoding)
11337 {
11338 case eEncodingT1:
11339 case eEncodingA1:
11340 {
11341 uint32_t size = Bits32 (opcode, 11, 10);
11342 uint32_t index_align = Bits32 (opcode, 7, 4);
Greg Clayton061b79d2011-05-09 20:18:18 +000011343 // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011344 if (size == 3)
11345 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011346 // case size of
11347 if (size == 0) // when '00'
11348 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011349 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011350 if (BitIsClear (index_align, 0))
11351 return false;
11352
11353 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11354 ebytes = 1;
11355 esize = 8;
11356 index = Bits32 (index_align, 3, 1);
11357 alignment = 1;
11358 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011359 else if (size == 1) // when Ô01Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011360 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011361 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011362 if (BitIsClear (index_align, 1))
11363 return false;
11364
11365 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11366 ebytes = 2;
11367 esize = 16;
11368 index = Bits32 (index_align, 3, 2);
11369
Greg Clayton061b79d2011-05-09 20:18:18 +000011370 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011371 if (BitIsClear (index_align, 0))
11372 alignment = 1;
11373 else
11374 alignment = 2;
11375 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011376 else if (size == 2) // when Ô10Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011377 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011378 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011379 if (BitIsClear (index_align, 2))
11380 return false;
11381
Greg Clayton061b79d2011-05-09 20:18:18 +000011382 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011383 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11384 return false;
11385
11386 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11387 ebytes = 4;
11388 esize = 32;
11389 index = Bit32 (index_align, 3);
11390
Greg Clayton061b79d2011-05-09 20:18:18 +000011391 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011392 if (Bits32 (index_align, 1, 0) == 0)
11393 alignment = 1;
11394 else
11395 alignment = 4;
11396 }
11397 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11398 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11399 n = Bits32 (opcode, 19, 16);
11400 m = Bits32 (opcode, 3, 0);
11401
11402 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11403 wback = (m != 15);
11404 register_index = ((m != 15) && (m != 13));
11405
11406 if (n == 15)
11407 return false;
11408
11409 }
11410 break;
11411
11412 default:
11413 return false;
11414 }
11415
Greg Claytonc07d4512011-04-26 23:48:45 +000011416 RegisterInfo base_reg;
11417 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011418
11419 uint32_t Rn = ReadCoreReg (n, &success);
11420 if (!success)
11421 return false;
11422
11423 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11424 addr_t address = Rn;
11425 if ((address % alignment) != 0)
11426 return false;
11427
11428 EmulateInstruction::Context context;
11429 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11430 if (wback)
11431 {
11432 uint32_t Rm = ReadCoreReg (m, &success);
11433 if (!success)
11434 return false;
11435
11436 uint32_t offset;
11437 if (register_index)
11438 offset = Rm;
11439 else
11440 offset = ebytes;
11441
11442 uint32_t value = Rn + offset;
11443
11444 context.type = eContextAdjustBaseRegister;
11445 context.SetRegisterPlusOffset (base_reg, offset);
11446
11447 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11448 return false;
11449 }
11450
11451 // Elem[D[d],index,esize] = MemU[address,ebytes];
11452 uint32_t element = MemURead (context, address, esize, 0, &success);
11453 if (!success)
11454 return false;
11455
11456 element = element << (index * esize);
11457
11458 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11459 if (!success)
11460 return false;
11461
11462 uint64_t all_ones = -1;
11463 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11464 // at element & to the right of element.
11465 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011466 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 +000011467 // now mask should be 0's where element goes & 1's
11468 // everywhere else.
11469
11470 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11471 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11472
11473 context.type = eContextRegisterLoad;
11474 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11475 return false;
11476 }
11477 return true;
11478}
11479
Caroline Tice1e542e32011-03-31 18:44:04 +000011480// A8.6.391 VST1 (multiple single elements)
11481// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11482// interleaving. Every element of each register is stored.
11483bool
11484EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11485{
11486#if 0
11487 if ConditionPassed() then
11488 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11489 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11490 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11491 for r = 0 to regs-1
11492 for e = 0 to elements-1
11493 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11494 address = address + ebytes;
11495#endif
11496
11497 bool success = false;
11498
11499 if (ConditionPassed (opcode))
11500 {
11501 uint32_t regs;
11502 uint32_t alignment;
11503 uint32_t ebytes;
11504 uint32_t esize;
11505 uint32_t elements;
11506 uint32_t d;
11507 uint32_t n;
11508 uint32_t m;
11509 bool wback;
11510 bool register_index;
11511
11512 switch (encoding)
11513 {
11514 case eEncodingT1:
11515 case eEncodingA1:
11516 {
11517 uint32_t type = Bits32 (opcode, 11, 8);
11518 uint32_t align = Bits32 (opcode, 5, 4);
11519
11520 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011521 if (type == 7) // when Ô0111Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011522 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011523 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011524 regs = 1;
11525 if (BitIsSet (align, 1))
11526 return false;
11527 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011528 else if (type == 10) // when Ô1010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011529 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011530 // regs = 2; if align == Ô11Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011531 regs = 2;
11532 if (align == 3)
11533 return false;
11534 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011535 else if (type == 6) // when Ô0110Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011536 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011537 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011538 regs = 3;
11539 if (BitIsSet (align, 1))
11540 return false;
11541 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011542 else if (type == 2) // when Ô0010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011543 // regs = 4;
11544 regs = 4;
11545 else // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011546 // SEE ÒRelated encodingsÓ;
Caroline Tice1e542e32011-03-31 18:44:04 +000011547 return false;
11548
Greg Clayton061b79d2011-05-09 20:18:18 +000011549 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice1e542e32011-03-31 18:44:04 +000011550 if (align == 0)
11551 alignment = 0;
11552 else
11553 alignment = 4 << align;
11554
11555 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11556 ebytes = 1 << Bits32 (opcode,7, 6);
11557 esize = 8 * ebytes;
11558 elements = 8 / ebytes;
11559
11560 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11561 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11562 n = Bits32 (opcode, 19, 16);
11563 m = Bits32 (opcode, 3, 0);
11564
11565 // wback = (m != 15); register_index = (m != 15 && m != 13);
11566 wback = (m != 15);
11567 register_index = ((m != 15) && (m != 13));
11568
11569 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11570 if ((d + regs) > 32)
11571 return false;
11572
11573 if (n == 15)
11574 return false;
11575
11576 }
11577 break;
11578
11579 default:
11580 return false;
11581 }
11582
Greg Claytonc07d4512011-04-26 23:48:45 +000011583 RegisterInfo base_reg;
11584 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011585
11586 uint32_t Rn = ReadCoreReg (n, &success);
11587 if (!success)
11588 return false;
11589
11590 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11591 addr_t address = Rn;
11592 if ((address % alignment) != 0)
11593 return false;
11594
11595 EmulateInstruction::Context context;
11596 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11597 if (wback)
11598 {
11599 uint32_t Rm = ReadCoreReg (m, &success);
11600 if (!success)
11601 return false;
11602
11603 uint32_t offset;
11604 if (register_index)
11605 offset = Rm;
11606 else
11607 offset = 8 * regs;
11608
11609 context.type = eContextAdjustBaseRegister;
11610 context.SetRegisterPlusOffset (base_reg, offset);
11611
11612 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11613 return false;
11614 }
11615
Greg Claytonc07d4512011-04-26 23:48:45 +000011616 RegisterInfo data_reg;
Caroline Tice1e542e32011-03-31 18:44:04 +000011617 context.type = eContextRegisterStore;
Caroline Tice1e542e32011-03-31 18:44:04 +000011618 // for r = 0 to regs-1
11619 for (int r = 0; r < regs; ++r)
11620 {
Greg Claytonc07d4512011-04-26 23:48:45 +000011621 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011622 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11623 if (!success)
11624 return false;
11625
11626 // for e = 0 to elements-1
11627 for (int e = 0; e < elements; ++e)
11628 {
11629 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011630 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011631
11632 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11633 if (!MemUWrite (context, address, word, ebytes))
11634 return false;
11635
11636 // address = address + ebytes;
11637 address = address + ebytes;
11638 }
11639 }
11640 }
11641 return true;
11642}
11643
Caroline Tice7b880942011-03-31 19:17:12 +000011644// A8.6.392 VST1 (single element from one lane)
11645// This instruction stores one element to memory from one element of a register.
11646bool
11647EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11648{
11649#if 0
11650 if ConditionPassed() then
11651 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11652 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11653 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11654 MemU[address,ebytes] = Elem[D[d],index,esize];
11655#endif
11656
11657 bool success = false;
11658
11659 if (ConditionPassed (opcode))
11660 {
11661 uint32_t ebytes;
11662 uint32_t esize;
11663 uint32_t index;
11664 uint32_t alignment;
11665 uint32_t d;
11666 uint32_t n;
11667 uint32_t m;
11668 bool wback;
11669 bool register_index;
11670
11671 switch (encoding)
11672 {
11673 case eEncodingT1:
11674 case eEncodingA1:
11675 {
11676 uint32_t size = Bits32 (opcode, 11, 10);
11677 uint32_t index_align = Bits32 (opcode, 7, 4);
11678
Greg Clayton061b79d2011-05-09 20:18:18 +000011679 // if size == Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011680 if (size == 3)
11681 return false;
11682
11683 // case size of
Greg Clayton061b79d2011-05-09 20:18:18 +000011684 if (size == 0) // when Ô00Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011685 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011686 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011687 if (BitIsClear (index_align, 0))
11688 return false;
11689 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11690 ebytes = 1;
11691 esize = 8;
11692 index = Bits32 (index_align, 3, 1);
11693 alignment = 1;
11694 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011695 else if (size == 1) // when Ô01Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011696 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011697 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011698 if (BitIsClear (index_align, 1))
11699 return false;
11700
11701 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11702 ebytes = 2;
11703 esize = 16;
11704 index = Bits32 (index_align, 3, 2);
11705
Greg Clayton061b79d2011-05-09 20:18:18 +000011706 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Tice7b880942011-03-31 19:17:12 +000011707 if (BitIsClear (index_align, 0))
11708 alignment = 1;
11709 else
11710 alignment = 2;
11711 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011712 else if (size == 2) // when Ô10Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011713 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011714 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011715 if (BitIsClear (index_align, 2))
11716 return false;
11717
Greg Clayton061b79d2011-05-09 20:18:18 +000011718 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011719 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11720 return false;
11721
11722 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11723 ebytes = 4;
11724 esize = 32;
11725 index = Bit32 (index_align, 3);
11726
Greg Clayton061b79d2011-05-09 20:18:18 +000011727 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Tice7b880942011-03-31 19:17:12 +000011728 if (Bits32 (index_align, 1, 0) == 0)
11729 alignment = 1;
11730 else
11731 alignment = 4;
11732 }
11733 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11734 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11735 n = Bits32 (opcode, 19, 16);
11736 m = Bits32 (opcode, 3, 0);
11737
11738 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11739 wback = (m != 15);
11740 register_index = ((m != 15) && (m != 13));
11741
11742 if (n == 15)
11743 return false;
11744 }
11745 break;
11746
11747 default:
11748 return false;
11749 }
11750
Greg Claytonc07d4512011-04-26 23:48:45 +000011751 RegisterInfo base_reg;
11752 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011753
11754 uint32_t Rn = ReadCoreReg (n, &success);
11755 if (!success)
11756 return false;
11757
11758 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11759 addr_t address = Rn;
11760 if ((address % alignment) != 0)
11761 return false;
11762
11763 EmulateInstruction::Context context;
11764 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11765 if (wback)
11766 {
11767 uint32_t Rm = ReadCoreReg (m, &success);
11768 if (!success)
11769 return false;
11770
11771 uint32_t offset;
11772 if (register_index)
11773 offset = Rm;
11774 else
11775 offset = ebytes;
11776
11777 context.type = eContextAdjustBaseRegister;
11778 context.SetRegisterPlusOffset (base_reg, offset);
11779
11780 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11781 return false;
11782 }
11783
11784 // MemU[address,ebytes] = Elem[D[d],index,esize];
11785 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11786 if (!success)
11787 return false;
11788
11789 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11790
Greg Claytonc07d4512011-04-26 23:48:45 +000011791 RegisterInfo data_reg;
11792 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011793 context.type = eContextRegisterStore;
11794 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11795
11796 if (!MemUWrite (context, address, word, ebytes))
11797 return false;
11798 }
11799 return true;
11800}
11801
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011802// A8.6.309 VLD1 (single element to all lanes)
11803// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011804bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011805EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011806{
11807#if 0
11808 if ConditionPassed() then
11809 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11810 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11811 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11812 replicated_element = Replicate(MemU[address,ebytes], elements);
11813 for r = 0 to regs-1
11814 D[d+r] = replicated_element;
11815#endif
11816
11817 bool success = false;
11818
11819 if (ConditionPassed (opcode))
11820 {
11821 uint32_t ebytes;
11822 uint32_t elements;
11823 uint32_t regs;
11824 uint32_t alignment;
11825 uint32_t d;
11826 uint32_t n;
11827 uint32_t m;
11828 bool wback;
11829 bool register_index;
11830
11831 switch (encoding)
11832 {
11833 case eEncodingT1:
11834 case eEncodingA1:
11835 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011836 //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
Caroline Tice93767b82011-03-31 21:15:29 +000011837 uint32_t size = Bits32 (opcode, 7, 6);
11838 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11839 return false;
11840
Greg Clayton061b79d2011-05-09 20:18:18 +000011841 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
Caroline Tice93767b82011-03-31 21:15:29 +000011842 ebytes = 1 << size;
11843 elements = 8 / ebytes;
11844 if (BitIsClear (opcode, 5))
11845 regs = 1;
11846 else
11847 regs = 2;
11848
Greg Clayton061b79d2011-05-09 20:18:18 +000011849 //alignment = if a == Ô0Õ then 1 else ebytes;
Caroline Tice93767b82011-03-31 21:15:29 +000011850 if (BitIsClear (opcode, 4))
11851 alignment = 1;
11852 else
11853 alignment = ebytes;
11854
11855 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11856 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11857 n = Bits32 (opcode, 19, 16);
11858 m = Bits32 (opcode, 3, 0);
11859
11860 //wback = (m != 15); register_index = (m != 15 && m != 13);
11861 wback = (m != 15);
11862 register_index = ((m != 15) && (m != 13));
11863
11864 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11865 if ((d + regs) > 32)
11866 return false;
11867
11868 if (n == 15)
11869 return false;
11870 }
11871 break;
11872
11873 default:
11874 break;
11875 }
11876
Greg Claytonc07d4512011-04-26 23:48:45 +000011877 RegisterInfo base_reg;
11878 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice93767b82011-03-31 21:15:29 +000011879
11880 uint32_t Rn = ReadCoreReg (n, &success);
11881 if (!success)
11882 return false;
11883
11884 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11885 addr_t address = Rn;
11886 if ((address % alignment) != 0)
11887 return false;
11888
11889 EmulateInstruction::Context context;
11890 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11891 if (wback)
11892 {
11893 uint32_t Rm = ReadCoreReg (m, &success);
11894 if (!success)
11895 return false;
11896
11897 uint32_t offset;
11898 if (register_index)
11899 offset = Rm;
11900 else
11901 offset = ebytes;
11902
11903 context.type = eContextAdjustBaseRegister;
11904 context.SetRegisterPlusOffset (base_reg, offset);
11905
11906 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11907 return false;
11908 }
11909
11910 // replicated_element = Replicate(MemU[address,ebytes], elements);
11911
11912 context.type = eContextRegisterLoad;
11913 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11914 if (!success)
11915 return false;
11916
11917 uint64_t replicated_element;
11918 uint32_t esize = ebytes * 8;
11919 for (int e = 0; e < elements; ++e)
11920 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11921
11922 // for r = 0 to regs-1
11923 for (int r = 0; r < regs; ++r)
11924 {
11925 // D[d+r] = replicated_element;
11926 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11927 return false;
11928 }
11929 }
11930 return true;
11931}
11932
Caroline Tice1f954f52011-04-11 15:51:10 +000011933// B6.2.13 SUBS PC, LR and related instructions
11934//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
11935// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
11936bool
11937EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
11938{
11939#if 0
11940 if ConditionPassed() then
11941 EncodingSpecificOperations();
11942 if CurrentInstrSet() == InstrSet_ThumbEE then
11943 UNPREDICTABLE;
11944 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11945 case opcode of
Greg Clayton061b79d2011-05-09 20:18:18 +000011946 when Ô0000Õ result = R[n] AND operand2; // AND
11947 when Ô0001Õ result = R[n] EOR operand2; // EOR
11948 when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
11949 when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
11950 when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
11951 when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
11952 when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
11953 when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
11954 when Ô1100Õ result = R[n] OR operand2; // ORR
11955 when Ô1101Õ result = operand2; // MOV
11956 when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
11957 when Ô1111Õ result = NOT(operand2); // MVN
11958 CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000011959 BranchWritePC(result);
11960#endif
11961
11962 bool success = false;
11963
11964 if (ConditionPassed (opcode))
11965 {
11966 uint32_t n;
11967 uint32_t m;
11968 uint32_t imm32;
11969 bool register_form;
11970 ARM_ShifterType shift_t;
11971 uint32_t shift_n;
11972 uint32_t code;
11973
11974 switch (encoding)
11975 {
11976 case eEncodingT1:
11977 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
Greg Clayton061b79d2011-05-09 20:18:18 +000011978 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000011979 n = 14;
11980 imm32 = Bits32 (opcode, 7, 0);
11981 register_form = false;
11982 code = 2;
11983
11984 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
11985 if (InITBlock() && !LastInITBlock())
11986 return false;
11987
11988 break;
11989
11990 case eEncodingA1:
11991 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
11992 n = Bits32 (opcode, 19, 16);
11993 imm32 = ARMExpandImm (opcode);
11994 register_form = false;
11995 code = Bits32 (opcode, 24, 21);
11996
11997 break;
11998
11999 case eEncodingA2:
12000 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12001 n = Bits32 (opcode, 19, 16);
12002 m = Bits32 (opcode, 3, 0);
12003 register_form = true;
12004
12005 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12006 shift_n = DecodeImmShiftARM (opcode, shift_t);
12007
12008 break;
12009
12010 default:
12011 return false;
12012 }
12013
12014 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12015 uint32_t operand2;
12016 if (register_form)
12017 {
12018 uint32_t Rm = ReadCoreReg (m, &success);
12019 if (!success)
12020 return false;
12021
12022 operand2 = Shift (Rm, shift_t, shift_n, APSR_C);
12023
12024 }
12025 else
12026 {
12027 operand2 = imm32;
12028 }
12029
12030 uint32_t Rn = ReadCoreReg (n, &success);
12031 if (!success)
12032 return false;
12033
12034 AddWithCarryResult result;
12035
12036 // case opcode of
12037 switch (code)
12038 {
Greg Clayton061b79d2011-05-09 20:18:18 +000012039 case 0: // when Ô0000Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012040 // result = R[n] AND operand2; // AND
12041 result.result = Rn & operand2;
12042 break;
12043
Greg Clayton061b79d2011-05-09 20:18:18 +000012044 case 1: // when Ô0001Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012045 // result = R[n] EOR operand2; // EOR
12046 result.result = Rn ^ operand2;
12047 break;
12048
Greg Clayton061b79d2011-05-09 20:18:18 +000012049 case 2: // when Ô0010Õ
12050 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012051 result = AddWithCarry (Rn, ~(operand2), 1);
12052 break;
12053
Greg Clayton061b79d2011-05-09 20:18:18 +000012054 case 3: // when Ô0011Õ
12055 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
Caroline Tice1f954f52011-04-11 15:51:10 +000012056 result = AddWithCarry (~(Rn), operand2, 1);
12057 break;
12058
Greg Clayton061b79d2011-05-09 20:18:18 +000012059 case 4: // when Ô0100Õ
12060 // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
Caroline Tice1f954f52011-04-11 15:51:10 +000012061 result = AddWithCarry (Rn, operand2, 0);
12062 break;
12063
Greg Clayton061b79d2011-05-09 20:18:18 +000012064 case 5: // when Ô0101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012065 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12066 result = AddWithCarry (Rn, operand2, APSR_C);
12067 break;
12068
Greg Clayton061b79d2011-05-09 20:18:18 +000012069 case 6: // when Ô0110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012070 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12071 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12072 break;
12073
Greg Clayton061b79d2011-05-09 20:18:18 +000012074 case 7: // when Ô0111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012075 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12076 result = AddWithCarry (~(Rn), operand2, APSR_C);
12077 break;
12078
Greg Clayton061b79d2011-05-09 20:18:18 +000012079 case 10: // when Ô1100Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012080 // result = R[n] OR operand2; // ORR
12081 result.result = Rn | operand2;
12082 break;
12083
Greg Clayton061b79d2011-05-09 20:18:18 +000012084 case 11: // when Ô1101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012085 // result = operand2; // MOV
12086 result.result = operand2;
12087 break;
12088
Greg Clayton061b79d2011-05-09 20:18:18 +000012089 case 12: // when Ô1110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012090 // result = R[n] AND NOT(operand2); // BIC
12091 result.result = Rn & ~(operand2);
12092 break;
12093
Greg Clayton061b79d2011-05-09 20:18:18 +000012094 case 15: // when Ô1111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012095 // result = NOT(operand2); // MVN
12096 result.result = ~(operand2);
12097 break;
12098
12099 default:
12100 return false;
12101 }
Greg Clayton061b79d2011-05-09 20:18:18 +000012102 // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012103
12104 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12105 // the best.
12106 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12107 if (!success)
12108 return false;
12109
12110 CPSRWriteByInstr (spsr, 15, true);
12111
12112 // BranchWritePC(result);
12113 EmulateInstruction::Context context;
12114 context.type = eContextAdjustPC;
12115 context.SetImmediate (result.result);
12116
12117 BranchWritePC (context, result.result);
12118 }
12119 return true;
12120}
12121
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012122EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012123EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012124{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012125 static ARMOpcode
12126 g_arm_opcodes[] =
12127 {
12128 //----------------------------------------------------------------------
12129 // Prologue instructions
12130 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012131
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012132 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012133 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12134 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012135
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012136 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012137 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12138 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012139 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012140 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12141 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12142 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012143
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012144 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012145 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12146 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012147
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012148 // push one register
12149 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012150 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012151
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012152 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012153 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12154 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012155
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012156 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012157 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012158 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012159
Caroline Tice4f605582011-03-31 00:02:51 +000012160 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12161 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12162 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12163 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012164
12165 //----------------------------------------------------------------------
12166 // Supervisor Call (previously Software Interrupt)
12167 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012168 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012169
12170 //----------------------------------------------------------------------
12171 // Branch instructions
12172 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012173 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012174 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012175 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12176 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12177 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012178 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012179 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012180 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012181 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012182
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012183 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012184 // Data-processing instructions
12185 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012186 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012187 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012188 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012189 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012190 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012191 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012192 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012193 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012194 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012195 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012196 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012197 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12198 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012199 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012200 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012201 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012202 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012203 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012204 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012205 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012206 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012207 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012208 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012209 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012210 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012211 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012212 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012213 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012214 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012215 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012216 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012217 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012218 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012219 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012220 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012221 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012222 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012223 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012224 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012225 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012226 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012227 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012228 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012229 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012230 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012231 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012232 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012233 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012234 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012235 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012236 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012237 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012238 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012239 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012240 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012241
Caroline Tice89c6d582011-03-29 19:53:44 +000012242 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012243 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12244 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012245 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012246 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012247 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012248 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012249 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012250 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012251 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012252 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012253 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012254 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012255 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012256 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012257 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012258 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012259 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012260 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012261 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012262 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012263 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012264 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012265 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012266 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012267 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012268 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012269 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012270 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012271 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012272 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012273 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012274 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012275 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012276 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012277 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012278 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012279
12280 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012281 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12282 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012283
12284 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012285 // Load instructions
12286 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012287 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12288 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12289 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12290 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12291 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12292 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12293 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12294 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12295 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12296 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12297 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12298 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12299 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12300 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12301 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12302 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12303 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12304 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012305 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12306 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12307 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12308 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012309 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12310 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012311 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012312
12313 //----------------------------------------------------------------------
12314 // Store instructions
12315 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012316 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12317 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12318 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12319 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12320 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12321 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12322 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12323 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12324 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012325 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012326 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012327 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12328 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12329 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12330 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12331 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012332 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012333
Caroline Tice6bf65162011-03-03 17:42:58 +000012334 //----------------------------------------------------------------------
12335 // Other instructions
12336 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012337 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12338 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12339 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12340 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12341 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012342
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012343 };
12344 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12345
12346 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12347 {
Greg Clayton888a7332011-04-26 04:39:08 +000012348 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12349 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012350 return &g_arm_opcodes[i];
12351 }
12352 return NULL;
12353}
Greg Clayton64c84432011-01-21 22:02:52 +000012354
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012355
12356EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012357EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012358{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012359
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012360 static ARMOpcode
12361 g_thumb_opcodes[] =
12362 {
12363 //----------------------------------------------------------------------
12364 // Prologue instructions
12365 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012366
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012367 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012368 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12369 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12370 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012371
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012372 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012373 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012374 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012375 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012376 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012377 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012378
Johnny Chen864a8e82011-02-18 00:07:39 +000012379 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012380 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012381
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012382 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012383 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12384 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12385 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12386 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12387 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012388
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012389 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012390 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12391 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012392
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012393 //----------------------------------------------------------------------
12394 // Epilogue instructions
12395 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012396
Caroline Tice4f605582011-03-31 00:02:51 +000012397 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12398 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12399 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12400 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12401 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12402 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12403 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012404
12405 //----------------------------------------------------------------------
12406 // Supervisor Call (previously Software Interrupt)
12407 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012408 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012409
12410 //----------------------------------------------------------------------
12411 // If Then makes up to four following instructions conditional.
12412 //----------------------------------------------------------------------
Greg Clayton04d397c2011-05-23 18:04:09 +000012413 // The next 5 opcode _must_ come before the if then instruction
12414 { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"},
12415 { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
12416 { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
12417 { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
12418 { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
12419 { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012420
12421 //----------------------------------------------------------------------
12422 // Branch instructions
12423 //----------------------------------------------------------------------
12424 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012425 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12426 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12427 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12428 { 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 +000012429 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012430 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012431 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012432 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12433 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012434 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012435 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012436 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012437 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012438 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012439 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012440 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012441 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012442 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012443 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012444
12445 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012446 // Data-processing instructions
12447 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012448 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012449 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012450 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012451 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12452 { 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 +000012453 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012454 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012455 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012456 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012457 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012458 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12459 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12460 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012461 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012462 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012463 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012464 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12465 { 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 +000012466 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012467 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012468 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012469 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12470 { 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 +000012471 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012472 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012473 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012474 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12475 { 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 +000012476 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012477 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012478 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012479 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12480 { 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 +000012481 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012482 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12483 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012484 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012485 { 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 +000012486 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012487 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012488 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012489 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12490 { 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 +000012491 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012492 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12493 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12494 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12495 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012496 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012497 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12498 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12499 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12500 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012501 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012502 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12503 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012504 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012505 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12506 { 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 +000012507 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012508 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012509 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012510 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012511 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012512 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012513 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012514 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12515 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012516
Johnny Chen7c5234d2011-02-18 23:41:11 +000012517
Johnny Chen338bf542011-02-10 19:29:03 +000012518 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012519 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012520 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012521 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012522 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012523 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012524 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012525 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12526 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12527 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012528 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012529 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012530 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012531 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12532 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012533 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012534 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012535 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012536 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12537 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012538 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012539 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12540 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012541 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012542 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012543 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012544 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012545 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012546 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12547 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012548 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012549 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12550 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012551 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012552 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12553 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012554 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012555 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12556 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012557 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012558 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12559 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012560 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012561 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12562 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012563 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012564 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012565 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012566 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012567 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012568 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12569 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012570 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012571 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012572 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012573 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012574
12575 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012576 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012577
12578 //----------------------------------------------------------------------
12579 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12580 // otherwise the wrong instructions will be selected.
12581 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012582
Caroline Tice080bf612011-04-05 18:46:00 +000012583 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12584 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12585
Johnny Chen26863dc2011-02-09 23:43:29 +000012586 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012587 // Load instructions
12588 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012589 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12590 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12591 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12592 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12593 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12594 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12595 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012596 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012597 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12598 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12599 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12600 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12601 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012602 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012603 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12604 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12605 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12606 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12607 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12608 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12609 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12610 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12611 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12612 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12613 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12614 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12615 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12616 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12617 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12618 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12619 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12620 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12621 { 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 +000012622 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012623 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12624 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12625 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12626 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012627 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12628 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012629 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012630
12631 //----------------------------------------------------------------------
12632 // Store instructions
12633 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012634 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12635 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12636 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12637 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12638 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12639 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12640 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12641 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12642 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12643 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12644 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12645 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12646 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12647 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12648 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12649 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012650 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12651 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12652 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12653 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12654 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012655 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012656
12657 //----------------------------------------------------------------------
12658 // Other instructions
12659 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012660 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12661 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12662 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12663 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12664 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12665 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12666 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12667 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012668 };
12669
12670 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12671 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12672 {
Greg Clayton888a7332011-04-26 04:39:08 +000012673 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12674 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012675 return &g_thumb_opcodes[i];
12676 }
12677 return NULL;
12678}
Greg Clayton64c84432011-01-21 22:02:52 +000012679
Greg Clayton31e2a382011-01-30 20:03:56 +000012680bool
Greg Clayton395fc332011-02-15 21:59:32 +000012681EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012682{
Caroline Tice080bf612011-04-05 18:46:00 +000012683 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012684 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012685 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012686 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012687 {
Greg Clayton395fc332011-02-15 21:59:32 +000012688 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12689 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12690 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12691 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12692 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12693 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12694 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12695 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12696 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12697 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Johnny Chen1d29a852011-04-26 18:51:57 +000012698 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12699 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
Greg Clayton31e2a382011-01-30 20:03:56 +000012700 }
12701 return m_arm_isa != 0;
12702}
12703
Caroline Tice080bf612011-04-05 18:46:00 +000012704bool
Greg Clayton888a7332011-04-26 04:39:08 +000012705EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012706{
Greg Clayton888a7332011-04-26 04:39:08 +000012707 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12708 {
12709 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12710 m_opcode_mode = eModeThumb;
12711 else
12712 {
12713 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012714
Greg Clayton888a7332011-04-26 04:39:08 +000012715 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12716 m_opcode_mode = eModeARM;
12717 else if (addr_class == eAddressClassCodeAlternateISA)
12718 m_opcode_mode = eModeThumb;
12719 else
12720 return false;
12721 }
12722 if (m_opcode_mode == eModeThumb)
12723 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12724 else
12725 m_opcode_cpsr = CPSR_MODE_USR;
12726 return true;
12727 }
12728 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012729}
Greg Clayton31e2a382011-01-30 20:03:56 +000012730
Greg Clayton64c84432011-01-21 22:02:52 +000012731bool
12732EmulateInstructionARM::ReadInstruction ()
12733{
12734 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012735 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012736 if (success)
12737 {
12738 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12739 if (success)
12740 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012741 Context read_inst_context;
12742 read_inst_context.type = eContextReadOpcode;
12743 read_inst_context.SetNoArgs ();
12744
Greg Claytonb3448432011-03-24 21:19:54 +000012745 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012746 {
Greg Claytonb3448432011-03-24 21:19:54 +000012747 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012748 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012749
12750 if (success)
12751 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012752 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012753 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012754 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012755 }
12756 else
12757 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012758 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012759 }
12760 }
12761 }
12762 else
12763 {
Greg Claytonb3448432011-03-24 21:19:54 +000012764 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012765 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012766 }
12767 }
12768 }
12769 if (!success)
12770 {
Greg Claytonb3448432011-03-24 21:19:54 +000012771 m_opcode_mode = eModeInvalid;
Greg Clayton3063c952011-04-29 22:50:31 +000012772 m_addr = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012773 }
12774 return success;
12775}
12776
Johnny Chenee9b1f72011-02-09 01:00:31 +000012777uint32_t
12778EmulateInstructionARM::ArchVersion ()
12779{
12780 return m_arm_isa;
12781}
12782
Greg Clayton64c84432011-01-21 22:02:52 +000012783bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012784EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012785{
Greg Clayton888a7332011-04-26 04:39:08 +000012786 // If we are ignoring conditions, then always return true.
12787 // this allows us to iterate over disassembly code and still
12788 // emulate an instruction even if we don't have all the right
12789 // bits set in the CPSR register...
12790 if (m_ignore_conditions)
12791 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000012792
Greg Clayton7bc39082011-03-24 23:53:38 +000012793 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012794
12795 if (cond == UINT32_MAX)
12796 return false;
12797
12798 bool result = false;
12799 switch (UnsignedBits(cond, 3, 1))
12800 {
Caroline Tice080bf612011-04-05 18:46:00 +000012801 case 0:
12802 if (m_opcode_cpsr == 0)
12803 return true;
12804 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12805 break;
12806 case 1:
12807 if (m_opcode_cpsr == 0)
12808 return true;
12809 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12810 break;
12811 case 2:
12812 if (m_opcode_cpsr == 0)
12813 return true;
12814 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12815 break;
12816 case 3:
12817 if (m_opcode_cpsr == 0)
12818 return true;
12819 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12820 break;
12821 case 4:
12822 if (m_opcode_cpsr == 0)
12823 return true;
12824 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12825 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012826 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012827 if (m_opcode_cpsr == 0)
12828 return true;
12829 else
12830 {
Greg Claytonb3448432011-03-24 21:19:54 +000012831 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12832 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012833 result = n == v;
12834 }
12835 break;
12836 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012837 if (m_opcode_cpsr == 0)
12838 return true;
12839 else
12840 {
Greg Claytonb3448432011-03-24 21:19:54 +000012841 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12842 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12843 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012844 }
12845 break;
12846 case 7:
12847 result = true;
12848 break;
12849 }
12850
12851 if (cond & 1)
12852 result = !result;
12853 return result;
12854}
12855
Johnny Chen9ee056b2011-02-08 00:06:35 +000012856uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012857EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012858{
Greg Claytonb3448432011-03-24 21:19:54 +000012859 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012860 {
12861 default:
12862 case eModeInvalid:
12863 break;
12864
12865 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012866 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012867
12868 case eModeThumb:
12869 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12870 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012871 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012872 const uint32_t byte_size = m_opcode.GetByteSize();
12873 if (byte_size == 2)
12874 {
12875 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12876 return Bits32(opcode, 11, 7);
12877 }
12878 else
12879 {
Greg Claytone1f47bb2011-06-02 22:23:35 +000012880 //assert (byte_size == 4);
Greg Clayton7bc39082011-03-24 23:53:38 +000012881 if (Bits32(opcode, 31, 27) == 0x1e &&
12882 Bits32(opcode, 15, 14) == 0x02 &&
12883 Bits32(opcode, 12, 12) == 0x00 &&
12884 Bits32(opcode, 25, 22) <= 0x0d)
12885 {
12886 return Bits32(opcode, 25, 22);
12887 }
12888 }
12889
12890 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012891 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012892 }
12893 return UINT32_MAX; // Return invalid value
12894}
12895
Johnny Chen9ee056b2011-02-08 00:06:35 +000012896bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012897EmulateInstructionARM::InITBlock()
12898{
12899 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12900}
12901
12902bool
12903EmulateInstructionARM::LastInITBlock()
12904{
12905 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12906}
12907
Caroline Ticeb27771d2011-03-03 22:37:46 +000012908bool
12909EmulateInstructionARM::BadMode (uint32_t mode)
12910{
12911
12912 switch (mode)
12913 {
12914 case 16: return false; // '10000'
12915 case 17: return false; // '10001'
12916 case 18: return false; // '10010'
12917 case 19: return false; // '10011'
12918 case 22: return false; // '10110'
12919 case 23: return false; // '10111'
12920 case 27: return false; // '11011'
12921 case 31: return false; // '11111'
12922 default: return true;
12923 }
12924 return true;
12925}
12926
12927bool
12928EmulateInstructionARM::CurrentModeIsPrivileged ()
12929{
Greg Claytonb3448432011-03-24 21:19:54 +000012930 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012931
12932 if (BadMode (mode))
12933 return false;
12934
12935 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000012936 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012937
12938 return true;
12939}
12940
12941void
12942EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
12943{
12944 bool privileged = CurrentModeIsPrivileged();
12945
12946 uint32_t tmp_cpsr = 0;
12947
Greg Claytonb3448432011-03-24 21:19:54 +000012948 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012949
12950 if (BitIsSet (bytemask, 3))
12951 {
12952 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
12953 if (affect_execstate)
12954 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
12955 }
12956
12957 if (BitIsSet (bytemask, 2))
12958 {
12959 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
12960 }
12961
12962 if (BitIsSet (bytemask, 1))
12963 {
12964 if (affect_execstate)
12965 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
12966 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
12967 if (privileged)
12968 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
12969 }
12970
12971 if (BitIsSet (bytemask, 0))
12972 {
12973 if (privileged)
12974 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
12975 if (affect_execstate)
12976 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
12977 if (privileged)
12978 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
12979 }
12980
Greg Claytonb3448432011-03-24 21:19:54 +000012981 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012982}
12983
12984
Johnny Chen098ae2d2011-02-12 00:50:05 +000012985bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000012986EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
12987{
12988 addr_t target;
12989
Johnny Chenee9b1f72011-02-09 01:00:31 +000012990 // Check the current instruction set.
12991 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012992 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012993 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000012994 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012995
Johnny Chen9ee056b2011-02-08 00:06:35 +000012996 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012997 return false;
12998
12999 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013000}
13001
13002// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
13003bool
Johnny Chen668b4512011-02-15 21:08:58 +000013004EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013005{
13006 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000013007 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
13008 // we want to record it and issue a WriteRegister callback so the clients
13009 // can track the mode changes accordingly.
13010 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013011
13012 if (BitIsSet(addr, 0))
13013 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013014 if (CurrentInstrSet() != eModeThumb)
13015 {
13016 SelectInstrSet(eModeThumb);
13017 cpsr_changed = true;
13018 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013019 target = addr & 0xfffffffe;
Greg Claytonc07d4512011-04-26 23:48:45 +000013020 context.SetISA (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013021 }
13022 else if (BitIsClear(addr, 1))
13023 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013024 if (CurrentInstrSet() != eModeARM)
13025 {
13026 SelectInstrSet(eModeARM);
13027 cpsr_changed = true;
13028 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013029 target = addr & 0xfffffffc;
Greg Claytonc07d4512011-04-26 23:48:45 +000013030 context.SetISA (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013031 }
13032 else
13033 return false; // address<1:0> == '10' => UNPREDICTABLE
13034
Johnny Chen0f309db2011-02-09 19:11:32 +000013035 if (cpsr_changed)
13036 {
Johnny Chen558133b2011-02-09 23:59:17 +000013037 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000013038 return false;
13039 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013040 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013041 return false;
13042
13043 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013044}
Greg Clayton64c84432011-01-21 22:02:52 +000013045
Johnny Chenee9b1f72011-02-09 01:00:31 +000013046// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13047bool
Johnny Chen668b4512011-02-15 21:08:58 +000013048EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000013049{
13050 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000013051 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000013052 else
13053 return BranchWritePC((const Context)context, addr);
13054}
13055
Johnny Chen26863dc2011-02-09 23:43:29 +000013056// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13057bool
Johnny Chen668b4512011-02-15 21:08:58 +000013058EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000013059{
13060 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013061 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013062 else
13063 return BranchWritePC((const Context)context, addr);
13064}
13065
Johnny Chenee9b1f72011-02-09 01:00:31 +000013066EmulateInstructionARM::Mode
13067EmulateInstructionARM::CurrentInstrSet ()
13068{
Greg Claytonb3448432011-03-24 21:19:54 +000013069 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013070}
13071
Greg Claytonb3448432011-03-24 21:19:54 +000013072// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013073// ReadInstruction() is performed. This function has a side effect of updating
13074// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013075bool
13076EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13077{
Greg Claytonb3448432011-03-24 21:19:54 +000013078 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013079 switch (arm_or_thumb)
13080 {
13081 default:
13082 return false;
13083 eModeARM:
13084 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013085 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013086 break;
13087 eModeThumb:
13088 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013089 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013090 break;
13091 }
13092 return true;
13093}
13094
Johnny Chenef21b592011-02-10 01:52:38 +000013095// This function returns TRUE if the processor currently provides support for
13096// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13097// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13098bool
13099EmulateInstructionARM::UnalignedSupport()
13100{
13101 return (ArchVersion() >= ARMv7);
13102}
13103
Johnny Chenbf6ad172011-02-11 01:29:53 +000013104// The main addition and subtraction instructions can produce status information
13105// about both unsigned carry and signed overflow conditions. This status
13106// information can be used to synthesize multi-word additions and subtractions.
13107EmulateInstructionARM::AddWithCarryResult
13108EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13109{
13110 uint32_t result;
13111 uint8_t carry_out;
13112 uint8_t overflow;
13113
13114 uint64_t unsigned_sum = x + y + carry_in;
13115 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13116
13117 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013118// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013119 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013120
13121 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013122 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013123 else
13124 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013125
13126 AddWithCarryResult res = { result, carry_out, overflow };
13127 return res;
13128}
13129
Johnny Chen157b9592011-02-18 21:13:05 +000013130uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013131EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013132{
Johnny Chene39f22d2011-02-19 01:36:13 +000013133 uint32_t reg_kind, reg_num;
13134 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013135 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013136 case SP_REG:
13137 reg_kind = eRegisterKindGeneric;
13138 reg_num = LLDB_REGNUM_GENERIC_SP;
13139 break;
13140 case LR_REG:
13141 reg_kind = eRegisterKindGeneric;
13142 reg_num = LLDB_REGNUM_GENERIC_RA;
13143 break;
13144 case PC_REG:
13145 reg_kind = eRegisterKindGeneric;
13146 reg_num = LLDB_REGNUM_GENERIC_PC;
13147 break;
13148 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013149 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013150 {
13151 reg_kind = eRegisterKindDWARF;
13152 reg_num = dwarf_r0 + num;
13153 }
Johnny Chen157b9592011-02-18 21:13:05 +000013154 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013155 {
Greg Claytone1f47bb2011-06-02 22:23:35 +000013156 //assert(0 && "Invalid register number");
Johnny Chene39f22d2011-02-19 01:36:13 +000013157 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013158 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013159 }
13160 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013161 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013162
13163 // Read our register.
13164 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13165
13166 // When executing an ARM instruction , PC reads as the address of the current
13167 // instruction plus 8.
13168 // When executing a Thumb instruction , PC reads as the address of the current
13169 // instruction plus 4.
13170 if (num == 15)
13171 {
13172 if (CurrentInstrSet() == eModeARM)
13173 val += 8;
13174 else
13175 val += 4;
13176 }
Johnny Chen157b9592011-02-18 21:13:05 +000013177
13178 return val;
13179}
13180
Johnny Chenca67d1c2011-02-17 01:35:27 +000013181// Write the result to the ARM core register Rd, and optionally update the
13182// condition flags based on the result.
13183//
13184// This helper method tries to encapsulate the following pseudocode from the
13185// ARM Architecture Reference Manual:
13186//
13187// if d == 15 then // Can only occur for encoding A1
13188// ALUWritePC(result); // setflags is always FALSE here
13189// else
13190// R[d] = result;
13191// if setflags then
13192// APSR.N = result<31>;
13193// APSR.Z = IsZeroBit(result);
13194// APSR.C = carry;
13195// // APSR.V unchanged
13196//
13197// In the above case, the API client does not pass in the overflow arg, which
13198// defaults to ~0u.
13199bool
Johnny Chen10530c22011-02-17 22:37:12 +000013200EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13201 const uint32_t result,
13202 const uint32_t Rd,
13203 bool setflags,
13204 const uint32_t carry,
13205 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013206{
13207 if (Rd == 15)
13208 {
13209 if (!ALUWritePC (context, result))
13210 return false;
13211 }
13212 else
13213 {
Johnny Chena695f952011-02-23 21:24:25 +000013214 uint32_t reg_kind, reg_num;
13215 switch (Rd)
13216 {
13217 case SP_REG:
13218 reg_kind = eRegisterKindGeneric;
13219 reg_num = LLDB_REGNUM_GENERIC_SP;
13220 break;
13221 case LR_REG:
13222 reg_kind = eRegisterKindGeneric;
13223 reg_num = LLDB_REGNUM_GENERIC_RA;
13224 break;
13225 default:
13226 reg_kind = eRegisterKindDWARF;
13227 reg_num = dwarf_r0 + Rd;
13228 }
13229 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013230 return false;
13231 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013232 return WriteFlags (context, result, carry, overflow);
13233 }
13234 return true;
13235}
13236
13237// This helper method tries to encapsulate the following pseudocode from the
13238// ARM Architecture Reference Manual:
13239//
13240// APSR.N = result<31>;
13241// APSR.Z = IsZeroBit(result);
13242// APSR.C = carry;
13243// APSR.V = overflow
13244//
13245// Default arguments can be specified for carry and overflow parameters, which means
13246// not to update the respective flags.
13247bool
13248EmulateInstructionARM::WriteFlags (Context &context,
13249 const uint32_t result,
13250 const uint32_t carry,
13251 const uint32_t overflow)
13252{
Greg Claytonb3448432011-03-24 21:19:54 +000013253 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013254 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13255 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013256 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013257 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013258 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013259 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013260 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013261 {
13262 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13263 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013264 }
13265 return true;
13266}
13267
Greg Clayton64c84432011-01-21 22:02:52 +000013268bool
Greg Clayton888a7332011-04-26 04:39:08 +000013269EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013270{
Johnny Chenc315f862011-02-05 00:46:10 +000013271 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013272 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013273 m_it_session.ITAdvance();
13274
Greg Clayton888a7332011-04-26 04:39:08 +000013275 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013276
13277 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013278 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013279 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013280 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13281
13282 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013283 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013284
Greg Clayton888a7332011-04-26 04:39:08 +000013285 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13286 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013287
Greg Clayton888a7332011-04-26 04:39:08 +000013288 bool success = false;
13289 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013290 {
Greg Clayton888a7332011-04-26 04:39:08 +000013291 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
Greg Clayton061b79d2011-05-09 20:18:18 +000013292 dwarf_cpsr,
13293 0,
13294 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013295 }
13296
Greg Clayton888a7332011-04-26 04:39:08 +000013297 // Only return false if we are unable to read the CPSR if we care about conditions
13298 if (success == false && m_ignore_conditions == false)
13299 return false;
13300
13301 uint32_t orig_pc_value = 0;
13302 if (auto_advance_pc)
13303 {
13304 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13305 if (!success)
13306 return false;
13307 }
13308
13309 // Call the Emulate... function.
13310 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13311 if (!success)
13312 return false;
13313
13314 if (auto_advance_pc)
13315 {
13316 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13317 if (!success)
13318 return false;
13319
13320 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13321 {
13322 if (opcode_data->size == eSize32)
13323 after_pc_value += 4;
13324 else if (opcode_data->size == eSize16)
13325 after_pc_value += 2;
13326
13327 EmulateInstruction::Context context;
13328 context.type = eContextAdvancePC;
13329 context.SetNoArgs();
13330 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13331 return false;
13332
13333 }
13334 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013335 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013336}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013337
13338bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013339EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013340{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013341 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013342 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013343 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013344 return false;
13345 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013346
13347 static ConstString opcode_key ("opcode");
13348 static ConstString before_key ("before_state");
13349 static ConstString after_key ("after_state");
13350
13351 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013352
13353 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013354 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013355 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013356 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013357 return false;
13358 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013359 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013360
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013361 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13362 {
13363 m_opcode_mode = eModeARM;
13364 m_opcode.SetOpcode32 (test_opcode);
13365 }
13366 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13367 {
13368 m_opcode_mode = eModeThumb;
13369 if (test_opcode < 0x10000)
13370 m_opcode.SetOpcode16 (test_opcode);
13371 else
13372 m_opcode.SetOpcode32 (test_opcode);
13373
13374 }
13375 else
13376 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013377 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013378 return false;
13379 }
13380
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013381 EmulationStateARM before_state;
13382 EmulationStateARM after_state;
13383
Caroline Ticedfb2e202011-04-22 05:08:45 +000013384 value_sp = test_data->GetValueForKey (before_key);
13385 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013386 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013387 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013388 return false;
13389 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013390
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013391 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013392 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013393 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013394 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013395 return false;
13396 }
13397
Caroline Ticedfb2e202011-04-22 05:08:45 +000013398 value_sp = test_data->GetValueForKey (after_key);
13399 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013400 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013401 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013402 return false;
13403 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013404
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013405 state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013406 if (!after_state.LoadStateFromDictionary (state_dictionary))
13407 {
13408 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13409 return false;
13410 }
13411
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013412 SetBaton ((void *) &before_state);
13413 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13414 &EmulationStateARM::WritePseudoMemory,
13415 &EmulationStateARM::ReadPseudoRegister,
13416 &EmulationStateARM::WritePseudoRegister);
13417
Greg Clayton888a7332011-04-26 04:39:08 +000013418 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013419 if (!success)
13420 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013421 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013422 return false;
13423 }
13424
13425 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013426 if (!success)
13427 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13428
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013429 return success;
13430}
Greg Claytonc07d4512011-04-26 23:48:45 +000013431//
13432//
13433//const char *
13434//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13435//{
13436// if (reg_kind == eRegisterKindGeneric)
13437// {
13438// switch (reg_num)
13439// {
13440// case LLDB_REGNUM_GENERIC_PC: return "pc";
13441// case LLDB_REGNUM_GENERIC_SP: return "sp";
13442// case LLDB_REGNUM_GENERIC_FP: return "fp";
13443// case LLDB_REGNUM_GENERIC_RA: return "lr";
13444// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13445// default: return NULL;
13446// }
13447// }
13448// else if (reg_kind == eRegisterKindDWARF)
13449// {
13450// return GetARMDWARFRegisterName (reg_num);
13451// }
13452// return NULL;
13453//}
13454//
13455bool
13456EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
Greg Clayton888a7332011-04-26 04:39:08 +000013457{
Greg Clayton75906e42011-05-11 18:39:18 +000013458 unwind_plan.Clear();
Greg Claytonc07d4512011-04-26 23:48:45 +000013459 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13460
13461 UnwindPlan::Row row;
Greg Claytonc07d4512011-04-26 23:48:45 +000013462
13463 // Our previous Call Frame Address is the stack pointer
13464 row.SetCFARegister (dwarf_sp);
13465
13466 // Our previous PC is in the LR
Greg Clayton75906e42011-05-11 18:39:18 +000013467 row.SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
Greg Claytonc07d4512011-04-26 23:48:45 +000013468 unwind_plan.AppendRow (row);
13469
13470 // All other registers are the same.
13471
13472 unwind_plan.SetSourceName ("EmulateInstructionARM");
13473 return true;
Greg Clayton888a7332011-04-26 04:39:08 +000013474}
13475
Greg Claytonc07d4512011-04-26 23:48:45 +000013476
13477
13478