blob: e9237acac918bc6e7ecd002a42d402c6f7be619b [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013#include "EmulationStateARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000014#include "lldb/Core/ArchSpec.h"
Caroline Tice080bf612011-04-05 18:46:00 +000015#include "lldb/Core/Address.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000016#include "lldb/Core/ConstString.h"
Caroline Tice080bf612011-04-05 18:46:00 +000017#include "lldb/Core/PluginManager.h"
Caroline Tice6b8d3b52011-04-19 23:30:03 +000018#include "lldb/Core/Stream.h"
Greg Claytonc07d4512011-04-26 23:48:45 +000019#include "lldb/Symbol/UnwindPlan.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000020
Greg Claytonf29a08f2011-02-09 17:41:27 +000021#include "Plugins/Process/Utility/ARMDefines.h"
22#include "Plugins/Process/Utility/ARMUtils.h"
23#include "Utility/ARM_DWARF_Registers.h"
24
Johnny Chen9b8d7832011-02-02 01:13:56 +000025#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000026 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000027
28using namespace lldb;
29using namespace lldb_private;
30
Johnny Chene97c0d52011-02-18 19:32:20 +000031// Convenient macro definitions.
Greg Claytonb3448432011-03-24 21:19:54 +000032#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
33#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000034
Caroline Ticef55261f2011-02-18 22:24:22 +000035#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
36
Johnny Chen0e00af22011-02-10 19:40:42 +000037//----------------------------------------------------------------------
38//
39// ITSession implementation
40//
41//----------------------------------------------------------------------
42
Johnny Chen93070472011-02-04 23:02:47 +000043// A8.6.50
44// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
Greg Clayton04d397c2011-05-23 18:04:09 +000045static uint32_t
46CountITSize (uint32_t ITMask) {
Johnny Chen93070472011-02-04 23:02:47 +000047 // First count the trailing zeros of the IT mask.
Greg Clayton04d397c2011-05-23 18:04:09 +000048 uint32_t TZ = llvm::CountTrailingZeros_32(ITMask);
Johnny Chen93070472011-02-04 23:02:47 +000049 if (TZ > 3)
50 {
51 printf("Encoding error: IT Mask '0000'\n");
52 return 0;
53 }
54 return (4 - TZ);
55}
56
57// Init ITState. Note that at least one bit is always 1 in mask.
Greg Clayton04d397c2011-05-23 18:04:09 +000058bool ITSession::InitIT(uint32_t bits7_0)
Johnny Chen93070472011-02-04 23:02:47 +000059{
60 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
61 if (ITCounter == 0)
62 return false;
63
64 // A8.6.50 IT
65 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
66 if (FirstCond == 0xF)
67 {
68 printf("Encoding error: IT FirstCond '1111'\n");
69 return false;
70 }
71 if (FirstCond == 0xE && ITCounter != 1)
72 {
73 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
74 return false;
75 }
76
77 ITState = bits7_0;
78 return true;
79}
80
81// Update ITState if necessary.
82void ITSession::ITAdvance()
83{
Greg Claytone1f47bb2011-06-02 22:23:35 +000084 //assert(ITCounter);
Johnny Chen93070472011-02-04 23:02:47 +000085 --ITCounter;
86 if (ITCounter == 0)
87 ITState = 0;
88 else
89 {
90 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
91 SetBits32(ITState, 4, 0, NewITState4_0);
92 }
93}
94
95// Return true if we're inside an IT Block.
96bool ITSession::InITBlock()
97{
98 return ITCounter != 0;
99}
100
Johnny Chenc315f862011-02-05 00:46:10 +0000101// Return true if we're the last instruction inside an IT Block.
102bool ITSession::LastInITBlock()
103{
104 return ITCounter == 1;
105}
106
Johnny Chen93070472011-02-04 23:02:47 +0000107// Get condition bits for the current thumb instruction.
108uint32_t ITSession::GetCond()
109{
Johnny Chenc315f862011-02-05 00:46:10 +0000110 if (InITBlock())
111 return Bits32(ITState, 7, 4);
112 else
113 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000114}
115
Greg Clayton64c84432011-01-21 22:02:52 +0000116// ARM constants used during decoding
117#define REG_RD 0
118#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000119#define SP_REG 13
120#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000121#define PC_REG 15
122#define PC_REGLIST_BIT 0x8000
123
Johnny Chen251af6a2011-01-21 22:47:25 +0000124#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000125#define ARMv4T (1u << 1)
126#define ARMv5T (1u << 2)
127#define ARMv5TE (1u << 3)
128#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000129#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000130#define ARMv6K (1u << 6)
131#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000132#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000133#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000134#define ARMvAll (0xffffffffu)
135
Johnny Chen9b8d7832011-02-02 01:13:56 +0000136#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
137#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice1697dd72011-03-30 17:11:45 +0000138#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000139#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000140#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000141#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton04d397c2011-05-23 18:04:09 +0000142#define ARMV7_ABOVE (ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000143
Caroline Tice4f605582011-03-31 00:02:51 +0000144#define No_VFP 0
145#define VFPv1 (1u << 1)
146#define VFPv2 (1u << 2)
147#define VFPv3 (1u << 3)
148#define AdvancedSIMD (1u << 4)
149
150#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
151#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
152#define VFPv2v3 (VFPv2 | VFPv3)
153
Johnny Chen0e00af22011-02-10 19:40:42 +0000154//----------------------------------------------------------------------
155//
156// EmulateInstructionARM implementation
157//
158//----------------------------------------------------------------------
159
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000160void
161EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000162{
Caroline Tice080bf612011-04-05 18:46:00 +0000163 PluginManager::RegisterPlugin (GetPluginNameStatic (),
164 GetPluginDescriptionStatic (),
165 CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000166}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000167
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000168void
169EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000170{
Caroline Tice080bf612011-04-05 18:46:00 +0000171 PluginManager::UnregisterPlugin (CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000172}
173
Caroline Tice080bf612011-04-05 18:46:00 +0000174const char *
175EmulateInstructionARM::GetPluginNameStatic ()
176{
177 return "lldb.emulate-instruction.arm";
178}
179
180const char *
181EmulateInstructionARM::GetPluginDescriptionStatic ()
182{
183 return "Emulate instructions for the ARM architecture.";
184}
185
186EmulateInstruction *
Greg Clayton888a7332011-04-26 04:39:08 +0000187EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
Caroline Tice080bf612011-04-05 18:46:00 +0000188{
Greg Clayton888a7332011-04-26 04:39:08 +0000189 if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
Caroline Tice080bf612011-04-05 18:46:00 +0000190 {
Greg Clayton888a7332011-04-26 04:39:08 +0000191 if (arch.GetTriple().getArch() == llvm::Triple::arm)
192 {
193 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
194
195 if (emulate_insn_ap.get())
196 return emulate_insn_ap.release();
197 }
198 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
199 {
200 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
201
202 if (emulate_insn_ap.get())
203 return emulate_insn_ap.release();
204 }
Caroline Tice080bf612011-04-05 18:46:00 +0000205 }
206
207 return NULL;
208}
209
210bool
211EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
212{
213 if (arch.GetTriple().getArch () == llvm::Triple::arm)
214 return true;
215 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
216 return true;
217
218 return false;
219}
220
Caroline Ticefa172202011-02-11 22:49:54 +0000221// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
222bool
223EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
224{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000225 EmulateInstruction::Context context;
226 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
227 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000228
229 uint32_t random_data = rand ();
230 const uint32_t addr_byte_size = GetAddressByteSize();
231
Caroline Ticecc96eb52011-02-17 19:20:40 +0000232 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000233 return false;
234
235 return true;
236}
237
Caroline Tice713c2662011-02-11 17:59:55 +0000238// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
239bool
240EmulateInstructionARM::WriteBits32Unknown (int n)
241{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000242 EmulateInstruction::Context context;
243 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
244 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000245
Johnny Chen62ff6f52011-02-11 18:11:22 +0000246 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000247 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
248
249 if (!success)
250 return false;
251
252 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
253 return false;
254
255 return true;
256}
257
Greg Claytonc07d4512011-04-26 23:48:45 +0000258bool
259EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
260{
261 if (reg_kind == eRegisterKindGeneric)
262 {
263 switch (reg_num)
264 {
265 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break;
266 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break;
267 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break;
268 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break;
269 case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break;
270 default: return false;
271 }
272 }
273
274 if (reg_kind == eRegisterKindDWARF)
275 return GetARMDWARFRegisterInfo(reg_num, reg_info);
276 return false;
277}
278
Greg Clayton04d397c2011-05-23 18:04:09 +0000279uint32_t
280EmulateInstructionARM::GetFramePointerRegisterNumber () const
281{
282 if (m_opcode_mode == eModeThumb || m_arch.GetTriple().getOS() == llvm::Triple::Darwin)
283 return 7;
284 else
285 return 11;
286}
287
288uint32_t
289EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const
290{
291 if (m_opcode_mode == eModeThumb || m_arch.GetTriple().getOS() == llvm::Triple::Darwin)
292 return dwarf_r7;
293 else
294 return dwarf_r11;
295}
296
Johnny Chen08c25e82011-01-31 18:02:28 +0000297// Push Multiple Registers stores multiple registers to the stack, storing to
298// consecutive memory locations ending just below the address in SP, and updates
299// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000300bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000301EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000302{
303#if 0
304 // ARM pseudo code...
305 if (ConditionPassed())
306 {
307 EncodingSpecificOperations();
308 NullCheckIfThumbEE(13);
309 address = SP - 4*BitCount(registers);
310
311 for (i = 0 to 14)
312 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000313 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000314 {
315 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
316 MemA[address,4] = bits(32) UNKNOWN;
317 else
318 MemA[address,4] = R[i];
319 address = address + 4;
320 }
321 }
322
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000323 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000324 MemA[address,4] = PCStoreValue();
325
326 SP = SP - 4*BitCount(registers);
327 }
328#endif
329
330 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000331 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000332 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000333 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000334 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000335 if (!success)
336 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000337 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000338 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000339 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000340 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000341 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000342 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000343 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000344 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000345 // if BitCount(registers) < 1 then UNPREDICTABLE;
346 if (BitCount(registers) < 1)
347 return false;
348 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000349 case eEncodingT2:
350 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000351 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000352 // if BitCount(registers) < 2 then UNPREDICTABLE;
353 if (BitCount(registers) < 2)
354 return false;
355 break;
356 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000357 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000358 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000359 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000360 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000361 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000362 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000363 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000364 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000365 // Instead of return false, let's handle the following case as well,
366 // which amounts to pushing one reg onto the full descending stacks.
367 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000368 break;
369 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000370 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000371 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000372 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000373 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000374 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000375 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000376 default:
377 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000378 }
Johnny Chence1ca772011-01-25 01:13:00 +0000379 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000380 addr_t addr = sp - sp_offset;
381 uint32_t i;
382
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000383 EmulateInstruction::Context context;
384 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000385 RegisterInfo reg_info;
386 RegisterInfo sp_reg;
387 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Clayton64c84432011-01-21 22:02:52 +0000388 for (i=0; i<15; ++i)
389 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000390 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000391 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000392 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
393 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000394 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000395 if (!success)
396 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000397 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000398 return false;
399 addr += addr_byte_size;
400 }
401 }
402
Johnny Chen7c1bf922011-02-08 23:49:37 +0000403 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000404 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000405 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info);
406 context.SetRegisterPlusOffset (reg_info, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000407 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000408 if (!success)
409 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000410 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000411 return false;
412 }
413
414 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000415 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000416
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000417 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000418 return false;
419 }
420 return true;
421}
422
Johnny Chenef85e912011-01-31 23:07:40 +0000423// Pop Multiple Registers loads multiple registers from the stack, loading from
424// consecutive memory locations staring at the address in SP, and updates
425// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000426bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000427EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000428{
429#if 0
430 // ARM pseudo code...
431 if (ConditionPassed())
432 {
433 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
434 address = SP;
435 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000436 if registers<i> == '1' then
Greg Claytonc07d4512011-04-26 23:48:45 +0000437 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000438 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000439 if UnalignedAllowed then
440 LoadWritePC(MemU[address,4]);
441 else
442 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000443 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
444 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000445 }
446#endif
447
448 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000449
Greg Claytonc07d4512011-04-26 23:48:45 +0000450 if (ConditionPassed(opcode)) {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000451 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000452 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000453 if (!success)
454 return false;
455 uint32_t registers = 0;
456 uint32_t Rt; // the destination register
457 switch (encoding) {
458 case eEncodingT1:
459 registers = Bits32(opcode, 7, 0);
460 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000461 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000462 registers |= (1u << 15);
463 // if BitCount(registers) < 1 then UNPREDICTABLE;
464 if (BitCount(registers) < 1)
465 return false;
466 break;
467 case eEncodingT2:
468 // Ignore bit 13.
469 registers = Bits32(opcode, 15, 0) & ~0x2000;
470 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000471 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000472 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000473 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
474 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
475 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000476 break;
477 case eEncodingT3:
478 Rt = Bits32(opcode, 15, 12);
479 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000480 if (Rt == 13)
481 return false;
482 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000483 return false;
484 registers = (1u << Rt);
485 break;
486 case eEncodingA1:
487 registers = Bits32(opcode, 15, 0);
488 // Instead of return false, let's handle the following case as well,
489 // which amounts to popping one reg from the full descending stacks.
490 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
491
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000492 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000493 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000494 return false;
495 break;
496 case eEncodingA2:
497 Rt = Bits32(opcode, 15, 12);
498 // if t == 13 then UNPREDICTABLE;
499 if (Rt == dwarf_sp)
500 return false;
501 registers = (1u << Rt);
502 break;
503 default:
504 return false;
505 }
506 addr_t sp_offset = addr_byte_size * BitCount (registers);
507 addr_t addr = sp;
508 uint32_t i, data;
509
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000510 EmulateInstruction::Context context;
511 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000512
513 RegisterInfo sp_reg;
514 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
515
Johnny Chenef85e912011-01-31 23:07:40 +0000516 for (i=0; i<15; ++i)
517 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000518 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000519 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000520 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000521 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000522 if (!success)
523 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +0000524 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000525 return false;
526 addr += addr_byte_size;
527 }
528 }
529
Johnny Chen7c1bf922011-02-08 23:49:37 +0000530 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000531 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000532 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000533 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000534 if (!success)
535 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000536 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000537 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000538 return false;
539 addr += addr_byte_size;
540 }
541
542 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000543 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000544
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000545 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000546 return false;
547 }
548 return true;
549}
550
Johnny Chen5b442b72011-01-27 19:34:30 +0000551// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000552// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000553bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000554EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000555{
556#if 0
557 // ARM pseudo code...
558 if (ConditionPassed())
559 {
560 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000561 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000562 if d == 15 then
563 ALUWritePC(result); // setflags is always FALSE here
564 else
565 R[d] = result;
566 if setflags then
567 APSR.N = result<31>;
568 APSR.Z = IsZeroBit(result);
569 APSR.C = carry;
570 APSR.V = overflow;
571 }
572#endif
573
574 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000575
Greg Clayton7bc39082011-03-24 23:53:38 +0000576 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000577 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000578 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000579 if (!success)
580 return false;
581 uint32_t Rd; // the destination register
582 uint32_t imm32;
583 switch (encoding) {
584 case eEncodingT1:
585 Rd = 7;
586 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
587 break;
588 case eEncodingA1:
589 Rd = Bits32(opcode, 15, 12);
590 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
591 break;
592 default:
593 return false;
594 }
595 addr_t sp_offset = imm32;
596 addr_t addr = sp + sp_offset; // a pointer to the stack area
597
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000598 EmulateInstruction::Context context;
Greg Clayton75906e42011-05-11 18:39:18 +0000599 context.type = eContextSetFramePointer;
Greg Claytonc07d4512011-04-26 23:48:45 +0000600 RegisterInfo sp_reg;
601 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000602 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000603
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000604 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000605 return false;
606 }
607 return true;
608}
609
Johnny Chen2ccad832011-01-28 19:57:25 +0000610// Set r7 or ip to the current stack pointer.
611// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000612bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000613EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000614{
615#if 0
616 // ARM pseudo code...
617 if (ConditionPassed())
618 {
619 EncodingSpecificOperations();
620 result = R[m];
621 if d == 15 then
622 ALUWritePC(result); // setflags is always FALSE here
623 else
624 R[d] = result;
625 if setflags then
626 APSR.N = result<31>;
627 APSR.Z = IsZeroBit(result);
628 // APSR.C unchanged
629 // APSR.V unchanged
630 }
631#endif
632
633 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000634
Greg Clayton7bc39082011-03-24 23:53:38 +0000635 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000636 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000637 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000638 if (!success)
639 return false;
640 uint32_t Rd; // the destination register
641 switch (encoding) {
642 case eEncodingT1:
643 Rd = 7;
644 break;
645 case eEncodingA1:
646 Rd = 12;
647 break;
648 default:
649 return false;
650 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000651
652 EmulateInstruction::Context context;
Greg Clayton04d397c2011-05-23 18:04:09 +0000653 if (Rd == GetFramePointerRegisterNumber())
654 context.type = EmulateInstruction::eContextSetFramePointer;
655 else
656 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +0000657 RegisterInfo sp_reg;
658 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000659 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000660
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000661 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000662 return false;
663 }
664 return true;
665}
666
Johnny Chen1c13b622011-01-29 00:11:15 +0000667// Move from high register (r8-r15) to low register (r0-r7).
668// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000669bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000670EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000671{
Greg Clayton7bc39082011-03-24 23:53:38 +0000672 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000673}
674
675// Move from register to register.
676// MOV (register)
677bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000678EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000679{
Johnny Chen1c13b622011-01-29 00:11:15 +0000680#if 0
681 // ARM pseudo code...
682 if (ConditionPassed())
683 {
684 EncodingSpecificOperations();
685 result = R[m];
686 if d == 15 then
687 ALUWritePC(result); // setflags is always FALSE here
688 else
689 R[d] = result;
690 if setflags then
691 APSR.N = result<31>;
692 APSR.Z = IsZeroBit(result);
693 // APSR.C unchanged
694 // APSR.V unchanged
695 }
696#endif
697
698 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000699
Greg Clayton7bc39082011-03-24 23:53:38 +0000700 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000701 {
702 uint32_t Rm; // the source register
703 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000704 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000705 switch (encoding) {
706 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000707 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000708 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000709 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000710 if (Rd == 15 && InITBlock() && !LastInITBlock())
711 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000712 break;
713 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000714 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000715 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000716 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000717 if (InITBlock())
718 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000719 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000720 case eEncodingT3:
721 Rd = Bits32(opcode, 11, 8);
722 Rm = Bits32(opcode, 3, 0);
723 setflags = BitIsSet(opcode, 20);
724 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
725 if (setflags && (BadReg(Rd) || BadReg(Rm)))
726 return false;
727 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
728 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
729 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000730 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000731 case eEncodingA1:
732 Rd = Bits32(opcode, 15, 12);
733 Rm = Bits32(opcode, 3, 0);
734 setflags = BitIsSet(opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +0000735
Johnny Chen01d61572011-02-25 00:23:25 +0000736 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000737 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000738 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000739 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000740 default:
741 return false;
742 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000743 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000744 if (!success)
745 return false;
746
747 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000748 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000749 context.type = EmulateInstruction::eContextRegisterLoad;
Greg Claytonc07d4512011-04-26 23:48:45 +0000750 RegisterInfo dwarf_reg;
751 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000752 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000753
Johnny Chen10530c22011-02-17 22:37:12 +0000754 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000755 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000756 }
757 return true;
758}
759
Johnny Chen357c30f2011-02-14 22:04:25 +0000760// Move (immediate) writes an immediate value to the destination register. It
761// can optionally update the condition flags based on the value.
762// MOV (immediate)
763bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000764EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000765{
766#if 0
767 // ARM pseudo code...
768 if (ConditionPassed())
769 {
770 EncodingSpecificOperations();
771 result = imm32;
772 if d == 15 then // Can only occur for ARM encoding
773 ALUWritePC(result); // setflags is always FALSE here
774 else
775 R[d] = result;
776 if setflags then
777 APSR.N = result<31>;
778 APSR.Z = IsZeroBit(result);
779 APSR.C = carry;
780 // APSR.V unchanged
781 }
782#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000783
Greg Clayton7bc39082011-03-24 23:53:38 +0000784 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000785 {
786 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000787 uint32_t imm32; // the immediate value to be written to Rd
788 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
789 bool setflags;
790 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000791 case eEncodingT1:
792 Rd = Bits32(opcode, 10, 8);
793 setflags = !InITBlock();
794 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
795 carry = APSR_C;
796
797 break;
798
799 case eEncodingT2:
800 Rd = Bits32(opcode, 11, 8);
801 setflags = BitIsSet(opcode, 20);
802 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
803 if (BadReg(Rd))
804 return false;
805
806 break;
807
808 case eEncodingT3:
809 {
810 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
811 Rd = Bits32 (opcode, 11, 8);
812 setflags = false;
813 uint32_t imm4 = Bits32 (opcode, 19, 16);
814 uint32_t imm3 = Bits32 (opcode, 14, 12);
815 uint32_t i = Bit32 (opcode, 26);
816 uint32_t imm8 = Bits32 (opcode, 7, 0);
817 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
818
819 // if BadReg(d) then UNPREDICTABLE;
820 if (BadReg (Rd))
821 return false;
822 }
823 break;
824
825 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +0000826 // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
Caroline Tice89c6d582011-03-29 19:53:44 +0000827 Rd = Bits32 (opcode, 15, 12);
828 setflags = BitIsSet (opcode, 20);
829 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000830
Greg Clayton061b79d2011-05-09 20:18:18 +0000831 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +0000832 if ((Rd == 15) && setflags)
833 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000834
835 break;
836
837 case eEncodingA2:
838 {
839 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
840 Rd = Bits32 (opcode, 15, 12);
841 setflags = false;
842 uint32_t imm4 = Bits32 (opcode, 19, 16);
843 uint32_t imm12 = Bits32 (opcode, 11, 0);
844 imm32 = (imm4 << 12) | imm12;
845
846 // if d == 15 then UNPREDICTABLE;
847 if (Rd == 15)
848 return false;
849 }
850 break;
851
852 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000853 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000854 }
855 uint32_t result = imm32;
856
857 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000858 EmulateInstruction::Context context;
859 context.type = EmulateInstruction::eContextImmediate;
860 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000861
Johnny Chen10530c22011-02-17 22:37:12 +0000862 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000863 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000864 }
865 return true;
866}
867
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000868// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
869// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
870// unsigned values.
871//
872// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
873// limited to only a few forms of the instruction.
874bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000875EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000876{
877#if 0
878 if ConditionPassed() then
879 EncodingSpecificOperations();
880 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
881 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
882 result = operand1 * operand2;
883 R[d] = result<31:0>;
884 if setflags then
885 APSR.N = result<31>;
886 APSR.Z = IsZeroBit(result);
887 if ArchVersion() == 4 then
888 APSR.C = bit UNKNOWN;
889 // else APSR.C unchanged
890 // APSR.V always unchanged
891#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000892
Greg Clayton7bc39082011-03-24 23:53:38 +0000893 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000894 {
895 uint32_t d;
896 uint32_t n;
897 uint32_t m;
898 bool setflags;
899
900 // EncodingSpecificOperations();
901 switch (encoding)
902 {
903 case eEncodingT1:
904 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
905 d = Bits32 (opcode, 2, 0);
906 n = Bits32 (opcode, 5, 3);
907 m = Bits32 (opcode, 2, 0);
908 setflags = !InITBlock();
909
910 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
911 if ((ArchVersion() < ARMv6) && (d == n))
912 return false;
913
914 break;
915
916 case eEncodingT2:
917 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
918 d = Bits32 (opcode, 11, 8);
919 n = Bits32 (opcode, 19, 16);
920 m = Bits32 (opcode, 3, 0);
921 setflags = false;
922
923 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
924 if (BadReg (d) || BadReg (n) || BadReg (m))
925 return false;
926
927 break;
928
929 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000930 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000931 d = Bits32 (opcode, 19, 16);
932 n = Bits32 (opcode, 3, 0);
933 m = Bits32 (opcode, 11, 8);
934 setflags = BitIsSet (opcode, 20);
935
936 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
937 if ((d == 15) || (n == 15) || (m == 15))
938 return false;
939
940 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
941 if ((ArchVersion() < ARMv6) && (d == n))
942 return false;
943
944 break;
945
946 default:
947 return false;
948 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000949
950 bool success = false;
951
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000952 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
953 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
954 if (!success)
955 return false;
956
957 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
958 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
959 if (!success)
960 return false;
961
962 // result = operand1 * operand2;
963 uint64_t result = operand1 * operand2;
964
965 // R[d] = result<31:0>;
Greg Claytonc07d4512011-04-26 23:48:45 +0000966 RegisterInfo op1_reg;
967 RegisterInfo op2_reg;
968 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
969 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000970
971 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +0000972 context.type = eContextArithmetic;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000973 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
974
975 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
976 return false;
977
978 // if setflags then
979 if (setflags)
980 {
981 // APSR.N = result<31>;
982 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000983 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000984 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
985 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000986 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000987 {
988 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
989 return false;
990 }
991
992 // if ArchVersion() == 4 then
993 // APSR.C = bit UNKNOWN;
994 }
995 }
996 return true;
997}
998
Johnny Chend642a6a2011-02-22 01:01:03 +0000999// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
1000// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +00001001bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001002EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +00001003{
1004#if 0
1005 // ARM pseudo code...
1006 if (ConditionPassed())
1007 {
1008 EncodingSpecificOperations();
1009 result = NOT(imm32);
1010 if d == 15 then // Can only occur for ARM encoding
1011 ALUWritePC(result); // setflags is always FALSE here
1012 else
1013 R[d] = result;
1014 if setflags then
1015 APSR.N = result<31>;
1016 APSR.Z = IsZeroBit(result);
1017 APSR.C = carry;
1018 // APSR.V unchanged
1019 }
1020#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001021
Greg Clayton7bc39082011-03-24 23:53:38 +00001022 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001023 {
1024 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +00001025 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1026 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001027 bool setflags;
1028 switch (encoding) {
1029 case eEncodingT1:
1030 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001031 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001032 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001033 break;
1034 case eEncodingA1:
1035 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001036 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001037 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +00001038
Johnny Chend642a6a2011-02-22 01:01:03 +00001039 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +00001040 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001041 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001042 break;
1043 default:
1044 return false;
1045 }
1046 uint32_t result = ~imm32;
1047
1048 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001049 EmulateInstruction::Context context;
1050 context.type = EmulateInstruction::eContextImmediate;
1051 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001052
Johnny Chen10530c22011-02-17 22:37:12 +00001053 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001054 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001055 }
1056 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001057}
1058
Johnny Chend642a6a2011-02-22 01:01:03 +00001059// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1060// It can optionally update the condition flags based on the result.
1061bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001062EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001063{
1064#if 0
1065 // ARM pseudo code...
1066 if (ConditionPassed())
1067 {
1068 EncodingSpecificOperations();
1069 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1070 result = NOT(shifted);
1071 if d == 15 then // Can only occur for ARM encoding
1072 ALUWritePC(result); // setflags is always FALSE here
1073 else
1074 R[d] = result;
1075 if setflags then
1076 APSR.N = result<31>;
1077 APSR.Z = IsZeroBit(result);
1078 APSR.C = carry;
1079 // APSR.V unchanged
1080 }
1081#endif
1082
Greg Clayton7bc39082011-03-24 23:53:38 +00001083 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001084 {
1085 uint32_t Rm; // the source register
1086 uint32_t Rd; // the destination register
1087 ARM_ShifterType shift_t;
1088 uint32_t shift_n; // the shift applied to the value read from Rm
1089 bool setflags;
1090 uint32_t carry; // the carry bit after the shift operation
1091 switch (encoding) {
1092 case eEncodingT1:
1093 Rd = Bits32(opcode, 2, 0);
1094 Rm = Bits32(opcode, 5, 3);
1095 setflags = !InITBlock();
1096 shift_t = SRType_LSL;
1097 shift_n = 0;
1098 if (InITBlock())
1099 return false;
1100 break;
1101 case eEncodingT2:
1102 Rd = Bits32(opcode, 11, 8);
1103 Rm = Bits32(opcode, 3, 0);
1104 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001105 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001106 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001107 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001108 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001109 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001110 case eEncodingA1:
1111 Rd = Bits32(opcode, 15, 12);
1112 Rm = Bits32(opcode, 3, 0);
1113 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001114 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001115 break;
1116 default:
1117 return false;
1118 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001119 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001120 uint32_t value = ReadCoreReg(Rm, &success);
1121 if (!success)
1122 return false;
1123
Johnny Chena4438a72011-06-02 22:50:51 +00001124 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1125 if (!success)
1126 return false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001127 uint32_t result = ~shifted;
1128
1129 // The context specifies that an immediate is to be moved into Rd.
1130 EmulateInstruction::Context context;
1131 context.type = EmulateInstruction::eContextImmediate;
1132 context.SetNoArgs ();
1133
1134 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1135 return false;
1136 }
1137 return true;
1138}
1139
Johnny Chen788e0552011-01-27 22:52:23 +00001140// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1141// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001142bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001143EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001144{
1145#if 0
1146 // ARM pseudo code...
1147 if (ConditionPassed())
1148 {
1149 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1150 base = Align(PC,4);
1151 address = if add then (base + imm32) else (base - imm32);
1152 data = MemU[address,4];
1153 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001154 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1155 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001156 R[t] = data;
1157 else // Can only apply before ARMv7
1158 if CurrentInstrSet() == InstrSet_ARM then
1159 R[t] = ROR(data, 8*UInt(address<1:0>));
1160 else
1161 R[t] = bits(32) UNKNOWN;
1162 }
1163#endif
1164
Greg Clayton7bc39082011-03-24 23:53:38 +00001165 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001166 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001167 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001168 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001169 if (!success)
1170 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001171
1172 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001173 EmulateInstruction::Context context;
1174 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001175 RegisterInfo pc_reg;
1176 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001177 context.SetRegisterPlusOffset (pc_reg, 0);
1178
Johnny Chenc9de9102011-02-11 19:12:30 +00001179 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001180 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001181 bool add; // +imm32 or -imm32?
1182 addr_t base; // the base address
1183 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001184 uint32_t data; // the literal data value from the PC relative load
1185 switch (encoding) {
1186 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001187 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001188 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001189 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001190 break;
1191 case eEncodingT2:
1192 Rt = Bits32(opcode, 15, 12);
1193 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1194 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001195 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001196 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001197 break;
1198 default:
1199 return false;
1200 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001201
Johnny Chene39f22d2011-02-19 01:36:13 +00001202 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001203 if (add)
1204 address = base + imm32;
1205 else
1206 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001207
1208 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001209 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001210 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001211 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001212
1213 if (Rt == 15)
1214 {
1215 if (Bits32(address, 1, 0) == 0)
1216 {
1217 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001218 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001219 return false;
1220 }
1221 else
1222 return false;
1223 }
1224 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1225 {
1226 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1227 return false;
1228 }
1229 else // We don't handle ARM for now.
1230 return false;
1231
Johnny Chen788e0552011-01-27 22:52:23 +00001232 }
1233 return true;
1234}
1235
Johnny Chen5b442b72011-01-27 19:34:30 +00001236// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001237// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001238bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001239EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001240{
1241#if 0
1242 // ARM pseudo code...
1243 if (ConditionPassed())
1244 {
1245 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001246 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001247 if d == 15 then // Can only occur for ARM encoding
1248 ALUWritePC(result); // setflags is always FALSE here
1249 else
1250 R[d] = result;
1251 if setflags then
1252 APSR.N = result<31>;
1253 APSR.Z = IsZeroBit(result);
1254 APSR.C = carry;
1255 APSR.V = overflow;
1256 }
1257#endif
1258
1259 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001260
Greg Clayton7bc39082011-03-24 23:53:38 +00001261 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001262 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001263 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001264 if (!success)
1265 return false;
1266 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001267 uint32_t d;
1268 bool setflags;
1269 switch (encoding)
1270 {
1271 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001272 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001273 d = Bits32 (opcode, 10, 8);
1274 setflags = false;
1275 imm32 = (Bits32 (opcode, 7, 0) << 2);
1276
1277 break;
1278
1279 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001280 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001281 d = 13;
1282 setflags = false;
1283 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1284
1285 break;
1286
1287 default:
1288 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001289 }
1290 addr_t sp_offset = imm32;
1291 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1292
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001293 EmulateInstruction::Context context;
1294 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +00001295 RegisterInfo sp_reg;
1296 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001297 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001298
Caroline Ticee2212882011-03-22 22:38:28 +00001299 if (d == 15)
1300 {
1301 if (!ALUWritePC (context, addr))
1302 return false;
1303 }
1304 else
1305 {
1306 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1307 return false;
1308 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001309 }
1310 return true;
1311}
1312
1313// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001314// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001315bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001316EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001317{
1318#if 0
1319 // ARM pseudo code...
1320 if (ConditionPassed())
1321 {
1322 EncodingSpecificOperations();
1323 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001324 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001325 if d == 15 then
1326 ALUWritePC(result); // setflags is always FALSE here
1327 else
1328 R[d] = result;
1329 if setflags then
1330 APSR.N = result<31>;
1331 APSR.Z = IsZeroBit(result);
1332 APSR.C = carry;
1333 APSR.V = overflow;
1334 }
1335#endif
1336
1337 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001338
Greg Clayton7bc39082011-03-24 23:53:38 +00001339 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001340 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001341 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001342 if (!success)
1343 return false;
1344 uint32_t Rm; // the second operand
1345 switch (encoding) {
1346 case eEncodingT2:
1347 Rm = Bits32(opcode, 6, 3);
1348 break;
1349 default:
1350 return false;
1351 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001352 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001353 if (!success)
1354 return false;
1355
1356 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1357
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001358 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00001359 context.type = eContextArithmetic;
1360 RegisterInfo sp_reg;
1361 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1362
1363 RegisterInfo other_reg;
1364 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001365 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001366
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001367 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001368 return false;
1369 }
1370 return true;
1371}
1372
Johnny Chen9b8d7832011-02-02 01:13:56 +00001373// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1374// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1375// from Thumb to ARM.
1376// BLX (immediate)
1377bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001378EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001379{
1380#if 0
1381 // ARM pseudo code...
1382 if (ConditionPassed())
1383 {
1384 EncodingSpecificOperations();
1385 if CurrentInstrSet() == InstrSet_ARM then
1386 LR = PC - 4;
1387 else
1388 LR = PC<31:1> : '1';
1389 if targetInstrSet == InstrSet_ARM then
1390 targetAddress = Align(PC,4) + imm32;
1391 else
1392 targetAddress = PC + imm32;
1393 SelectInstrSet(targetInstrSet);
1394 BranchWritePC(targetAddress);
1395 }
1396#endif
1397
Greg Clayton7bc39082011-03-24 23:53:38 +00001398 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001399
Greg Clayton7bc39082011-03-24 23:53:38 +00001400 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001401 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001402 EmulateInstruction::Context context;
1403 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001404 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001405 if (!success)
1406 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001407 addr_t lr; // next instruction address
1408 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001409 int32_t imm32; // PC-relative offset
1410 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001411 case eEncodingT1:
1412 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001413 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001414 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001415 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001416 uint32_t J1 = Bit32(opcode, 13);
1417 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001418 uint32_t imm11 = Bits32(opcode, 10, 0);
1419 uint32_t I1 = !(J1 ^ S);
1420 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001421 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001422 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001423 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001424 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001425 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001426 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001427 break;
1428 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001429 case eEncodingT2:
1430 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001431 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001432 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001433 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001434 uint32_t J1 = Bit32(opcode, 13);
1435 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001436 uint32_t imm10L = Bits32(opcode, 10, 1);
1437 uint32_t I1 = !(J1 ^ S);
1438 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001439 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001440 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001441 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001442 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001443 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001444 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001445 break;
1446 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001447 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001448 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001449 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001450 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001451 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001452 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001453 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001454 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001455 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001456 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001457 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001458 break;
1459 default:
1460 return false;
1461 }
1462 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1463 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001464 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001465 return false;
1466 }
1467 return true;
1468}
1469
1470// Branch with Link and Exchange (register) calls a subroutine at an address and
1471// instruction set specified by a register.
1472// BLX (register)
1473bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001474EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001475{
1476#if 0
1477 // ARM pseudo code...
1478 if (ConditionPassed())
1479 {
1480 EncodingSpecificOperations();
1481 target = R[m];
1482 if CurrentInstrSet() == InstrSet_ARM then
1483 next_instr_addr = PC - 4;
1484 LR = next_instr_addr;
1485 else
1486 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001487 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001488 BXWritePC(target);
1489 }
1490#endif
1491
1492 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001493
Greg Clayton7bc39082011-03-24 23:53:38 +00001494 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001495 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001496 EmulateInstruction::Context context;
1497 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001498 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001499 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001500 if (!success)
1501 return false;
1502 uint32_t Rm; // the register with the target address
1503 switch (encoding) {
1504 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001505 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001506 Rm = Bits32(opcode, 6, 3);
1507 // if m == 15 then UNPREDICTABLE;
1508 if (Rm == 15)
1509 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001510 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001511 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001512 break;
1513 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001514 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001515 Rm = Bits32(opcode, 3, 0);
1516 // if m == 15 then UNPREDICTABLE;
1517 if (Rm == 15)
1518 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001519 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001520 default:
1521 return false;
1522 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001523 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001524 if (!success)
1525 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001526 RegisterInfo dwarf_reg;
1527 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001528 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001529 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1530 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001531 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001532 return false;
1533 }
1534 return true;
1535}
1536
Johnny Chenab3b3512011-02-12 00:10:51 +00001537// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001538bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001539EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001540{
1541#if 0
1542 // ARM pseudo code...
1543 if (ConditionPassed())
1544 {
1545 EncodingSpecificOperations();
1546 BXWritePC(R[m]);
1547 }
1548#endif
1549
Greg Clayton7bc39082011-03-24 23:53:38 +00001550 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001551 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001552 EmulateInstruction::Context context;
1553 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001554 uint32_t Rm; // the register with the target address
1555 switch (encoding) {
1556 case eEncodingT1:
1557 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001558 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001559 return false;
1560 break;
1561 case eEncodingA1:
1562 Rm = Bits32(opcode, 3, 0);
1563 break;
1564 default:
1565 return false;
1566 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001567 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001568 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001569 if (!success)
1570 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001571
1572 RegisterInfo dwarf_reg;
1573 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen668b4512011-02-15 21:08:58 +00001574 context.SetRegister (dwarf_reg);
1575 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001576 return false;
1577 }
1578 return true;
1579}
1580
Johnny Chen59e6ab72011-02-24 21:01:20 +00001581// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1582// address and instruction set specified by a register as though it were a BX instruction.
1583//
1584// TODO: Emulate Jazelle architecture?
1585// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1586bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001587EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001588{
1589#if 0
1590 // ARM pseudo code...
1591 if (ConditionPassed())
1592 {
1593 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001594 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001595 BXWritePC(R[m]);
1596 else
1597 if JazelleAcceptsExecution() then
1598 SwitchToJazelleExecution();
1599 else
1600 SUBARCHITECTURE_DEFINED handler call;
1601 }
1602#endif
1603
Greg Clayton7bc39082011-03-24 23:53:38 +00001604 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001605 {
1606 EmulateInstruction::Context context;
1607 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1608 uint32_t Rm; // the register with the target address
1609 switch (encoding) {
1610 case eEncodingT1:
1611 Rm = Bits32(opcode, 19, 16);
1612 if (BadReg(Rm))
1613 return false;
1614 if (InITBlock() && !LastInITBlock())
1615 return false;
1616 break;
1617 case eEncodingA1:
1618 Rm = Bits32(opcode, 3, 0);
1619 if (Rm == 15)
1620 return false;
1621 break;
1622 default:
1623 return false;
1624 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001625 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001626 addr_t target = ReadCoreReg (Rm, &success);
1627 if (!success)
1628 return false;
1629
Greg Claytonc07d4512011-04-26 23:48:45 +00001630 RegisterInfo dwarf_reg;
1631 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen59e6ab72011-02-24 21:01:20 +00001632 context.SetRegister (dwarf_reg);
1633 if (!BXWritePC(context, target))
1634 return false;
1635 }
1636 return true;
1637}
1638
Johnny Chen0d0148e2011-01-28 02:26:08 +00001639// Set r7 to point to some ip offset.
1640// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001641bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001642EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001643{
1644#if 0
1645 // ARM pseudo code...
1646 if (ConditionPassed())
1647 {
1648 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001649 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001650 if d == 15 then // Can only occur for ARM encoding
1651 ALUWritePC(result); // setflags is always FALSE here
1652 else
1653 R[d] = result;
1654 if setflags then
1655 APSR.N = result<31>;
1656 APSR.Z = IsZeroBit(result);
1657 APSR.C = carry;
1658 APSR.V = overflow;
1659 }
1660#endif
1661
Greg Clayton7bc39082011-03-24 23:53:38 +00001662 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001663 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001664 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001665 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001666 if (!success)
1667 return false;
1668 uint32_t imm32;
1669 switch (encoding) {
1670 case eEncodingA1:
1671 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1672 break;
1673 default:
1674 return false;
1675 }
1676 addr_t ip_offset = imm32;
1677 addr_t addr = ip - ip_offset; // the adjusted ip value
1678
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001679 EmulateInstruction::Context context;
1680 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001681 RegisterInfo dwarf_reg;
1682 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001683 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001684
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001685 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001686 return false;
1687 }
1688 return true;
1689}
1690
1691// Set ip to point to some stack offset.
1692// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001693bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001694EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001695{
1696#if 0
1697 // ARM pseudo code...
1698 if (ConditionPassed())
1699 {
1700 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001701 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001702 if d == 15 then // Can only occur for ARM encoding
1703 ALUWritePC(result); // setflags is always FALSE here
1704 else
1705 R[d] = result;
1706 if setflags then
1707 APSR.N = result<31>;
1708 APSR.Z = IsZeroBit(result);
1709 APSR.C = carry;
1710 APSR.V = overflow;
1711 }
1712#endif
1713
Greg Clayton7bc39082011-03-24 23:53:38 +00001714 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001715 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001716 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001717 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001718 if (!success)
1719 return false;
1720 uint32_t imm32;
1721 switch (encoding) {
1722 case eEncodingA1:
1723 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1724 break;
1725 default:
1726 return false;
1727 }
1728 addr_t sp_offset = imm32;
1729 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1730
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001731 EmulateInstruction::Context context;
1732 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001733 RegisterInfo dwarf_reg;
1734 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001735 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001736
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001737 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001738 return false;
1739 }
1740 return true;
1741}
1742
Johnny Chenc9e747f2011-02-23 01:55:07 +00001743// This instruction subtracts an immediate value from the SP value, and writes
1744// the result to the destination register.
1745//
1746// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001747bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001748EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001749{
1750#if 0
1751 // ARM pseudo code...
1752 if (ConditionPassed())
1753 {
1754 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001755 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001756 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001757 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001758 else
1759 R[d] = result;
1760 if setflags then
1761 APSR.N = result<31>;
1762 APSR.Z = IsZeroBit(result);
1763 APSR.C = carry;
1764 APSR.V = overflow;
1765 }
1766#endif
1767
1768 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001769 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001770 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001771 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001772 if (!success)
1773 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001774
1775 uint32_t Rd;
1776 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001777 uint32_t imm32;
1778 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001779 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001780 Rd = 13;
1781 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001782 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001783 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001784 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001785 Rd = Bits32(opcode, 11, 8);
1786 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001787 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001788 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001789 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001790 if (Rd == 15 && !setflags)
1791 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001792 break;
1793 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001794 Rd = Bits32(opcode, 11, 8);
1795 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001796 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001797 if (Rd == 15)
1798 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001799 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001800 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001801 Rd = Bits32(opcode, 15, 12);
1802 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001803 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001804
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001805 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001806 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001807 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001808 break;
1809 default:
1810 return false;
1811 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001812 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1813
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001814 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001815 if (Rd == 13)
1816 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001817 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1818 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001819 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001820 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001821 }
1822 else
1823 {
1824 context.type = EmulateInstruction::eContextImmediate;
1825 context.SetNoArgs ();
1826 }
1827
1828 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001829 return false;
1830 }
1831 return true;
1832}
1833
Johnny Chen08c25e82011-01-31 18:02:28 +00001834// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001835bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001836EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001837{
1838#if 0
1839 // ARM pseudo code...
1840 if (ConditionPassed())
1841 {
1842 EncodingSpecificOperations();
1843 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1844 address = if index then offset_addr else R[n];
1845 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1846 if wback then R[n] = offset_addr;
1847 }
1848#endif
1849
1850 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001851
Greg Clayton7bc39082011-03-24 23:53:38 +00001852 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001853 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001854 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001855 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001856 if (!success)
1857 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001858 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001859 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001860 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1861
1862 bool index;
1863 bool add;
1864 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001865 switch (encoding) {
1866 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001867 Rt = Bits32(opcode, 15, 12);
1868 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001869 Rn = Bits32 (opcode, 19, 16);
1870
1871 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1872 return false;
1873
1874 index = BitIsSet (opcode, 24);
1875 add = BitIsSet (opcode, 23);
1876 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1877
1878 if (wback && ((Rn == 15) || (Rn == Rt)))
1879 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001880 break;
1881 default:
1882 return false;
1883 }
Caroline Tice3e407972011-03-18 19:41:00 +00001884 addr_t offset_addr;
1885 if (add)
1886 offset_addr = sp + imm12;
1887 else
1888 offset_addr = sp - imm12;
1889
1890 addr_t addr;
1891 if (index)
1892 addr = offset_addr;
1893 else
1894 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001895
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001896 EmulateInstruction::Context context;
1897 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001898 RegisterInfo sp_reg;
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001899 RegisterInfo dwarf_reg;
1900
Greg Claytonc07d4512011-04-26 23:48:45 +00001901 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001902 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1903 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001904 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001905 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001906 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001907 if (!success)
1908 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001909 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001910 return false;
1911 }
1912 else
1913 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001914 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001915 if (!success)
1916 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001917 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001918 return false;
1919 }
1920
Caroline Tice3e407972011-03-18 19:41:00 +00001921
1922 if (wback)
1923 {
1924 context.type = EmulateInstruction::eContextAdjustStackPointer;
1925 context.SetImmediateSigned (addr - sp);
1926 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1927 return false;
1928 }
Johnny Chence1ca772011-01-25 01:13:00 +00001929 }
1930 return true;
1931}
1932
Johnny Chen08c25e82011-01-31 18:02:28 +00001933// Vector Push stores multiple extension registers to the stack.
1934// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001935bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001936EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001937{
1938#if 0
1939 // ARM pseudo code...
1940 if (ConditionPassed())
1941 {
1942 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1943 address = SP - imm32;
1944 SP = SP - imm32;
1945 if single_regs then
1946 for r = 0 to regs-1
1947 MemA[address,4] = S[d+r]; address = address+4;
1948 else
1949 for r = 0 to regs-1
1950 // Store as two word-aligned words in the correct order for current endianness.
1951 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1952 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1953 address = address+8;
1954 }
1955#endif
1956
1957 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001958
Greg Clayton7bc39082011-03-24 23:53:38 +00001959 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001960 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001961 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001962 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001963 if (!success)
1964 return false;
1965 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001966 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001967 uint32_t imm32; // stack offset
1968 uint32_t regs; // number of registers
1969 switch (encoding) {
1970 case eEncodingT1:
1971 case eEncodingA1:
1972 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001973 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001974 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1975 // If UInt(imm8) is odd, see "FSTMX".
1976 regs = Bits32(opcode, 7, 0) / 2;
1977 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1978 if (regs == 0 || regs > 16 || (d + regs) > 32)
1979 return false;
1980 break;
1981 case eEncodingT2:
1982 case eEncodingA2:
1983 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001984 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001985 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1986 regs = Bits32(opcode, 7, 0);
1987 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1988 if (regs == 0 || regs > 16 || (d + regs) > 32)
1989 return false;
1990 break;
1991 default:
1992 return false;
1993 }
1994 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1995 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1996 addr_t sp_offset = imm32;
1997 addr_t addr = sp - sp_offset;
1998 uint32_t i;
1999
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002000 EmulateInstruction::Context context;
2001 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002002 RegisterInfo dwarf_reg;
2003 RegisterInfo sp_reg;
2004 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002005 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00002006 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002007 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002008 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00002009 // uint64_t to accommodate 64-bit registers.
Greg Clayton061b79d2011-05-09 20:18:18 +00002010 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00002011 if (!success)
2012 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002013 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00002014 return false;
2015 addr += reg_byte_size;
2016 }
2017
2018 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002019 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00002020
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002021 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00002022 return false;
2023 }
2024 return true;
2025}
2026
Johnny Chen587a0a42011-02-01 18:35:28 +00002027// Vector Pop loads multiple extension registers from the stack.
2028// It also updates SP to point just above the loaded data.
2029bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002030EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00002031{
2032#if 0
2033 // ARM pseudo code...
2034 if (ConditionPassed())
2035 {
2036 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2037 address = SP;
2038 SP = SP + imm32;
2039 if single_regs then
2040 for r = 0 to regs-1
2041 S[d+r] = MemA[address,4]; address = address+4;
2042 else
2043 for r = 0 to regs-1
2044 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2045 // Combine the word-aligned words in the correct order for current endianness.
2046 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2047 }
2048#endif
2049
2050 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002051
Greg Clayton7bc39082011-03-24 23:53:38 +00002052 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002053 {
2054 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002055 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002056 if (!success)
2057 return false;
2058 bool single_regs;
2059 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2060 uint32_t imm32; // stack offset
2061 uint32_t regs; // number of registers
2062 switch (encoding) {
2063 case eEncodingT1:
2064 case eEncodingA1:
2065 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002066 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002067 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2068 // If UInt(imm8) is odd, see "FLDMX".
2069 regs = Bits32(opcode, 7, 0) / 2;
2070 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2071 if (regs == 0 || regs > 16 || (d + regs) > 32)
2072 return false;
2073 break;
2074 case eEncodingT2:
2075 case eEncodingA2:
2076 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002077 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002078 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2079 regs = Bits32(opcode, 7, 0);
2080 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2081 if (regs == 0 || regs > 16 || (d + regs) > 32)
2082 return false;
2083 break;
2084 default:
2085 return false;
2086 }
2087 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2088 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2089 addr_t sp_offset = imm32;
2090 addr_t addr = sp;
2091 uint32_t i;
2092 uint64_t data; // uint64_t to accomodate 64-bit registers.
2093
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002094 EmulateInstruction::Context context;
2095 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002096 RegisterInfo dwarf_reg;
2097 RegisterInfo sp_reg;
2098 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002099 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002100 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002101 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002102 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002103 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002104 if (!success)
2105 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +00002106 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002107 return false;
2108 addr += reg_byte_size;
2109 }
2110
2111 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002112 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002113
2114 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2115 return false;
2116 }
2117 return true;
2118}
2119
Johnny Chenb77be412011-02-04 00:40:18 +00002120// SVC (previously SWI)
2121bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002122EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002123{
2124#if 0
2125 // ARM pseudo code...
2126 if (ConditionPassed())
2127 {
2128 EncodingSpecificOperations();
2129 CallSupervisor();
2130 }
2131#endif
2132
2133 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002134
Greg Clayton7bc39082011-03-24 23:53:38 +00002135 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002136 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002137 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002138 addr_t lr; // next instruction address
2139 if (!success)
2140 return false;
2141 uint32_t imm32; // the immediate constant
2142 uint32_t mode; // ARM or Thumb mode
2143 switch (encoding) {
2144 case eEncodingT1:
2145 lr = (pc + 2) | 1u; // return address
2146 imm32 = Bits32(opcode, 7, 0);
2147 mode = eModeThumb;
2148 break;
2149 case eEncodingA1:
2150 lr = pc + 4; // return address
2151 imm32 = Bits32(opcode, 23, 0);
2152 mode = eModeARM;
2153 break;
2154 default:
2155 return false;
2156 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002157
2158 EmulateInstruction::Context context;
2159 context.type = EmulateInstruction::eContextSupervisorCall;
Greg Claytonc07d4512011-04-26 23:48:45 +00002160 context.SetISAAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002161 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2162 return false;
2163 }
2164 return true;
2165}
2166
Johnny Chenc315f862011-02-05 00:46:10 +00002167// If Then makes up to four following instructions (the IT block) conditional.
2168bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002169EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002170{
2171#if 0
2172 // ARM pseudo code...
2173 EncodingSpecificOperations();
2174 ITSTATE.IT<7:0> = firstcond:mask;
2175#endif
2176
Johnny Chenc315f862011-02-05 00:46:10 +00002177 m_it_session.InitIT(Bits32(opcode, 7, 0));
2178 return true;
2179}
2180
Greg Clayton04d397c2011-05-23 18:04:09 +00002181bool
2182EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding)
2183{
2184 // NOP, nothing to do...
2185 return true;
2186}
2187
Johnny Chen3b620b32011-02-07 20:11:47 +00002188// Branch causes a branch to a target address.
2189bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002190EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002191{
2192#if 0
2193 // ARM pseudo code...
2194 if (ConditionPassed())
2195 {
2196 EncodingSpecificOperations();
2197 BranchWritePC(PC + imm32);
2198 }
2199#endif
2200
2201 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002202
Greg Clayton7bc39082011-03-24 23:53:38 +00002203 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002204 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002205 EmulateInstruction::Context context;
2206 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002207 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002208 if (!success)
2209 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002210 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002211 int32_t imm32; // PC-relative offset
2212 switch (encoding) {
2213 case eEncodingT1:
2214 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2215 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002216 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002217 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002218 break;
2219 case eEncodingT2:
2220 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002221 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002222 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002223 break;
2224 case eEncodingT3:
2225 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2226 {
Johnny Chenbd599902011-02-10 21:39:01 +00002227 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002228 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002229 uint32_t J1 = Bit32(opcode, 13);
2230 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002231 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002232 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002233 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002234 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002235 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002236 break;
2237 }
2238 case eEncodingT4:
2239 {
Johnny Chenbd599902011-02-10 21:39:01 +00002240 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002241 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002242 uint32_t J1 = Bit32(opcode, 13);
2243 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002244 uint32_t imm11 = Bits32(opcode, 10, 0);
2245 uint32_t I1 = !(J1 ^ S);
2246 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002247 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002248 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002249 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002250 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002251 break;
2252 }
2253 case eEncodingA1:
2254 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002255 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002256 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002257 break;
2258 default:
2259 return false;
2260 }
2261 if (!BranchWritePC(context, target))
2262 return false;
2263 }
2264 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002265}
2266
Johnny Chen53ebab72011-02-08 23:21:57 +00002267// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2268// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2269// CBNZ, CBZ
2270bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002271EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002272{
2273#if 0
2274 // ARM pseudo code...
2275 EncodingSpecificOperations();
2276 if nonzero ^ IsZero(R[n]) then
2277 BranchWritePC(PC + imm32);
2278#endif
2279
2280 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002281
2282 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002283 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002284 if (!success)
2285 return false;
2286
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002287 EmulateInstruction::Context context;
2288 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002289 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002290 if (!success)
2291 return false;
2292
2293 addr_t target; // target address
2294 uint32_t imm32; // PC-relative offset to branch forward
2295 bool nonzero;
2296 switch (encoding) {
2297 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002298 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002299 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002300 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002301 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002302 break;
2303 default:
2304 return false;
2305 }
2306 if (nonzero ^ (reg_val == 0))
2307 if (!BranchWritePC(context, target))
2308 return false;
2309
2310 return true;
2311}
2312
Johnny Chen60299ec2011-02-17 19:34:27 +00002313// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2314// A base register provides a pointer to the table, and a second register supplies an index into the table.
2315// The branch length is twice the value of the byte returned from the table.
2316//
2317// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2318// A base register provides a pointer to the table, and a second register supplies an index into the table.
2319// The branch length is twice the value of the halfword returned from the table.
2320// TBB, TBH
2321bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002322EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002323{
2324#if 0
2325 // ARM pseudo code...
2326 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2327 if is_tbh then
2328 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2329 else
2330 halfwords = UInt(MemU[R[n]+R[m], 1]);
2331 BranchWritePC(PC + 2*halfwords);
2332#endif
2333
2334 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002335
2336 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2337 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2338 bool is_tbh; // true if table branch halfword
2339 switch (encoding) {
2340 case eEncodingT1:
2341 Rn = Bits32(opcode, 19, 16);
2342 Rm = Bits32(opcode, 3, 0);
2343 is_tbh = BitIsSet(opcode, 4);
2344 if (Rn == 13 || BadReg(Rm))
2345 return false;
2346 if (InITBlock() && !LastInITBlock())
2347 return false;
2348 break;
2349 default:
2350 return false;
2351 }
2352
2353 // Read the address of the table from the operand register Rn.
2354 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002355 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002356 if (!success)
2357 return false;
2358
2359 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002360 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002361 if (!success)
2362 return false;
2363
2364 // the offsetted table address
2365 addr_t addr = base + (is_tbh ? index*2 : index);
2366
2367 // PC-relative offset to branch forward
2368 EmulateInstruction::Context context;
2369 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002370 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002371 if (!success)
2372 return false;
2373
Johnny Chene39f22d2011-02-19 01:36:13 +00002374 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002375 if (!success)
2376 return false;
2377
2378 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002379 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002380 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Greg Claytonc07d4512011-04-26 23:48:45 +00002381 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
Johnny Chen60299ec2011-02-17 19:34:27 +00002382
2383 if (!BranchWritePC(context, target))
2384 return false;
2385
2386 return true;
2387}
2388
Caroline Ticedcc11b32011-03-02 23:57:02 +00002389// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2390// It can optionally update the condition flags based on the result.
2391bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002392EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002393{
2394#if 0
2395 if ConditionPassed() then
2396 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002397 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002398 R[d] = result;
2399 if setflags then
2400 APSR.N = result<31>;
2401 APSR.Z = IsZeroBit(result);
2402 APSR.C = carry;
2403 APSR.V = overflow;
2404#endif
2405
2406 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002407
Greg Clayton7bc39082011-03-24 23:53:38 +00002408 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002409 {
2410 uint32_t d;
2411 uint32_t n;
2412 bool setflags;
2413 uint32_t imm32;
2414 uint32_t carry_out;
2415
2416 //EncodingSpecificOperations();
2417 switch (encoding)
2418 {
2419 case eEncodingT1:
2420 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2421 d = Bits32 (opcode, 2, 0);
2422 n = Bits32 (opcode, 5, 3);
2423 setflags = !InITBlock();
2424 imm32 = Bits32 (opcode, 8,6);
2425
2426 break;
2427
2428 case eEncodingT2:
2429 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2430 d = Bits32 (opcode, 10, 8);
2431 n = Bits32 (opcode, 10, 8);
2432 setflags = !InITBlock();
2433 imm32 = Bits32 (opcode, 7, 0);
2434
2435 break;
2436
2437 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002438 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2439 // if Rn == '1101' then SEE ADD (SP plus immediate);
2440 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002441 d = Bits32 (opcode, 11, 8);
2442 n = Bits32 (opcode, 19, 16);
2443 setflags = BitIsSet (opcode, 20);
2444 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2445
2446 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2447 if (BadReg (d) || (n == 15))
2448 return false;
2449
2450 break;
2451
2452 case eEncodingT4:
2453 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002454 // if Rn == '1111' then SEE ADR;
2455 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002456 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2457 d = Bits32 (opcode, 11, 8);
2458 n = Bits32 (opcode, 19, 16);
2459 setflags = false;
2460 uint32_t i = Bit32 (opcode, 26);
2461 uint32_t imm3 = Bits32 (opcode, 14, 12);
2462 uint32_t imm8 = Bits32 (opcode, 7, 0);
2463 imm32 = (i << 11) | (imm3 << 8) | imm8;
2464
2465 // if BadReg(d) then UNPREDICTABLE;
2466 if (BadReg (d))
2467 return false;
2468
2469 break;
2470 }
2471 default:
2472 return false;
2473 }
2474
2475 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2476 if (!success)
2477 return false;
2478
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002479 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002480 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2481
Greg Claytonc07d4512011-04-26 23:48:45 +00002482 RegisterInfo reg_n;
2483 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002484
2485 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002486 context.type = eContextArithmetic;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002487 context.SetRegisterPlusOffset (reg_n, imm32);
2488
2489 //R[d] = result;
2490 //if setflags then
2491 //APSR.N = result<31>;
2492 //APSR.Z = IsZeroBit(result);
2493 //APSR.C = carry;
2494 //APSR.V = overflow;
2495 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2496 return false;
2497
2498 }
2499 return true;
2500}
2501
Johnny Chen8fa20592011-02-18 01:22:22 +00002502// This instruction adds an immediate value to a register value, and writes the result to the destination
2503// register. It can optionally update the condition flags based on the result.
2504bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002505EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002506{
2507#if 0
2508 // ARM pseudo code...
2509 if ConditionPassed() then
2510 EncodingSpecificOperations();
2511 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2512 if d == 15 then
2513 ALUWritePC(result); // setflags is always FALSE here
2514 else
2515 R[d] = result;
2516 if setflags then
2517 APSR.N = result<31>;
2518 APSR.Z = IsZeroBit(result);
2519 APSR.C = carry;
2520 APSR.V = overflow;
2521#endif
2522
2523 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002524
Greg Clayton7bc39082011-03-24 23:53:38 +00002525 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002526 {
2527 uint32_t Rd, Rn;
2528 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2529 bool setflags;
2530 switch (encoding)
2531 {
2532 case eEncodingA1:
2533 Rd = Bits32(opcode, 15, 12);
2534 Rn = Bits32(opcode, 19, 16);
2535 setflags = BitIsSet(opcode, 20);
2536 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2537 break;
2538 default:
2539 return false;
2540 }
2541
Johnny Chen8fa20592011-02-18 01:22:22 +00002542 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002543 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002544 if (!success)
2545 return false;
2546
2547 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2548
2549 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002550 context.type = eContextArithmetic;
2551 RegisterInfo dwarf_reg;
2552 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00002553 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002554
2555 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2556 return false;
2557 }
2558 return true;
2559}
2560
Johnny Chend761dcf2011-02-17 22:03:29 +00002561// This instruction adds a register value and an optionally-shifted register value, and writes the result
2562// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002563bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002564EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002565{
2566#if 0
2567 // ARM pseudo code...
2568 if ConditionPassed() then
2569 EncodingSpecificOperations();
2570 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2571 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2572 if d == 15 then
2573 ALUWritePC(result); // setflags is always FALSE here
2574 else
2575 R[d] = result;
2576 if setflags then
2577 APSR.N = result<31>;
2578 APSR.Z = IsZeroBit(result);
2579 APSR.C = carry;
2580 APSR.V = overflow;
2581#endif
2582
2583 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002584
Greg Clayton7bc39082011-03-24 23:53:38 +00002585 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002586 {
2587 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002588 ARM_ShifterType shift_t;
2589 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002590 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002591 switch (encoding)
2592 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002593 case eEncodingT1:
2594 Rd = Bits32(opcode, 2, 0);
2595 Rn = Bits32(opcode, 5, 3);
2596 Rm = Bits32(opcode, 8, 6);
2597 setflags = !InITBlock();
2598 shift_t = SRType_LSL;
2599 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002600 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002601 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002602 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002603 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002604 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002605 shift_t = SRType_LSL;
2606 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002607 if (Rn == 15 && Rm == 15)
2608 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002609 if (Rd == 15 && InITBlock() && !LastInITBlock())
2610 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002611 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002612 case eEncodingA1:
2613 Rd = Bits32(opcode, 15, 12);
2614 Rn = Bits32(opcode, 19, 16);
2615 Rm = Bits32(opcode, 3, 0);
2616 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002617 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002618 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002619 default:
2620 return false;
2621 }
2622
Johnny Chen26863dc2011-02-09 23:43:29 +00002623 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002624 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002625 if (!success)
2626 return false;
2627
2628 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002629 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002630 if (!success)
2631 return false;
2632
Johnny Chena4438a72011-06-02 22:50:51 +00002633 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2634 if (!success)
2635 return false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002636 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002637
2638 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002639 context.type = eContextArithmetic;
2640 RegisterInfo op1_reg;
2641 RegisterInfo op2_reg;
2642 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2643 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00002644 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002645
Johnny Chen10530c22011-02-17 22:37:12 +00002646 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002647 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002648 }
2649 return true;
2650}
2651
Johnny Chen34075cb2011-02-22 01:56:31 +00002652// Compare Negative (immediate) adds a register value and an immediate value.
2653// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002654bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002655EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002656{
2657#if 0
2658 // ARM pseudo code...
2659 if ConditionPassed() then
2660 EncodingSpecificOperations();
2661 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2662 APSR.N = result<31>;
2663 APSR.Z = IsZeroBit(result);
2664 APSR.C = carry;
2665 APSR.V = overflow;
2666#endif
2667
2668 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002669
2670 uint32_t Rn; // the first operand
2671 uint32_t imm32; // the immediate value to be compared with
2672 switch (encoding) {
2673 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002674 Rn = Bits32(opcode, 19, 16);
2675 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2676 if (Rn == 15)
2677 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002678 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002679 case eEncodingA1:
2680 Rn = Bits32(opcode, 19, 16);
2681 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2682 break;
2683 default:
2684 return false;
2685 }
2686 // Read the register value from the operand register Rn.
2687 uint32_t reg_val = ReadCoreReg(Rn, &success);
2688 if (!success)
2689 return false;
2690
Johnny Chen078fbc62011-02-22 19:48:22 +00002691 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002692
2693 EmulateInstruction::Context context;
2694 context.type = EmulateInstruction::eContextImmediate;
2695 context.SetNoArgs ();
2696 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2697 return false;
2698
2699 return true;
2700}
2701
2702// Compare Negative (register) adds a register value and an optionally-shifted register value.
2703// It updates the condition flags based on the result, and discards the result.
2704bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002705EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002706{
2707#if 0
2708 // ARM pseudo code...
2709 if ConditionPassed() then
2710 EncodingSpecificOperations();
2711 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2712 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2713 APSR.N = result<31>;
2714 APSR.Z = IsZeroBit(result);
2715 APSR.C = carry;
2716 APSR.V = overflow;
2717#endif
2718
2719 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002720
2721 uint32_t Rn; // the first operand
2722 uint32_t Rm; // the second operand
2723 ARM_ShifterType shift_t;
2724 uint32_t shift_n; // the shift applied to the value read from Rm
2725 switch (encoding) {
2726 case eEncodingT1:
2727 Rn = Bits32(opcode, 2, 0);
2728 Rm = Bits32(opcode, 5, 3);
2729 shift_t = SRType_LSL;
2730 shift_n = 0;
2731 break;
2732 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002733 Rn = Bits32(opcode, 19, 16);
2734 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002735 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002736 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2737 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002738 return false;
2739 break;
2740 case eEncodingA1:
2741 Rn = Bits32(opcode, 19, 16);
2742 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002743 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002744 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002745 default:
2746 return false;
2747 }
2748 // Read the register value from register Rn.
2749 uint32_t val1 = ReadCoreReg(Rn, &success);
2750 if (!success)
2751 return false;
2752
2753 // Read the register value from register Rm.
2754 uint32_t val2 = ReadCoreReg(Rm, &success);
2755 if (!success)
2756 return false;
2757
Johnny Chena4438a72011-06-02 22:50:51 +00002758 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2759 if (!success)
2760 return false;
Johnny Chen078fbc62011-02-22 19:48:22 +00002761 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002762
2763 EmulateInstruction::Context context;
2764 context.type = EmulateInstruction::eContextImmediate;
2765 context.SetNoArgs();
2766 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2767 return false;
2768
2769 return true;
2770}
2771
2772// Compare (immediate) subtracts an immediate value from a register value.
2773// It updates the condition flags based on the result, and discards the result.
2774bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002775EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002776{
2777#if 0
2778 // ARM pseudo code...
2779 if ConditionPassed() then
2780 EncodingSpecificOperations();
2781 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2782 APSR.N = result<31>;
2783 APSR.Z = IsZeroBit(result);
2784 APSR.C = carry;
2785 APSR.V = overflow;
2786#endif
2787
2788 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002789
2790 uint32_t Rn; // the first operand
2791 uint32_t imm32; // the immediate value to be compared with
2792 switch (encoding) {
2793 case eEncodingT1:
2794 Rn = Bits32(opcode, 10, 8);
2795 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002796 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002797 case eEncodingT2:
2798 Rn = Bits32(opcode, 19, 16);
2799 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2800 if (Rn == 15)
2801 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002802 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002803 case eEncodingA1:
2804 Rn = Bits32(opcode, 19, 16);
2805 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002806 break;
2807 default:
2808 return false;
2809 }
2810 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002811 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002812 if (!success)
2813 return false;
2814
Johnny Chen10530c22011-02-17 22:37:12 +00002815 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2816
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002817 EmulateInstruction::Context context;
2818 context.type = EmulateInstruction::eContextImmediate;
2819 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002820 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2821 return false;
2822
Johnny Chend4dc4442011-02-11 02:02:56 +00002823 return true;
2824}
2825
Johnny Chen34075cb2011-02-22 01:56:31 +00002826// Compare (register) subtracts an optionally-shifted register value from a register value.
2827// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002828bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002829EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002830{
2831#if 0
2832 // ARM pseudo code...
2833 if ConditionPassed() then
2834 EncodingSpecificOperations();
2835 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2836 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2837 APSR.N = result<31>;
2838 APSR.Z = IsZeroBit(result);
2839 APSR.C = carry;
2840 APSR.V = overflow;
2841#endif
2842
2843 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002844
2845 uint32_t Rn; // the first operand
2846 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002847 ARM_ShifterType shift_t;
2848 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002849 switch (encoding) {
2850 case eEncodingT1:
2851 Rn = Bits32(opcode, 2, 0);
2852 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002853 shift_t = SRType_LSL;
2854 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002855 break;
2856 case eEncodingT2:
2857 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2858 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002859 shift_t = SRType_LSL;
2860 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002861 if (Rn < 8 && Rm < 8)
2862 return false;
2863 if (Rn == 15 || Rm == 15)
2864 return false;
2865 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002866 case eEncodingA1:
2867 Rn = Bits32(opcode, 19, 16);
2868 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002869 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002870 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002871 default:
2872 return false;
2873 }
2874 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002875 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002876 if (!success)
2877 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002878
Johnny Chene4a4d302011-02-11 21:53:58 +00002879 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002880 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002881 if (!success)
2882 return false;
2883
Johnny Chena4438a72011-06-02 22:50:51 +00002884 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2885 if (!success)
2886 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002887 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002888
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002889 EmulateInstruction::Context context;
2890 context.type = EmulateInstruction::eContextImmediate;
2891 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002892 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2893 return false;
2894
Johnny Chene4a4d302011-02-11 21:53:58 +00002895 return true;
2896}
2897
Johnny Chen82f16aa2011-02-15 20:10:55 +00002898// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2899// shifting in copies of its sign bit, and writes the result to the destination register. It can
2900// optionally update the condition flags based on the result.
2901bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002902EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002903{
2904#if 0
2905 // ARM pseudo code...
2906 if ConditionPassed() then
2907 EncodingSpecificOperations();
2908 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2909 if d == 15 then // Can only occur for ARM encoding
2910 ALUWritePC(result); // setflags is always FALSE here
2911 else
2912 R[d] = result;
2913 if setflags then
2914 APSR.N = result<31>;
2915 APSR.Z = IsZeroBit(result);
2916 APSR.C = carry;
2917 // APSR.V unchanged
2918#endif
2919
Greg Clayton7bc39082011-03-24 23:53:38 +00002920 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002921}
2922
2923// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2924// shifting in copies of its sign bit, and writes the result to the destination register.
2925// The variable number of bits is read from the bottom byte of a register. It can optionally update
2926// the condition flags based on the result.
2927bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002928EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002929{
2930#if 0
2931 // ARM pseudo code...
2932 if ConditionPassed() then
2933 EncodingSpecificOperations();
2934 shift_n = UInt(R[m]<7:0>);
2935 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2936 R[d] = result;
2937 if setflags then
2938 APSR.N = result<31>;
2939 APSR.Z = IsZeroBit(result);
2940 APSR.C = carry;
2941 // APSR.V unchanged
2942#endif
2943
Greg Clayton7bc39082011-03-24 23:53:38 +00002944 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002945}
2946
2947// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2948// shifting in zeros, and writes the result to the destination register. It can optionally
2949// update the condition flags based on the result.
2950bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002951EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002952{
2953#if 0
2954 // ARM pseudo code...
2955 if ConditionPassed() then
2956 EncodingSpecificOperations();
2957 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2958 if d == 15 then // Can only occur for ARM encoding
2959 ALUWritePC(result); // setflags is always FALSE here
2960 else
2961 R[d] = result;
2962 if setflags then
2963 APSR.N = result<31>;
2964 APSR.Z = IsZeroBit(result);
2965 APSR.C = carry;
2966 // APSR.V unchanged
2967#endif
2968
Greg Clayton7bc39082011-03-24 23:53:38 +00002969 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002970}
2971
2972// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2973// shifting in zeros, and writes the result to the destination register. The variable number
2974// of bits is read from the bottom byte of a register. It can optionally update the condition
2975// flags based on the result.
2976bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002977EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002978{
2979#if 0
2980 // ARM pseudo code...
2981 if ConditionPassed() then
2982 EncodingSpecificOperations();
2983 shift_n = UInt(R[m]<7:0>);
2984 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2985 R[d] = result;
2986 if setflags then
2987 APSR.N = result<31>;
2988 APSR.Z = IsZeroBit(result);
2989 APSR.C = carry;
2990 // APSR.V unchanged
2991#endif
2992
Greg Clayton7bc39082011-03-24 23:53:38 +00002993 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002994}
2995
2996// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2997// shifting in zeros, and writes the result to the destination register. It can optionally
2998// update the condition flags based on the result.
2999bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003000EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003001{
3002#if 0
3003 // ARM pseudo code...
3004 if ConditionPassed() then
3005 EncodingSpecificOperations();
3006 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3007 if d == 15 then // Can only occur for ARM encoding
3008 ALUWritePC(result); // setflags is always FALSE here
3009 else
3010 R[d] = result;
3011 if setflags then
3012 APSR.N = result<31>;
3013 APSR.Z = IsZeroBit(result);
3014 APSR.C = carry;
3015 // APSR.V unchanged
3016#endif
3017
Greg Clayton7bc39082011-03-24 23:53:38 +00003018 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003019}
3020
3021// Logical Shift Right (register) shifts a register value right by a variable number of bits,
3022// shifting in zeros, and writes the result to the destination register. The variable number
3023// of bits is read from the bottom byte of a register. It can optionally update the condition
3024// flags based on the result.
3025bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003026EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003027{
3028#if 0
3029 // ARM pseudo code...
3030 if ConditionPassed() then
3031 EncodingSpecificOperations();
3032 shift_n = UInt(R[m]<7:0>);
3033 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3034 R[d] = result;
3035 if setflags then
3036 APSR.N = result<31>;
3037 APSR.Z = IsZeroBit(result);
3038 APSR.C = carry;
3039 // APSR.V unchanged
3040#endif
3041
Greg Clayton7bc39082011-03-24 23:53:38 +00003042 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003043}
3044
Johnny Cheneeab4852011-02-16 22:14:44 +00003045// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3046// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3047// It can optionally update the condition flags based on the result.
3048bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003049EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003050{
3051#if 0
3052 // ARM pseudo code...
3053 if ConditionPassed() then
3054 EncodingSpecificOperations();
3055 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3056 if d == 15 then // Can only occur for ARM encoding
3057 ALUWritePC(result); // setflags is always FALSE here
3058 else
3059 R[d] = result;
3060 if setflags then
3061 APSR.N = result<31>;
3062 APSR.Z = IsZeroBit(result);
3063 APSR.C = carry;
3064 // APSR.V unchanged
3065#endif
3066
Greg Clayton7bc39082011-03-24 23:53:38 +00003067 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003068}
3069
3070// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3071// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3072// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3073// flags based on the result.
3074bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003075EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003076{
3077#if 0
3078 // ARM pseudo code...
3079 if ConditionPassed() then
3080 EncodingSpecificOperations();
3081 shift_n = UInt(R[m]<7:0>);
3082 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3083 R[d] = result;
3084 if setflags then
3085 APSR.N = result<31>;
3086 APSR.Z = IsZeroBit(result);
3087 APSR.C = carry;
3088 // APSR.V unchanged
3089#endif
3090
Greg Clayton7bc39082011-03-24 23:53:38 +00003091 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003092}
3093
3094// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3095// with the carry flag shifted into bit [31].
3096//
3097// RRX can optionally update the condition flags based on the result.
3098// In that case, bit [0] is shifted into the carry flag.
3099bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003100EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003101{
3102#if 0
3103 // ARM pseudo code...
3104 if ConditionPassed() then
3105 EncodingSpecificOperations();
3106 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3107 if d == 15 then // Can only occur for ARM encoding
3108 ALUWritePC(result); // setflags is always FALSE here
3109 else
3110 R[d] = result;
3111 if setflags then
3112 APSR.N = result<31>;
3113 APSR.Z = IsZeroBit(result);
3114 APSR.C = carry;
3115 // APSR.V unchanged
3116#endif
3117
Greg Clayton7bc39082011-03-24 23:53:38 +00003118 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003119}
3120
Johnny Chen41a0a152011-02-16 01:27:54 +00003121bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003122EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003123{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003124// assert(shift_type == SRType_ASR
3125// || shift_type == SRType_LSL
3126// || shift_type == SRType_LSR
3127// || shift_type == SRType_ROR
3128// || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003129
Johnny Chen82f16aa2011-02-15 20:10:55 +00003130 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003131
Greg Clayton7bc39082011-03-24 23:53:38 +00003132 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003133 {
Johnny Chene7f89532011-02-15 23:22:46 +00003134 uint32_t Rd; // the destination register
3135 uint32_t Rm; // the first operand register
3136 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003137 uint32_t carry; // the carry bit after the shift operation
3138 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003139
3140 // Special case handling!
3141 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003142 ARMEncoding use_encoding = encoding;
3143 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003144 {
3145 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3146 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003147 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003148 }
3149
Greg Clayton7bc39082011-03-24 23:53:38 +00003150 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003151 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003152 // Due to the above special case handling!
Greg Claytone1f47bb2011-06-02 22:23:35 +00003153 //assert(shift_type != SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003154
Johnny Chen82f16aa2011-02-15 20:10:55 +00003155 Rd = Bits32(opcode, 2, 0);
3156 Rm = Bits32(opcode, 5, 3);
3157 setflags = !InITBlock();
3158 imm5 = Bits32(opcode, 10, 6);
3159 break;
3160 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003161 // A8.6.141 RRX
Greg Claytone1f47bb2011-06-02 22:23:35 +00003162 //assert(shift_type != SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003163
Johnny Chen82f16aa2011-02-15 20:10:55 +00003164 Rd = Bits32(opcode, 11, 8);
3165 Rm = Bits32(opcode, 3, 0);
3166 setflags = BitIsSet(opcode, 20);
3167 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3168 if (BadReg(Rd) || BadReg(Rm))
3169 return false;
3170 break;
3171 case eEncodingA1:
3172 Rd = Bits32(opcode, 15, 12);
3173 Rm = Bits32(opcode, 3, 0);
3174 setflags = BitIsSet(opcode, 20);
3175 imm5 = Bits32(opcode, 11, 7);
3176 break;
3177 default:
3178 return false;
3179 }
3180
Johnny Cheneeab4852011-02-16 22:14:44 +00003181 // A8.6.139 ROR (immediate)
3182 if (shift_type == SRType_ROR && imm5 == 0)
3183 shift_type = SRType_RRX;
3184
Johnny Chen82f16aa2011-02-15 20:10:55 +00003185 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003186 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003187 if (!success)
3188 return false;
3189
Johnny Cheneeab4852011-02-16 22:14:44 +00003190 // Decode the shift amount if not RRX.
3191 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003192
Johnny Chena4438a72011-06-02 22:50:51 +00003193 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3194 if (!success)
3195 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003196
3197 // The context specifies that an immediate is to be moved into Rd.
3198 EmulateInstruction::Context context;
3199 context.type = EmulateInstruction::eContextImmediate;
3200 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003201
Johnny Chen10530c22011-02-17 22:37:12 +00003202 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003203 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003204 }
3205 return true;
3206}
3207
Johnny Chene7f89532011-02-15 23:22:46 +00003208bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003209EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003210{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003211 // assert(shift_type == SRType_ASR
3212 // || shift_type == SRType_LSL
3213 // || shift_type == SRType_LSR
3214 // || shift_type == SRType_ROR);
Johnny Chene7f89532011-02-15 23:22:46 +00003215
3216 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003217
Greg Clayton7bc39082011-03-24 23:53:38 +00003218 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003219 {
3220 uint32_t Rd; // the destination register
3221 uint32_t Rn; // the first operand register
3222 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3223 uint32_t carry; // the carry bit after the shift operation
3224 bool setflags;
3225 switch (encoding) {
3226 case eEncodingT1:
3227 Rd = Bits32(opcode, 2, 0);
3228 Rn = Rd;
3229 Rm = Bits32(opcode, 5, 3);
3230 setflags = !InITBlock();
3231 break;
3232 case eEncodingT2:
3233 Rd = Bits32(opcode, 11, 8);
3234 Rn = Bits32(opcode, 19, 16);
3235 Rm = Bits32(opcode, 3, 0);
3236 setflags = BitIsSet(opcode, 20);
3237 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3238 return false;
3239 break;
3240 case eEncodingA1:
3241 Rd = Bits32(opcode, 15, 12);
3242 Rn = Bits32(opcode, 3, 0);
3243 Rm = Bits32(opcode, 11, 8);
3244 setflags = BitIsSet(opcode, 20);
3245 if (Rd == 15 || Rn == 15 || Rm == 15)
3246 return false;
3247 break;
3248 default:
3249 return false;
3250 }
3251
3252 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003253 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003254 if (!success)
3255 return false;
3256 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003257 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003258 if (!success)
3259 return false;
3260
3261 // Get the shift amount.
3262 uint32_t amt = Bits32(val, 7, 0);
3263
Johnny Chena4438a72011-06-02 22:50:51 +00003264 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3265 if (!success)
3266 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003267
3268 // The context specifies that an immediate is to be moved into Rd.
3269 EmulateInstruction::Context context;
3270 context.type = EmulateInstruction::eContextImmediate;
3271 context.SetNoArgs ();
3272
Johnny Chen10530c22011-02-17 22:37:12 +00003273 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003274 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003275 }
3276 return true;
3277}
3278
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003279// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003280// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003281// can be written back to the base register.
3282bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003283EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003284{
3285#if 0
3286 // ARM pseudo code...
3287 if ConditionPassed()
3288 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3289 address = R[n];
3290
3291 for i = 0 to 14
3292 if registers<i> == '1' then
3293 R[i] = MemA[address, 4]; address = address + 4;
3294 if registers<15> == '1' then
3295 LoadWritePC (MemA[address, 4]);
3296
3297 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3298 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3299
3300#endif
3301
3302 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003303
Greg Clayton7bc39082011-03-24 23:53:38 +00003304 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003305 {
3306 uint32_t n;
3307 uint32_t registers = 0;
3308 bool wback;
3309 const uint32_t addr_byte_size = GetAddressByteSize();
3310 switch (encoding)
3311 {
3312 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003313 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003314 n = Bits32 (opcode, 10, 8);
3315 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003316 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003317 wback = BitIsClear (registers, n);
3318 // if BitCount(registers) < 1 then UNPREDICTABLE;
3319 if (BitCount(registers) < 1)
3320 return false;
3321 break;
3322 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003323 // if W == '1' && Rn == '1101' then SEE POP;
3324 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003325 n = Bits32 (opcode, 19, 16);
3326 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003327 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003328 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003329
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003330 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003331 if ((n == 15)
3332 || (BitCount (registers) < 2)
3333 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3334 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003335
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003336 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003337 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003338 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003339
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003340 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003341 if (wback
3342 && BitIsSet (registers, n))
3343 return false;
3344 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003345
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003346 case eEncodingA1:
3347 n = Bits32 (opcode, 19, 16);
3348 registers = Bits32 (opcode, 15, 0);
3349 wback = BitIsSet (opcode, 21);
3350 if ((n == 15)
3351 || (BitCount (registers) < 1))
3352 return false;
3353 break;
3354 default:
3355 return false;
3356 }
3357
3358 int32_t offset = 0;
3359 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3360 if (!success)
3361 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003362
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003363 EmulateInstruction::Context context;
3364 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003365 RegisterInfo dwarf_reg;
3366 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003367 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003368
3369 for (int i = 0; i < 14; ++i)
3370 {
3371 if (BitIsSet (registers, i))
3372 {
Caroline Tice85aab332011-02-08 23:56:10 +00003373 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003374 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003375 if (wback && (n == 13)) // Pop Instruction
3376 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3377
3378 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003379 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003380 if (!success)
3381 return false;
3382
3383 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3384 return false;
3385
3386 offset += addr_byte_size;
3387 }
3388 }
3389
3390 if (BitIsSet (registers, 15))
3391 {
3392 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003393 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003394 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003395 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003396 if (!success)
3397 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003398 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003399 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003400 return false;
3401 }
3402
3403 if (wback && BitIsClear (registers, n))
3404 {
Caroline Ticefa172202011-02-11 22:49:54 +00003405 // R[n] = R[n] + 4 * BitCount (registers)
3406 int32_t offset = addr_byte_size * BitCount (registers);
3407 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003408 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003409
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003410 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3411 return false;
3412 }
3413 if (wback && BitIsSet (registers, n))
3414 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003415 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003416 }
3417 return true;
3418}
Caroline Tice713c2662011-02-11 17:59:55 +00003419
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003420// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3421// The consecutive memory locations end at this address and the address just below the lowest of those locations
3422// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003423bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003424EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003425{
3426#if 0
3427 // ARM pseudo code...
3428 if ConditionPassed() then
3429 EncodingSpecificOperations();
3430 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003431
Caroline Tice713c2662011-02-11 17:59:55 +00003432 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003433 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003434 R[i] = MemA[address,4]; address = address + 4;
3435
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003436 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003437 LoadWritePC(MemA[address,4]);
3438
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003439 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3440 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003441#endif
3442
3443 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003444
Greg Clayton7bc39082011-03-24 23:53:38 +00003445 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003446 {
3447 uint32_t n;
3448 uint32_t registers = 0;
3449 bool wback;
3450 const uint32_t addr_byte_size = GetAddressByteSize();
3451
3452 // EncodingSpecificOperations();
3453 switch (encoding)
3454 {
3455 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003456 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003457 n = Bits32 (opcode, 19, 16);
3458 registers = Bits32 (opcode, 15, 0);
3459 wback = BitIsSet (opcode, 21);
3460
3461 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3462 if ((n == 15) || (BitCount (registers) < 1))
3463 return false;
3464
3465 break;
3466
3467 default:
3468 return false;
3469 }
3470 // address = R[n] - 4*BitCount(registers) + 4;
3471
3472 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003473 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003474
3475 if (!success)
3476 return false;
3477
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003478 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003479
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003480 EmulateInstruction::Context context;
3481 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003482 RegisterInfo dwarf_reg;
3483 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003484 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003485
3486 // for i = 0 to 14
3487 for (int i = 0; i < 14; ++i)
3488 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003489 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003490 if (BitIsSet (registers, i))
3491 {
3492 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003493 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003494 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003495 if (!success)
3496 return false;
3497 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3498 return false;
3499 offset += addr_byte_size;
3500 }
3501 }
3502
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003503 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003504 // LoadWritePC(MemA[address,4]);
3505 if (BitIsSet (registers, 15))
3506 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003507 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003508 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003509 if (!success)
3510 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003511 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003512 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003513 return false;
3514 }
3515
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003516 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003517 if (wback && BitIsClear (registers, n))
3518 {
Caroline Tice713c2662011-02-11 17:59:55 +00003519 if (!success)
3520 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003521
3522 offset = (addr_byte_size * BitCount (registers)) * -1;
3523 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003524 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003525 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003526 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3527 return false;
3528 }
3529
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003530 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003531 if (wback && BitIsSet (registers, n))
3532 return WriteBits32Unknown (n);
3533 }
3534 return true;
3535}
3536
3537// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3538// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3539// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003540bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003541EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003542{
3543#if 0
3544 // ARM pseudo code...
3545 if ConditionPassed() then
3546 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3547 address = R[n] - 4*BitCount(registers);
3548
3549 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003550 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003551 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003552 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003553 LoadWritePC(MemA[address,4]);
3554
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003555 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3556 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003557#endif
3558
3559 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003560
Greg Clayton7bc39082011-03-24 23:53:38 +00003561 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003562 {
3563 uint32_t n;
3564 uint32_t registers = 0;
3565 bool wback;
3566 const uint32_t addr_byte_size = GetAddressByteSize();
3567 switch (encoding)
3568 {
3569 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003570 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003571 n = Bits32 (opcode, 19, 16);
3572 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003573 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003574 wback = BitIsSet (opcode, 21);
3575
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003576 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003577 if ((n == 15)
3578 || (BitCount (registers) < 2)
3579 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3580 return false;
3581
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003582 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003583 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003584 return false;
3585
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003586 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003587 if (wback && BitIsSet (registers, n))
3588 return false;
3589
3590 break;
3591
3592 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003593 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003594 n = Bits32 (opcode, 19, 16);
3595 registers = Bits32 (opcode, 15, 0);
3596 wback = BitIsSet (opcode, 21);
3597
3598 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3599 if ((n == 15) || (BitCount (registers) < 1))
3600 return false;
3601
3602 break;
3603
3604 default:
3605 return false;
3606 }
3607
Caroline Tice713c2662011-02-11 17:59:55 +00003608 // address = R[n] - 4*BitCount(registers);
3609
Caroline Tice0b29e242011-02-08 23:16:02 +00003610 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003611 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003612
3613 if (!success)
3614 return false;
3615
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003616 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003617 EmulateInstruction::Context context;
3618 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003619 RegisterInfo dwarf_reg;
3620 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003621 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003622
3623 for (int i = 0; i < 14; ++i)
3624 {
3625 if (BitIsSet (registers, i))
3626 {
3627 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003628 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003629 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003630 if (!success)
3631 return false;
3632
3633 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3634 return false;
3635
3636 offset += addr_byte_size;
3637 }
3638 }
3639
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003640 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003641 // LoadWritePC(MemA[address,4]);
3642 if (BitIsSet (registers, 15))
3643 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003644 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003645 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003646 if (!success)
3647 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003648 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003649 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003650 return false;
3651 }
3652
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003653 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003654 if (wback && BitIsClear (registers, n))
3655 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003656 if (!success)
3657 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003658
3659 offset = (addr_byte_size * BitCount (registers)) * -1;
3660 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003661 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003662 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003663 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3664 return false;
3665 }
3666
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003667 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003668 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003669 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003670 }
3671 return true;
3672}
Caroline Tice85aab332011-02-08 23:56:10 +00003673
Caroline Tice713c2662011-02-11 17:59:55 +00003674// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3675// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3676// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003677bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003678EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003679{
3680#if 0
3681 if ConditionPassed() then
3682 EncodingSpecificOperations();
3683 address = R[n] + 4;
3684
3685 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003686 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003687 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003688 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003689 LoadWritePC(MemA[address,4]);
3690
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003691 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3692 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003693#endif
3694
3695 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003696
Greg Clayton7bc39082011-03-24 23:53:38 +00003697 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003698 {
3699 uint32_t n;
3700 uint32_t registers = 0;
3701 bool wback;
3702 const uint32_t addr_byte_size = GetAddressByteSize();
3703 switch (encoding)
3704 {
3705 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003706 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003707 n = Bits32 (opcode, 19, 16);
3708 registers = Bits32 (opcode, 15, 0);
3709 wback = BitIsSet (opcode, 21);
3710
3711 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3712 if ((n == 15) || (BitCount (registers) < 1))
3713 return false;
3714
3715 break;
3716 default:
3717 return false;
3718 }
3719 // address = R[n] + 4;
3720
3721 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003722 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003723
3724 if (!success)
3725 return false;
3726
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003727 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003728
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003729 EmulateInstruction::Context context;
3730 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003731 RegisterInfo dwarf_reg;
3732 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003733 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003734
3735 for (int i = 0; i < 14; ++i)
3736 {
3737 if (BitIsSet (registers, i))
3738 {
3739 // R[i] = MemA[address,4]; address = address + 4;
3740
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003741 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003742 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003743 if (!success)
3744 return false;
3745
3746 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3747 return false;
3748
3749 offset += addr_byte_size;
3750 }
3751 }
3752
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003753 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003754 // LoadWritePC(MemA[address,4]);
3755 if (BitIsSet (registers, 15))
3756 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003757 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003758 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003759 if (!success)
3760 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003761 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003762 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003763 return false;
3764 }
3765
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003766 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003767 if (wback && BitIsClear (registers, n))
3768 {
Caroline Tice85aab332011-02-08 23:56:10 +00003769 if (!success)
3770 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003771
3772 offset = addr_byte_size * BitCount (registers);
3773 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003774 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003775 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003776 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3777 return false;
3778 }
3779
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003780 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003781 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003782 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003783 }
3784 return true;
3785}
Caroline Tice0b29e242011-02-08 23:16:02 +00003786
Johnny Chenef21b592011-02-10 01:52:38 +00003787// Load Register (immediate) calculates an address from a base register value and
3788// an immediate offset, loads a word from memory, and writes to a register.
3789// LDR (immediate, Thumb)
3790bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003791EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003792{
3793#if 0
3794 // ARM pseudo code...
3795 if (ConditionPassed())
3796 {
3797 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3798 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3799 address = if index then offset_addr else R[n];
3800 data = MemU[address,4];
3801 if wback then R[n] = offset_addr;
3802 if t == 15 then
3803 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3804 elsif UnalignedSupport() || address<1:0> = '00' then
3805 R[t] = data;
3806 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3807 }
3808#endif
3809
3810 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003811
Greg Clayton7bc39082011-03-24 23:53:38 +00003812 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003813 {
3814 uint32_t Rt; // the destination register
3815 uint32_t Rn; // the base register
3816 uint32_t imm32; // the immediate offset used to form the address
3817 addr_t offset_addr; // the offset address
3818 addr_t address; // the calculated address
3819 uint32_t data; // the literal data value from memory load
3820 bool add, index, wback;
3821 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003822 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003823 Rt = Bits32(opcode, 2, 0);
3824 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003825 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3826 // index = TRUE; add = TRUE; wback = FALSE
3827 add = true;
3828 index = true;
3829 wback = false;
3830
3831 break;
3832
3833 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003834 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003835 Rt = Bits32 (opcode, 10, 8);
3836 Rn = 13;
3837 imm32 = Bits32 (opcode, 7, 0) << 2;
3838
3839 // index = TRUE; add = TRUE; wback = FALSE;
3840 index = true;
3841 add = true;
3842 wback = false;
3843
3844 break;
3845
3846 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003847 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003848 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3849 Rt = Bits32 (opcode, 15, 12);
3850 Rn = Bits32 (opcode, 19, 16);
3851 imm32 = Bits32 (opcode, 11, 0);
3852
3853 // index = TRUE; add = TRUE; wback = FALSE;
3854 index = true;
3855 add = true;
3856 wback = false;
3857
3858 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3859 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3860 return false;
3861
3862 break;
3863
3864 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003865 // if Rn == '1111' then SEE LDR (literal);
3866 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3867 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3868 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003869 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3870 return false;
3871
3872 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3873 Rt = Bits32 (opcode, 15, 12);
3874 Rn = Bits32 (opcode, 19, 16);
3875 imm32 = Bits32 (opcode, 7, 0);
3876
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003877 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003878 index = BitIsSet (opcode, 10);
3879 add = BitIsSet (opcode, 9);
3880 wback = BitIsSet (opcode, 8);
3881
3882 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3883 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3884 return false;
3885
3886 break;
3887
3888 default:
3889 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003890 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003891 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003892 if (!success)
3893 return false;
3894 if (add)
3895 offset_addr = base + imm32;
3896 else
3897 offset_addr = base - imm32;
3898
3899 address = (index ? offset_addr : base);
3900
Greg Claytonc07d4512011-04-26 23:48:45 +00003901 RegisterInfo base_reg;
3902 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
Johnny Chenef21b592011-02-10 01:52:38 +00003903 if (wback)
3904 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003905 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003906 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3907 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003908
Johnny Chenef21b592011-02-10 01:52:38 +00003909 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3910 return false;
3911 }
3912
3913 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003914 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003915 context.type = EmulateInstruction::eContextRegisterLoad;
3916 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003917
3918 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003919 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003920 if (!success)
3921 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003922
3923 if (Rt == 15)
3924 {
3925 if (Bits32(address, 1, 0) == 0)
3926 {
Johnny Chen668b4512011-02-15 21:08:58 +00003927 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003928 return false;
3929 }
3930 else
3931 return false;
3932 }
3933 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3934 {
3935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3936 return false;
3937 }
3938 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003939 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003940 }
3941 return true;
3942}
3943
Caroline Ticeaf556562011-02-15 18:42:15 +00003944// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3945// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3946// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003947bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003948EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003949{
3950#if 0
3951 if ConditionPassed() then
3952 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3953 address = R[n];
3954
3955 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003956 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003957 if i == n && wback && i != LowestSetBit(registers) then
3958 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3959 else
3960 MemA[address,4] = R[i];
3961 address = address + 4;
3962
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003963 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003964 MemA[address,4] = PCStoreValue();
3965 if wback then R[n] = R[n] + 4*BitCount(registers);
3966#endif
3967
3968 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003969
Greg Clayton7bc39082011-03-24 23:53:38 +00003970 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003971 {
3972 uint32_t n;
3973 uint32_t registers = 0;
3974 bool wback;
3975 const uint32_t addr_byte_size = GetAddressByteSize();
3976
3977 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3978 switch (encoding)
3979 {
3980 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003981 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003982 n = Bits32 (opcode, 10, 8);
3983 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003984 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003985 wback = true;
3986
3987 // if BitCount(registers) < 1 then UNPREDICTABLE;
3988 if (BitCount (registers) < 1)
3989 return false;
3990
3991 break;
3992
3993 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003994 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003995 n = Bits32 (opcode, 19, 16);
3996 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003997 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003998 wback = BitIsSet (opcode, 21);
3999
4000 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4001 if ((n == 15) || (BitCount (registers) < 2))
4002 return false;
4003
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004004 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00004005 if (wback && BitIsSet (registers, n))
4006 return false;
4007
4008 break;
4009
4010 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004011 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00004012 n = Bits32 (opcode, 19, 16);
4013 registers = Bits32 (opcode, 15, 0);
4014 wback = BitIsSet (opcode, 21);
4015
4016 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4017 if ((n == 15) || (BitCount (registers) < 1))
4018 return false;
4019
4020 break;
4021
4022 default:
4023 return false;
4024 }
4025
4026 // address = R[n];
4027 int32_t offset = 0;
4028 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4029 if (!success)
4030 return false;
4031
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004032 EmulateInstruction::Context context;
4033 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004034 RegisterInfo base_reg;
4035 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefa172202011-02-11 22:49:54 +00004036
4037 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004038 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00004039 for (int i = 0; i < 14; ++i)
4040 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004041 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00004042 if (BitIsSet (registers, i))
4043 {
4044 if (i < lowest_set_bit)
4045 lowest_set_bit = i;
4046 // if i == n && wback && i != LowestSetBit(registers) then
4047 if ((i == n) && wback && (i != lowest_set_bit))
4048 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4049 WriteBits32UnknownToMemory (address + offset);
4050 else
4051 {
4052 // MemA[address,4] = R[i];
4053 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4054 if (!success)
4055 return false;
4056
Greg Claytonc07d4512011-04-26 23:48:45 +00004057 RegisterInfo data_reg;
4058 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004059 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004060 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004061 return false;
4062 }
4063
4064 // address = address + 4;
4065 offset += addr_byte_size;
4066 }
4067 }
4068
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004069 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004070 // MemA[address,4] = PCStoreValue();
4071 if (BitIsSet (registers, 15))
4072 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004073 RegisterInfo pc_reg;
4074 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004075 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004076 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004077 if (!success)
4078 return false;
4079
Caroline Tice8d681f52011-03-17 23:50:16 +00004080 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004081 return false;
4082 }
4083
4084 // if wback then R[n] = R[n] + 4*BitCount(registers);
4085 if (wback)
4086 {
4087 offset = addr_byte_size * BitCount (registers);
4088 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004089 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004090 addr_t data = address + offset;
4091 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4092 return false;
4093 }
4094 }
4095 return true;
4096}
4097
Caroline Ticeaf556562011-02-15 18:42:15 +00004098// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4099// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4100// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004101bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004102EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004103{
4104#if 0
4105 if ConditionPassed() then
4106 EncodingSpecificOperations();
4107 address = R[n] - 4*BitCount(registers) + 4;
4108
4109 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004110 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004111 if i == n && wback && i != LowestSetBit(registers) then
4112 MemA[address,4] = bits(32) UNKNOWN;
4113 else
4114 MemA[address,4] = R[i];
4115 address = address + 4;
4116
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004117 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004118 MemA[address,4] = PCStoreValue();
4119
4120 if wback then R[n] = R[n] - 4*BitCount(registers);
4121#endif
4122
4123 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004124
Greg Clayton7bc39082011-03-24 23:53:38 +00004125 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004126 {
4127 uint32_t n;
4128 uint32_t registers = 0;
4129 bool wback;
4130 const uint32_t addr_byte_size = GetAddressByteSize();
4131
4132 // EncodingSpecificOperations();
4133 switch (encoding)
4134 {
4135 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004136 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004137 n = Bits32 (opcode, 19, 16);
4138 registers = Bits32 (opcode, 15, 0);
4139 wback = BitIsSet (opcode, 21);
4140
4141 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4142 if ((n == 15) || (BitCount (registers) < 1))
4143 return false;
4144 break;
4145 default:
4146 return false;
4147 }
4148
4149 // address = R[n] - 4*BitCount(registers) + 4;
4150 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004151 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004152 if (!success)
4153 return false;
4154
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004155 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004156
4157 EmulateInstruction::Context context;
4158 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004159 RegisterInfo base_reg;
4160 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004161
4162 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004163 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004164 for (int i = 0; i < 14; ++i)
4165 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004166 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004167 if (BitIsSet (registers, i))
4168 {
4169 if (i < lowest_bit_set)
4170 lowest_bit_set = i;
4171 //if i == n && wback && i != LowestSetBit(registers) then
4172 if ((i == n) && wback && (i != lowest_bit_set))
4173 // MemA[address,4] = bits(32) UNKNOWN;
4174 WriteBits32UnknownToMemory (address + offset);
4175 else
4176 {
4177 // MemA[address,4] = R[i];
4178 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4179 if (!success)
4180 return false;
4181
Greg Claytonc07d4512011-04-26 23:48:45 +00004182 RegisterInfo data_reg;
4183 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004184 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004185 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004186 return false;
4187 }
4188
4189 // address = address + 4;
4190 offset += addr_byte_size;
4191 }
4192 }
4193
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004194 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004195 // MemA[address,4] = PCStoreValue();
4196 if (BitIsSet (registers, 15))
4197 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004198 RegisterInfo pc_reg;
4199 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004200 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004201 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004202 if (!success)
4203 return false;
4204
Caroline Tice8d681f52011-03-17 23:50:16 +00004205 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004206 return false;
4207 }
4208
4209 // if wback then R[n] = R[n] - 4*BitCount(registers);
4210 if (wback)
4211 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004212 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004213 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4214 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004215 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004216 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4217 return false;
4218 }
4219 }
4220 return true;
4221}
4222
Caroline Ticeaf556562011-02-15 18:42:15 +00004223// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4224// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4225// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004226bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004227EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004228{
4229#if 0
4230 if ConditionPassed() then
4231 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4232 address = R[n] - 4*BitCount(registers);
4233
4234 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004235 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004236 if i == n && wback && i != LowestSetBit(registers) then
4237 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4238 else
4239 MemA[address,4] = R[i];
4240 address = address + 4;
4241
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004242 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004243 MemA[address,4] = PCStoreValue();
4244
4245 if wback then R[n] = R[n] - 4*BitCount(registers);
4246#endif
4247
4248
4249 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004250
Greg Clayton7bc39082011-03-24 23:53:38 +00004251 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004252 {
4253 uint32_t n;
4254 uint32_t registers = 0;
4255 bool wback;
4256 const uint32_t addr_byte_size = GetAddressByteSize();
4257
4258 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4259 switch (encoding)
4260 {
4261 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004262 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004263 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4264 {
4265 // See PUSH
4266 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004267 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004268 n = Bits32 (opcode, 19, 16);
4269 registers = Bits32 (opcode, 15, 0);
4270 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4271 wback = BitIsSet (opcode, 21);
4272 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4273 if ((n == 15) || BitCount (registers) < 2)
4274 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004275 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004276 if (wback && BitIsSet (registers, n))
4277 return false;
4278 break;
4279
4280 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00004281 // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004282 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4283 {
4284 // See Push
4285 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004286 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004287 n = Bits32 (opcode, 19, 16);
4288 registers = Bits32 (opcode, 15, 0);
4289 wback = BitIsSet (opcode, 21);
4290 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4291 if ((n == 15) || BitCount (registers) < 1)
4292 return false;
4293 break;
4294
4295 default:
4296 return false;
4297 }
4298
4299 // address = R[n] - 4*BitCount(registers);
4300
4301 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004302 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004303 if (!success)
4304 return false;
4305
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004306 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004307
4308 EmulateInstruction::Context context;
4309 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004310 RegisterInfo base_reg;
4311 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004312
4313 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004314 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004315 for (int i = 0; i < 14; ++i)
4316 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004317 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004318 if (BitIsSet (registers, i))
4319 {
4320 if (i < lowest_set_bit)
4321 lowest_set_bit = i;
4322 // if i == n && wback && i != LowestSetBit(registers) then
4323 if ((i == n) && wback && (i != lowest_set_bit))
4324 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4325 WriteBits32UnknownToMemory (address + offset);
4326 else
4327 {
4328 // MemA[address,4] = R[i];
4329 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4330 if (!success)
4331 return false;
4332
Greg Claytonc07d4512011-04-26 23:48:45 +00004333 RegisterInfo data_reg;
4334 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004335 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004336 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004337 return false;
4338 }
4339
4340 // address = address + 4;
4341 offset += addr_byte_size;
4342 }
4343 }
4344
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004345 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004346 // MemA[address,4] = PCStoreValue();
4347 if (BitIsSet (registers, 15))
4348 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004349 RegisterInfo pc_reg;
4350 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004351 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004352 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004353 if (!success)
4354 return false;
4355
Caroline Tice8d681f52011-03-17 23:50:16 +00004356 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004357 return false;
4358 }
4359
4360 // if wback then R[n] = R[n] - 4*BitCount(registers);
4361 if (wback)
4362 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004363 offset = (addr_byte_size * BitCount (registers)) * -1;
4364 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4365 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004366 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004367 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4368 return false;
4369 }
4370 }
4371 return true;
4372}
4373
4374// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4375// from a base register. The consecutive memory locations start just above this address, and the address of the last
4376// of those locations can optionally be written back to the base register.
4377bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004378EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004379{
4380#if 0
4381 if ConditionPassed() then
4382 EncodingSpecificOperations();
4383 address = R[n] + 4;
4384
4385 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004386 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004387 if i == n && wback && i != LowestSetBit(registers) then
4388 MemA[address,4] = bits(32) UNKNOWN;
4389 else
4390 MemA[address,4] = R[i];
4391 address = address + 4;
4392
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004393 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004394 MemA[address,4] = PCStoreValue();
4395
4396 if wback then R[n] = R[n] + 4*BitCount(registers);
4397#endif
4398
4399 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004400
Greg Clayton7bc39082011-03-24 23:53:38 +00004401 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004402 {
4403 uint32_t n;
4404 uint32_t registers = 0;
4405 bool wback;
4406 const uint32_t addr_byte_size = GetAddressByteSize();
4407
4408 // EncodingSpecificOperations();
4409 switch (encoding)
4410 {
4411 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004412 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004413 n = Bits32 (opcode, 19, 16);
4414 registers = Bits32 (opcode, 15, 0);
4415 wback = BitIsSet (opcode, 21);
4416
4417 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4418 if ((n == 15) && (BitCount (registers) < 1))
4419 return false;
4420 break;
4421 default:
4422 return false;
4423 }
4424 // address = R[n] + 4;
4425
4426 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004427 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004428 if (!success)
4429 return false;
4430
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004431 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004432
4433 EmulateInstruction::Context context;
4434 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004435 RegisterInfo base_reg;
4436 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004437
4438 uint32_t lowest_set_bit = 14;
4439 // for i = 0 to 14
4440 for (int i = 0; i < 14; ++i)
4441 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004442 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004443 if (BitIsSet (registers, i))
4444 {
4445 if (i < lowest_set_bit)
4446 lowest_set_bit = i;
4447 // if i == n && wback && i != LowestSetBit(registers) then
4448 if ((i == n) && wback && (i != lowest_set_bit))
4449 // MemA[address,4] = bits(32) UNKNOWN;
4450 WriteBits32UnknownToMemory (address + offset);
4451 // else
4452 else
4453 {
4454 // MemA[address,4] = R[i];
4455 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4456 if (!success)
4457 return false;
4458
Greg Claytonc07d4512011-04-26 23:48:45 +00004459 RegisterInfo data_reg;
4460 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004461 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004462 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004463 return false;
4464 }
4465
4466 // address = address + 4;
4467 offset += addr_byte_size;
4468 }
4469 }
4470
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004471 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004472 // MemA[address,4] = PCStoreValue();
4473 if (BitIsSet (registers, 15))
4474 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004475 RegisterInfo pc_reg;
4476 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004477 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004478 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004479 if (!success)
4480 return false;
4481
Caroline Tice8d681f52011-03-17 23:50:16 +00004482 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004483 return false;
4484 }
4485
4486 // if wback then R[n] = R[n] + 4*BitCount(registers);
4487 if (wback)
4488 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004489 offset = addr_byte_size * BitCount (registers);
4490 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4491 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004492 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004493 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4494 return false;
4495 }
4496 }
4497 return true;
4498}
Caroline Tice7fac8572011-02-15 22:53:54 +00004499
4500// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4501// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4502bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004503EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004504{
4505#if 0
4506 if ConditionPassed() then
4507 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4508 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4509 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004510 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004511 MemU[address,4] = R[t];
4512 else // Can only occur before ARMv7
4513 MemU[address,4] = bits(32) UNKNOWN;
4514 if wback then R[n] = offset_addr;
4515#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004516
Caroline Tice7fac8572011-02-15 22:53:54 +00004517 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004518
Greg Clayton7bc39082011-03-24 23:53:38 +00004519 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004520 {
4521 const uint32_t addr_byte_size = GetAddressByteSize();
4522
4523 uint32_t t;
4524 uint32_t n;
4525 uint32_t imm32;
4526 bool index;
4527 bool add;
4528 bool wback;
4529 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4530 switch (encoding)
4531 {
4532 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004533 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004534 t = Bits32 (opcode, 2, 0);
4535 n = Bits32 (opcode, 5, 3);
4536 imm32 = Bits32 (opcode, 10, 6) << 2;
4537
4538 // index = TRUE; add = TRUE; wback = FALSE;
4539 index = true;
4540 add = false;
4541 wback = false;
4542 break;
4543
4544 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004545 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004546 t = Bits32 (opcode, 10, 8);
4547 n = 13;
4548 imm32 = Bits32 (opcode, 7, 0) << 2;
4549
4550 // index = TRUE; add = TRUE; wback = FALSE;
4551 index = true;
4552 add = true;
4553 wback = false;
4554 break;
4555
4556 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004557 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004558 if (Bits32 (opcode, 19, 16) == 15)
4559 return false;
4560
4561 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4562 t = Bits32 (opcode, 15, 12);
4563 n = Bits32 (opcode, 19, 16);
4564 imm32 = Bits32 (opcode, 11, 0);
4565
4566 // index = TRUE; add = TRUE; wback = FALSE;
4567 index = true;
4568 add = true;
4569 wback = false;
4570
4571 // if t == 15 then UNPREDICTABLE;
4572 if (t == 15)
4573 return false;
4574 break;
4575
4576 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004577 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4578 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4579 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004580 if ((Bits32 (opcode, 19, 16) == 15)
4581 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4582 return false;
4583
4584 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4585 t = Bits32 (opcode, 15, 12);
4586 n = Bits32 (opcode, 19, 16);
4587 imm32 = Bits32 (opcode, 7, 0);
4588
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004589 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004590 index = BitIsSet (opcode, 10);
4591 add = BitIsSet (opcode, 9);
4592 wback = BitIsSet (opcode, 8);
4593
4594 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4595 if ((t == 15) || (wback && (n == t)))
4596 return false;
4597 break;
4598
4599 default:
4600 return false;
4601 }
4602
4603 addr_t offset_addr;
4604 addr_t address;
4605
4606 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004607 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004608 if (!success)
4609 return false;
4610
4611 if (add)
4612 offset_addr = base_address + imm32;
4613 else
4614 offset_addr = base_address - imm32;
4615
4616 // address = if index then offset_addr else R[n];
4617 if (index)
4618 address = offset_addr;
4619 else
4620 address = base_address;
4621
4622 EmulateInstruction::Context context;
4623 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004624 RegisterInfo base_reg;
4625 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004626
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004627 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004628 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4629 {
4630 // MemU[address,4] = R[t];
4631 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4632 if (!success)
4633 return false;
4634
Greg Claytonc07d4512011-04-26 23:48:45 +00004635 RegisterInfo data_reg;
4636 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004637 int32_t offset = address - base_address;
4638 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004639 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004640 return false;
4641 }
4642 else
4643 {
4644 // MemU[address,4] = bits(32) UNKNOWN;
4645 WriteBits32UnknownToMemory (address);
4646 }
4647
4648 // if wback then R[n] = offset_addr;
4649 if (wback)
4650 {
4651 context.type = eContextRegisterLoad;
4652 context.SetAddress (offset_addr);
4653 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4654 return false;
4655 }
4656 }
4657 return true;
4658}
Caroline Ticeaf556562011-02-15 18:42:15 +00004659
Caroline Tice3fd63e92011-02-16 00:33:43 +00004660// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4661// word from a register to memory. The offset register value can optionally be shifted.
4662bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004663EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004664{
4665#if 0
4666 if ConditionPassed() then
4667 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4668 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4669 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4670 address = if index then offset_addr else R[n];
4671 if t == 15 then // Only possible for encoding A1
4672 data = PCStoreValue();
4673 else
4674 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004675 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004676 MemU[address,4] = data;
4677 else // Can only occur before ARMv7
4678 MemU[address,4] = bits(32) UNKNOWN;
4679 if wback then R[n] = offset_addr;
4680#endif
4681
4682 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004683
Greg Clayton7bc39082011-03-24 23:53:38 +00004684 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004685 {
4686 const uint32_t addr_byte_size = GetAddressByteSize();
4687
4688 uint32_t t;
4689 uint32_t n;
4690 uint32_t m;
4691 ARM_ShifterType shift_t;
4692 uint32_t shift_n;
4693 bool index;
4694 bool add;
4695 bool wback;
4696
4697 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4698 switch (encoding)
4699 {
4700 case eEncodingT1:
4701 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4702 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4703 t = Bits32 (opcode, 2, 0);
4704 n = Bits32 (opcode, 5, 3);
4705 m = Bits32 (opcode, 8, 6);
4706
4707 // index = TRUE; add = TRUE; wback = FALSE;
4708 index = true;
4709 add = true;
4710 wback = false;
4711
4712 // (shift_t, shift_n) = (SRType_LSL, 0);
4713 shift_t = SRType_LSL;
4714 shift_n = 0;
4715 break;
4716
4717 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004718 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004719 if (Bits32 (opcode, 19, 16) == 15)
4720 return false;
4721
4722 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4723 t = Bits32 (opcode, 15, 12);
4724 n = Bits32 (opcode, 19, 16);
4725 m = Bits32 (opcode, 3, 0);
4726
4727 // index = TRUE; add = TRUE; wback = FALSE;
4728 index = true;
4729 add = true;
4730 wback = false;
4731
4732 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4733 shift_t = SRType_LSL;
4734 shift_n = Bits32 (opcode, 5, 4);
4735
4736 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4737 if ((t == 15) || (BadReg (m)))
4738 return false;
4739 break;
4740
4741 case eEncodingA1:
4742 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004743 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004744 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4745 t = Bits32 (opcode, 15, 12);
4746 n = Bits32 (opcode, 19, 16);
4747 m = Bits32 (opcode, 3, 0);
4748
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004749 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004750 index = BitIsSet (opcode, 24);
4751 add = BitIsSet (opcode, 23);
4752 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4753
4754 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4755 uint32_t typ = Bits32 (opcode, 6, 5);
4756 uint32_t imm5 = Bits32 (opcode, 11, 7);
4757 shift_n = DecodeImmShift(typ, imm5, shift_t);
4758
4759 // if m == 15 then UNPREDICTABLE;
4760 if (m == 15)
4761 return false;
4762
4763 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4764 if (wback && ((n == 15) || (n == t)))
4765 return false;
4766
4767 break;
4768 }
4769 default:
4770 return false;
4771 }
4772
4773 addr_t offset_addr;
4774 addr_t address;
4775 int32_t offset = 0;
4776
4777 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4778 if (!success)
4779 return false;
4780
4781 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4782 if (!success)
4783 return false;
4784
4785 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00004786 offset = Shift (Rm_data, shift_t, shift_n, APSR_C, &success);
4787 if (!success)
4788 return false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004789
4790 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4791 if (add)
4792 offset_addr = base_address + offset;
4793 else
4794 offset_addr = base_address - offset;
4795
4796 // address = if index then offset_addr else R[n];
4797 if (index)
4798 address = offset_addr;
4799 else
4800 address = base_address;
4801
4802 uint32_t data;
4803 // if t == 15 then // Only possible for encoding A1
4804 if (t == 15)
4805 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004806 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004807 else
4808 // data = R[t];
4809 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4810
4811 if (!success)
4812 return false;
4813
4814 EmulateInstruction::Context context;
4815 context.type = eContextRegisterStore;
4816
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004817 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004818 if (UnalignedSupport ()
4819 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4820 || CurrentInstrSet() == eModeARM)
4821 {
4822 // MemU[address,4] = data;
4823
Greg Claytonc07d4512011-04-26 23:48:45 +00004824 RegisterInfo base_reg;
4825 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004826
Greg Claytonc07d4512011-04-26 23:48:45 +00004827 RegisterInfo data_reg;
4828 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004829
4830 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004831 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004832 return false;
4833
4834 }
4835 else
4836 // MemU[address,4] = bits(32) UNKNOWN;
4837 WriteBits32UnknownToMemory (address);
4838
4839 // if wback then R[n] = offset_addr;
4840 if (wback)
4841 {
4842 context.type = eContextRegisterLoad;
4843 context.SetAddress (offset_addr);
4844 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4845 return false;
4846 }
4847
4848 }
4849 return true;
4850}
Caroline Tice73a29de2011-02-16 20:22:22 +00004851
4852bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004853EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004854{
4855#if 0
4856 if ConditionPassed() then
4857 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4858 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4859 address = if index then offset_addr else R[n];
4860 MemU[address,1] = R[t]<7:0>;
4861 if wback then R[n] = offset_addr;
4862#endif
4863
4864
4865 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004866
Greg Clayton7bc39082011-03-24 23:53:38 +00004867 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004868 {
4869 uint32_t t;
4870 uint32_t n;
4871 uint32_t imm32;
4872 bool index;
4873 bool add;
4874 bool wback;
4875 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4876 switch (encoding)
4877 {
4878 case eEncodingT1:
4879 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4880 t = Bits32 (opcode, 2, 0);
4881 n = Bits32 (opcode, 5, 3);
4882 imm32 = Bits32 (opcode, 10, 6);
4883
4884 // index = TRUE; add = TRUE; wback = FALSE;
4885 index = true;
4886 add = true;
4887 wback = false;
4888 break;
4889
4890 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004891 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004892 if (Bits32 (opcode, 19, 16) == 15)
4893 return false;
4894
4895 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4896 t = Bits32 (opcode, 15, 12);
4897 n = Bits32 (opcode, 19, 16);
4898 imm32 = Bits32 (opcode, 11, 0);
4899
4900 // index = TRUE; add = TRUE; wback = FALSE;
4901 index = true;
4902 add = true;
4903 wback = false;
4904
4905 // if BadReg(t) then UNPREDICTABLE;
4906 if (BadReg (t))
4907 return false;
4908 break;
4909
4910 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004911 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4912 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004913 if (Bits32 (opcode, 19, 16) == 15)
4914 return false;
4915
4916 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4917 t = Bits32 (opcode, 15, 12);
4918 n = Bits32 (opcode, 19, 16);
4919 imm32 = Bits32 (opcode, 7, 0);
4920
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004921 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004922 index = BitIsSet (opcode, 10);
4923 add = BitIsSet (opcode, 9);
4924 wback = BitIsSet (opcode, 8);
4925
4926 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4927 if ((BadReg (t)) || (wback && (n == t)))
4928 return false;
4929 break;
4930
4931 default:
4932 return false;
4933 }
4934
4935 addr_t offset_addr;
4936 addr_t address;
4937 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4938 if (!success)
4939 return false;
4940
4941 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4942 if (add)
4943 offset_addr = base_address + imm32;
4944 else
4945 offset_addr = base_address - imm32;
4946
4947 // address = if index then offset_addr else R[n];
4948 if (index)
4949 address = offset_addr;
4950 else
4951 address = base_address;
4952
Caroline Ticecc96eb52011-02-17 19:20:40 +00004953 // MemU[address,1] = R[t]<7:0>
Greg Claytonc07d4512011-04-26 23:48:45 +00004954 RegisterInfo base_reg;
4955 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004956
Greg Claytonc07d4512011-04-26 23:48:45 +00004957 RegisterInfo data_reg;
4958 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004959
4960 EmulateInstruction::Context context;
4961 context.type = eContextRegisterStore;
4962 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4963
4964 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4965 if (!success)
4966 return false;
4967
4968 data = Bits32 (data, 7, 0);
4969
Caroline Ticecc96eb52011-02-17 19:20:40 +00004970 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004971 return false;
4972
4973 // if wback then R[n] = offset_addr;
4974 if (wback)
4975 {
4976 context.type = eContextRegisterLoad;
4977 context.SetAddress (offset_addr);
4978 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4979 return false;
4980 }
4981
4982 }
4983
4984 return true;
4985}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004986
4987// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4988// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4989bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004990EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004991{
4992#if 0
4993 if ConditionPassed() then
4994 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4995 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4996 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4997 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004998 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004999 MemU[address,2] = R[t]<15:0>;
5000 else // Can only occur before ARMv7
5001 MemU[address,2] = bits(16) UNKNOWN;
5002 if wback then R[n] = offset_addr;
5003#endif
5004
5005 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005006
Greg Clayton7bc39082011-03-24 23:53:38 +00005007 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00005008 {
5009 uint32_t t;
5010 uint32_t n;
5011 uint32_t m;
5012 bool index;
5013 bool add;
5014 bool wback;
5015 ARM_ShifterType shift_t;
5016 uint32_t shift_n;
5017
5018 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5019 switch (encoding)
5020 {
5021 case eEncodingT1:
5022 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5023 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5024 t = Bits32 (opcode, 2, 0);
5025 n = Bits32 (opcode, 5, 3);
5026 m = Bits32 (opcode, 8, 6);
5027
5028 // index = TRUE; add = TRUE; wback = FALSE;
5029 index = true;
5030 add = true;
5031 wback = false;
5032
5033 // (shift_t, shift_n) = (SRType_LSL, 0);
5034 shift_t = SRType_LSL;
5035 shift_n = 0;
5036
5037 break;
5038
5039 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005040 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005041 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5042 t = Bits32 (opcode, 15, 12);
5043 n = Bits32 (opcode, 19, 16);
5044 m = Bits32 (opcode, 3, 0);
5045 if (n == 15)
5046 return false;
5047
5048 // index = TRUE; add = TRUE; wback = FALSE;
5049 index = true;
5050 add = true;
5051 wback = false;
5052
5053 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5054 shift_t = SRType_LSL;
5055 shift_n = Bits32 (opcode, 5, 4);
5056
5057 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5058 if (BadReg (t) || BadReg (m))
5059 return false;
5060
5061 break;
5062
5063 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005064 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005065 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5066 t = Bits32 (opcode, 15, 12);
5067 n = Bits32 (opcode, 19, 16);
5068 m = Bits32 (opcode, 3, 0);
5069
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005070 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005071 index = BitIsSet (opcode, 24);
5072 add = BitIsSet (opcode, 23);
5073 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5074
5075 // (shift_t, shift_n) = (SRType_LSL, 0);
5076 shift_t = SRType_LSL;
5077 shift_n = 0;
5078
5079 // if t == 15 || m == 15 then UNPREDICTABLE;
5080 if ((t == 15) || (m == 15))
5081 return false;
5082
5083 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5084 if (wback && ((n == 15) || (n == t)))
5085 return false;
5086
5087 break;
5088
5089 default:
5090 return false;
5091 }
5092
5093 uint32_t Rm = ReadCoreReg (m, &success);
5094 if (!success)
5095 return false;
5096
5097 uint32_t Rn = ReadCoreReg (n, &success);
5098 if (!success)
5099 return false;
5100
5101 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00005102 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
5103 if (!success)
5104 return false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005105
5106 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5107 addr_t offset_addr;
5108 if (add)
5109 offset_addr = Rn + offset;
5110 else
5111 offset_addr = Rn - offset;
5112
5113 // address = if index then offset_addr else R[n];
5114 addr_t address;
5115 if (index)
5116 address = offset_addr;
5117 else
5118 address = Rn;
5119
5120 EmulateInstruction::Context context;
5121 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005122 RegisterInfo base_reg;
5123 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5124 RegisterInfo offset_reg;
5125 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005126
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005127 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005128 if (UnalignedSupport() || BitIsClear (address, 0))
5129 {
5130 // MemU[address,2] = R[t]<15:0>;
5131 uint32_t Rt = ReadCoreReg (t, &success);
5132 if (!success)
5133 return false;
5134
5135 EmulateInstruction::Context context;
5136 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005137 RegisterInfo base_reg;
5138 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5139 RegisterInfo offset_reg;
5140 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5141 RegisterInfo data_reg;
5142 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005143 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5144
5145 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5146 return false;
5147 }
5148 else // Can only occur before ARMv7
5149 {
5150 // MemU[address,2] = bits(16) UNKNOWN;
5151 }
5152
5153 // if wback then R[n] = offset_addr;
5154 if (wback)
5155 {
5156 context.type = eContextAdjustBaseRegister;
5157 context.SetAddress (offset_addr);
5158 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5159 return false;
5160 }
5161 }
5162
5163 return true;
5164}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005165
Johnny Chen157b9592011-02-18 21:13:05 +00005166// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5167// and writes the result to the destination register. It can optionally update the condition flags
5168// based on the result.
5169bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005170EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005171{
5172#if 0
5173 // ARM pseudo code...
5174 if ConditionPassed() then
5175 EncodingSpecificOperations();
5176 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5177 if d == 15 then // Can only occur for ARM encoding
5178 ALUWritePC(result); // setflags is always FALSE here
5179 else
5180 R[d] = result;
5181 if setflags then
5182 APSR.N = result<31>;
5183 APSR.Z = IsZeroBit(result);
5184 APSR.C = carry;
5185 APSR.V = overflow;
5186#endif
5187
5188 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005189
Greg Clayton7bc39082011-03-24 23:53:38 +00005190 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005191 {
5192 uint32_t Rd, Rn;
5193 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5194 bool setflags;
5195 switch (encoding)
5196 {
5197 case eEncodingT1:
5198 Rd = Bits32(opcode, 11, 8);
5199 Rn = Bits32(opcode, 19, 16);
5200 setflags = BitIsSet(opcode, 20);
5201 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5202 if (BadReg(Rd) || BadReg(Rn))
5203 return false;
5204 break;
5205 case eEncodingA1:
5206 Rd = Bits32(opcode, 15, 12);
5207 Rn = Bits32(opcode, 19, 16);
5208 setflags = BitIsSet(opcode, 20);
5209 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005210
Johnny Chen157b9592011-02-18 21:13:05 +00005211 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005212 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005213 break;
5214 default:
5215 return false;
5216 }
5217
5218 // Read the first operand.
5219 int32_t val1 = ReadCoreReg(Rn, &success);
5220 if (!success)
5221 return false;
5222
5223 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5224
5225 EmulateInstruction::Context context;
5226 context.type = EmulateInstruction::eContextImmediate;
5227 context.SetNoArgs ();
5228
5229 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5230 return false;
5231 }
5232 return true;
5233}
5234
5235// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5236// register value, and writes the result to the destination register. It can optionally update the
5237// condition flags based on the result.
5238bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005239EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005240{
5241#if 0
5242 // ARM pseudo code...
5243 if ConditionPassed() then
5244 EncodingSpecificOperations();
5245 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5246 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5247 if d == 15 then // Can only occur for ARM encoding
5248 ALUWritePC(result); // setflags is always FALSE here
5249 else
5250 R[d] = result;
5251 if setflags then
5252 APSR.N = result<31>;
5253 APSR.Z = IsZeroBit(result);
5254 APSR.C = carry;
5255 APSR.V = overflow;
5256#endif
5257
5258 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005259
Greg Clayton7bc39082011-03-24 23:53:38 +00005260 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005261 {
5262 uint32_t Rd, Rn, Rm;
5263 ARM_ShifterType shift_t;
5264 uint32_t shift_n; // the shift applied to the value read from Rm
5265 bool setflags;
5266 switch (encoding)
5267 {
5268 case eEncodingT1:
5269 Rd = Rn = Bits32(opcode, 2, 0);
5270 Rm = Bits32(opcode, 5, 3);
5271 setflags = !InITBlock();
5272 shift_t = SRType_LSL;
5273 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005274 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005275 case eEncodingT2:
5276 Rd = Bits32(opcode, 11, 8);
5277 Rn = Bits32(opcode, 19, 16);
5278 Rm = Bits32(opcode, 3, 0);
5279 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005280 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005281 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5282 return false;
5283 break;
5284 case eEncodingA1:
5285 Rd = Bits32(opcode, 15, 12);
5286 Rn = Bits32(opcode, 19, 16);
5287 Rm = Bits32(opcode, 3, 0);
5288 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005289 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005290
Johnny Chen157b9592011-02-18 21:13:05 +00005291 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005292 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005293 break;
5294 default:
5295 return false;
5296 }
5297
5298 // Read the first operand.
5299 int32_t val1 = ReadCoreReg(Rn, &success);
5300 if (!success)
5301 return false;
5302
5303 // Read the second operand.
5304 int32_t val2 = ReadCoreReg(Rm, &success);
5305 if (!success)
5306 return false;
5307
Johnny Chena4438a72011-06-02 22:50:51 +00005308 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5309 if (!success)
5310 return false;
Johnny Chen157b9592011-02-18 21:13:05 +00005311 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5312
5313 EmulateInstruction::Context context;
5314 context.type = EmulateInstruction::eContextImmediate;
5315 context.SetNoArgs ();
5316
5317 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5318 return false;
5319 }
5320 return true;
5321}
5322
Johnny Chena695f952011-02-23 21:24:25 +00005323// This instruction adds an immediate value to the PC value to form a PC-relative address,
5324// and writes the result to the destination register.
5325bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005326EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005327{
5328#if 0
5329 // ARM pseudo code...
5330 if ConditionPassed() then
5331 EncodingSpecificOperations();
5332 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5333 if d == 15 then // Can only occur for ARM encodings
5334 ALUWritePC(result);
5335 else
5336 R[d] = result;
5337#endif
5338
5339 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005340
Greg Clayton7bc39082011-03-24 23:53:38 +00005341 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005342 {
5343 uint32_t Rd;
5344 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5345 bool add;
5346 switch (encoding)
5347 {
5348 case eEncodingT1:
5349 Rd = Bits32(opcode, 10, 8);
5350 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5351 break;
5352 case eEncodingT2:
5353 case eEncodingT3:
5354 Rd = Bits32(opcode, 11, 8);
5355 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5356 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5357 if (BadReg(Rd))
5358 return false;
5359 break;
5360 case eEncodingA1:
5361 case eEncodingA2:
5362 Rd = Bits32(opcode, 15, 12);
5363 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5364 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5365 break;
5366 default:
5367 return false;
5368 }
5369
5370 // Read the PC value.
5371 uint32_t pc = ReadCoreReg(PC_REG, &success);
5372 if (!success)
5373 return false;
5374
5375 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5376
5377 EmulateInstruction::Context context;
5378 context.type = EmulateInstruction::eContextImmediate;
5379 context.SetNoArgs ();
5380
5381 if (!WriteCoreReg(context, result, Rd))
5382 return false;
5383 }
5384 return true;
5385}
5386
Johnny Chene97c0d52011-02-18 19:32:20 +00005387// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5388// to the destination register. It can optionally update the condition flags based on the result.
5389bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005390EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005391{
5392#if 0
5393 // ARM pseudo code...
5394 if ConditionPassed() then
5395 EncodingSpecificOperations();
5396 result = R[n] AND imm32;
5397 if d == 15 then // Can only occur for ARM encoding
5398 ALUWritePC(result); // setflags is always FALSE here
5399 else
5400 R[d] = result;
5401 if setflags then
5402 APSR.N = result<31>;
5403 APSR.Z = IsZeroBit(result);
5404 APSR.C = carry;
5405 // APSR.V unchanged
5406#endif
5407
5408 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005409
Greg Clayton7bc39082011-03-24 23:53:38 +00005410 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005411 {
5412 uint32_t Rd, Rn;
5413 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5414 bool setflags;
5415 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5416 switch (encoding)
5417 {
5418 case eEncodingT1:
5419 Rd = Bits32(opcode, 11, 8);
5420 Rn = Bits32(opcode, 19, 16);
5421 setflags = BitIsSet(opcode, 20);
5422 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005423 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005424 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005425 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005426 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5427 return false;
5428 break;
5429 case eEncodingA1:
5430 Rd = Bits32(opcode, 15, 12);
5431 Rn = Bits32(opcode, 19, 16);
5432 setflags = BitIsSet(opcode, 20);
5433 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005434
Johnny Chene97c0d52011-02-18 19:32:20 +00005435 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005436 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005437 break;
5438 default:
5439 return false;
5440 }
5441
Johnny Chene97c0d52011-02-18 19:32:20 +00005442 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005443 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005444 if (!success)
5445 return false;
5446
5447 uint32_t result = val1 & imm32;
5448
5449 EmulateInstruction::Context context;
5450 context.type = EmulateInstruction::eContextImmediate;
5451 context.SetNoArgs ();
5452
5453 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5454 return false;
5455 }
5456 return true;
5457}
5458
5459// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5460// and writes the result to the destination register. It can optionally update the condition flags
5461// based on the result.
5462bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005463EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005464{
5465#if 0
5466 // ARM pseudo code...
5467 if ConditionPassed() then
5468 EncodingSpecificOperations();
5469 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5470 result = R[n] AND shifted;
5471 if d == 15 then // Can only occur for ARM encoding
5472 ALUWritePC(result); // setflags is always FALSE here
5473 else
5474 R[d] = result;
5475 if setflags then
5476 APSR.N = result<31>;
5477 APSR.Z = IsZeroBit(result);
5478 APSR.C = carry;
5479 // APSR.V unchanged
5480#endif
5481
5482 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005483
Greg Clayton7bc39082011-03-24 23:53:38 +00005484 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005485 {
5486 uint32_t Rd, Rn, Rm;
5487 ARM_ShifterType shift_t;
5488 uint32_t shift_n; // the shift applied to the value read from Rm
5489 bool setflags;
5490 uint32_t carry;
5491 switch (encoding)
5492 {
5493 case eEncodingT1:
5494 Rd = Rn = Bits32(opcode, 2, 0);
5495 Rm = Bits32(opcode, 5, 3);
5496 setflags = !InITBlock();
5497 shift_t = SRType_LSL;
5498 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005499 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005500 case eEncodingT2:
5501 Rd = Bits32(opcode, 11, 8);
5502 Rn = Bits32(opcode, 19, 16);
5503 Rm = Bits32(opcode, 3, 0);
5504 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005505 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005506 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005507 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005508 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005509 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5510 return false;
5511 break;
5512 case eEncodingA1:
5513 Rd = Bits32(opcode, 15, 12);
5514 Rn = Bits32(opcode, 19, 16);
5515 Rm = Bits32(opcode, 3, 0);
5516 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005517 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005518
Johnny Chene97c0d52011-02-18 19:32:20 +00005519 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005520 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005521 break;
5522 default:
5523 return false;
5524 }
5525
Johnny Chene97c0d52011-02-18 19:32:20 +00005526 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005527 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005528 if (!success)
5529 return false;
5530
5531 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005532 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005533 if (!success)
5534 return false;
5535
Johnny Chena4438a72011-06-02 22:50:51 +00005536 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5537 if (!success)
5538 return false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005539 uint32_t result = val1 & shifted;
5540
5541 EmulateInstruction::Context context;
5542 context.type = EmulateInstruction::eContextImmediate;
5543 context.SetNoArgs ();
5544
5545 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5546 return false;
5547 }
5548 return true;
5549}
5550
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005551// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5552// immediate value, and writes the result to the destination register. It can optionally update the
5553// condition flags based on the result.
5554bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005555EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005556{
5557#if 0
5558 // ARM pseudo code...
5559 if ConditionPassed() then
5560 EncodingSpecificOperations();
5561 result = R[n] AND NOT(imm32);
5562 if d == 15 then // Can only occur for ARM encoding
5563 ALUWritePC(result); // setflags is always FALSE here
5564 else
5565 R[d] = result;
5566 if setflags then
5567 APSR.N = result<31>;
5568 APSR.Z = IsZeroBit(result);
5569 APSR.C = carry;
5570 // APSR.V unchanged
5571#endif
5572
5573 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005574
Greg Clayton7bc39082011-03-24 23:53:38 +00005575 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005576 {
5577 uint32_t Rd, Rn;
5578 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5579 bool setflags;
5580 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5581 switch (encoding)
5582 {
5583 case eEncodingT1:
5584 Rd = Bits32(opcode, 11, 8);
5585 Rn = Bits32(opcode, 19, 16);
5586 setflags = BitIsSet(opcode, 20);
5587 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5588 if (BadReg(Rd) || BadReg(Rn))
5589 return false;
5590 break;
5591 case eEncodingA1:
5592 Rd = Bits32(opcode, 15, 12);
5593 Rn = Bits32(opcode, 19, 16);
5594 setflags = BitIsSet(opcode, 20);
5595 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005596
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005597 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005598 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005599 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005600 break;
5601 default:
5602 return false;
5603 }
5604
5605 // Read the first operand.
5606 uint32_t val1 = ReadCoreReg(Rn, &success);
5607 if (!success)
5608 return false;
5609
5610 uint32_t result = val1 & ~imm32;
5611
5612 EmulateInstruction::Context context;
5613 context.type = EmulateInstruction::eContextImmediate;
5614 context.SetNoArgs ();
5615
5616 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5617 return false;
5618 }
5619 return true;
5620}
5621
5622// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5623// optionally-shifted register value, and writes the result to the destination register.
5624// It can optionally update the condition flags based on the result.
5625bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005626EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005627{
5628#if 0
5629 // ARM pseudo code...
5630 if ConditionPassed() then
5631 EncodingSpecificOperations();
5632 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5633 result = R[n] AND NOT(shifted);
5634 if d == 15 then // Can only occur for ARM encoding
5635 ALUWritePC(result); // setflags is always FALSE here
5636 else
5637 R[d] = result;
5638 if setflags then
5639 APSR.N = result<31>;
5640 APSR.Z = IsZeroBit(result);
5641 APSR.C = carry;
5642 // APSR.V unchanged
5643#endif
5644
5645 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005646
Greg Clayton7bc39082011-03-24 23:53:38 +00005647 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005648 {
5649 uint32_t Rd, Rn, Rm;
5650 ARM_ShifterType shift_t;
5651 uint32_t shift_n; // the shift applied to the value read from Rm
5652 bool setflags;
5653 uint32_t carry;
5654 switch (encoding)
5655 {
5656 case eEncodingT1:
5657 Rd = Rn = Bits32(opcode, 2, 0);
5658 Rm = Bits32(opcode, 5, 3);
5659 setflags = !InITBlock();
5660 shift_t = SRType_LSL;
5661 shift_n = 0;
5662 break;
5663 case eEncodingT2:
5664 Rd = Bits32(opcode, 11, 8);
5665 Rn = Bits32(opcode, 19, 16);
5666 Rm = Bits32(opcode, 3, 0);
5667 setflags = BitIsSet(opcode, 20);
5668 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5669 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5670 return false;
5671 break;
5672 case eEncodingA1:
5673 Rd = Bits32(opcode, 15, 12);
5674 Rn = Bits32(opcode, 19, 16);
5675 Rm = Bits32(opcode, 3, 0);
5676 setflags = BitIsSet(opcode, 20);
5677 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005678
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005679 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005680 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005681 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005682 break;
5683 default:
5684 return false;
5685 }
5686
5687 // Read the first operand.
5688 uint32_t val1 = ReadCoreReg(Rn, &success);
5689 if (!success)
5690 return false;
5691
5692 // Read the second operand.
5693 uint32_t val2 = ReadCoreReg(Rm, &success);
5694 if (!success)
5695 return false;
5696
Johnny Chena4438a72011-06-02 22:50:51 +00005697 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5698 if (!success)
5699 return false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005700 uint32_t result = val1 & ~shifted;
5701
5702 EmulateInstruction::Context context;
5703 context.type = EmulateInstruction::eContextImmediate;
5704 context.SetNoArgs ();
5705
5706 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5707 return false;
5708 }
5709 return true;
5710}
5711
Caroline Tice4d729c52011-02-18 00:55:53 +00005712// 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 +00005713// 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 +00005714bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005715EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005716{
5717#if 0
5718 if ConditionPassed() then
5719 EncodingSpecificOperations();
5720 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5721 address = if index then offset_addr else R[n];
5722 data = MemU[address,4];
5723 if wback then R[n] = offset_addr;
5724 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005725 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5726 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005727 R[t] = data;
5728 else // Can only apply before ARMv7
5729 R[t] = ROR(data, 8*UInt(address<1:0>));
5730#endif
5731
5732 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005733
Greg Clayton7bc39082011-03-24 23:53:38 +00005734 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005735 {
5736 const uint32_t addr_byte_size = GetAddressByteSize();
5737
5738 uint32_t t;
5739 uint32_t n;
5740 uint32_t imm32;
5741 bool index;
5742 bool add;
5743 bool wback;
5744
5745 switch (encoding)
5746 {
5747 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005748 // if Rn == '1111' then SEE LDR (literal);
5749 // if P == '0' && W == '1' then SEE LDRT;
5750 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005751 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5752 t = Bits32 (opcode, 15, 12);
5753 n = Bits32 (opcode, 19, 16);
5754 imm32 = Bits32 (opcode, 11, 0);
5755
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005756 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5757 index = BitIsSet (opcode, 24);
5758 add = BitIsSet (opcode, 23);
5759 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005760
5761 // if wback && n == t then UNPREDICTABLE;
5762 if (wback && (n == t))
5763 return false;
5764
5765 break;
5766
5767 default:
5768 return false;
5769 }
5770
5771 addr_t address;
5772 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005773 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005774 if (!success)
5775 return false;
5776
5777 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5778 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005779 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005780 else
5781 offset_addr = base_address - imm32;
5782
5783 // address = if index then offset_addr else R[n];
5784 if (index)
5785 address = offset_addr;
5786 else
5787 address = base_address;
5788
5789 // data = MemU[address,4];
5790
Greg Claytonc07d4512011-04-26 23:48:45 +00005791 RegisterInfo base_reg;
5792 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4d729c52011-02-18 00:55:53 +00005793
5794 EmulateInstruction::Context context;
5795 context.type = eContextRegisterLoad;
5796 context.SetRegisterPlusOffset (base_reg, address - base_address);
5797
5798 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5799 if (!success)
5800 return false;
5801
5802 // if wback then R[n] = offset_addr;
5803 if (wback)
5804 {
5805 context.type = eContextAdjustBaseRegister;
5806 context.SetAddress (offset_addr);
5807 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5808 return false;
5809 }
5810
5811 // if t == 15 then
5812 if (t == 15)
5813 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005814 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005815 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5816 {
5817 // LoadWritePC (data);
5818 context.type = eContextRegisterLoad;
5819 context.SetRegisterPlusOffset (base_reg, address - base_address);
5820 LoadWritePC (context, data);
5821 }
5822 else
5823 return false;
5824 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005825 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005826 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5827 {
5828 // R[t] = data;
5829 context.type = eContextRegisterLoad;
5830 context.SetRegisterPlusOffset (base_reg, address - base_address);
5831 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5832 return false;
5833 }
5834 // else // Can only apply before ARMv7
5835 else
5836 {
5837 // R[t] = ROR(data, 8*UInt(address<1:0>));
Johnny Chena4438a72011-06-02 22:50:51 +00005838 data = ROR (data, Bits32 (address, 1, 0), &success);
5839 if (!success)
5840 return false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005841 context.type = eContextRegisterLoad;
5842 context.SetImmediate (data);
5843 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5844 return false;
5845 }
5846
5847 }
5848 return true;
5849}
5850
Caroline Ticefe479112011-02-18 18:52:37 +00005851// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5852// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5853bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005854EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005855{
5856#if 0
5857 if ConditionPassed() then
5858 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5859 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5860 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5861 address = if index then offset_addr else R[n];
5862 data = MemU[address,4];
5863 if wback then R[n] = offset_addr;
5864 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005865 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5866 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005867 R[t] = data;
5868 else // Can only apply before ARMv7
5869 if CurrentInstrSet() == InstrSet_ARM then
5870 R[t] = ROR(data, 8*UInt(address<1:0>));
5871 else
5872 R[t] = bits(32) UNKNOWN;
5873#endif
5874
5875 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005876
Greg Clayton7bc39082011-03-24 23:53:38 +00005877 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005878 {
5879 const uint32_t addr_byte_size = GetAddressByteSize();
5880
5881 uint32_t t;
5882 uint32_t n;
5883 uint32_t m;
5884 bool index;
5885 bool add;
5886 bool wback;
5887 ARM_ShifterType shift_t;
5888 uint32_t shift_n;
5889
5890 switch (encoding)
5891 {
5892 case eEncodingT1:
5893 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5894 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5895 t = Bits32 (opcode, 2, 0);
5896 n = Bits32 (opcode, 5, 3);
5897 m = Bits32 (opcode, 8, 6);
5898
5899 // index = TRUE; add = TRUE; wback = FALSE;
5900 index = true;
5901 add = true;
5902 wback = false;
5903
5904 // (shift_t, shift_n) = (SRType_LSL, 0);
5905 shift_t = SRType_LSL;
5906 shift_n = 0;
5907
5908 break;
5909
5910 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005911 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005912 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5913 t = Bits32 (opcode, 15, 12);
5914 n = Bits32 (opcode, 19, 16);
5915 m = Bits32 (opcode, 3, 0);
5916
5917 // index = TRUE; add = TRUE; wback = FALSE;
5918 index = true;
5919 add = true;
5920 wback = false;
5921
5922 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5923 shift_t = SRType_LSL;
5924 shift_n = Bits32 (opcode, 5, 4);
5925
5926 // if BadReg(m) then UNPREDICTABLE;
5927 if (BadReg (m))
5928 return false;
5929
5930 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5931 if ((t == 15) && InITBlock() && !LastInITBlock())
5932 return false;
5933
5934 break;
5935
5936 case eEncodingA1:
5937 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005938 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005939 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5940 t = Bits32 (opcode, 15, 12);
5941 n = Bits32 (opcode, 19, 16);
5942 m = Bits32 (opcode, 3, 0);
5943
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005944 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005945 index = BitIsSet (opcode, 24);
5946 add = BitIsSet (opcode, 23);
5947 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5948
5949 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5950 uint32_t type = Bits32 (opcode, 6, 5);
5951 uint32_t imm5 = Bits32 (opcode, 11, 7);
5952 shift_n = DecodeImmShift (type, imm5, shift_t);
5953
5954 // if m == 15 then UNPREDICTABLE;
5955 if (m == 15)
5956 return false;
5957
5958 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5959 if (wback && ((n == 15) || (n == t)))
5960 return false;
5961 }
5962 break;
5963
5964
5965 default:
5966 return false;
5967 }
5968
5969 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5970 if (!success)
5971 return false;
5972
5973 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5974 if (!success)
5975 return false;
5976
5977 addr_t offset_addr;
5978 addr_t address;
5979
5980 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Johnny Chena4438a72011-06-02 22:50:51 +00005981 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C), &success);
5982 if (!success)
5983 return false;
Caroline Ticefe479112011-02-18 18:52:37 +00005984
5985 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5986 if (add)
5987 offset_addr = Rn + offset;
5988 else
5989 offset_addr = Rn - offset;
5990
5991 // address = if index then offset_addr else R[n];
5992 if (index)
5993 address = offset_addr;
5994 else
5995 address = Rn;
5996
5997 // data = MemU[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +00005998 RegisterInfo base_reg;
5999 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefe479112011-02-18 18:52:37 +00006000
6001 EmulateInstruction::Context context;
6002 context.type = eContextRegisterLoad;
6003 context.SetRegisterPlusOffset (base_reg, address - Rn);
6004
6005 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
6006 if (!success)
6007 return false;
6008
6009 // if wback then R[n] = offset_addr;
6010 if (wback)
6011 {
6012 context.type = eContextAdjustBaseRegister;
6013 context.SetAddress (offset_addr);
6014 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6015 return false;
6016 }
6017
6018 // if t == 15 then
6019 if (t == 15)
6020 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006021 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00006022 if (BitIsClear (address, 1) && BitIsClear (address, 0))
6023 {
6024 context.type = eContextRegisterLoad;
6025 context.SetRegisterPlusOffset (base_reg, address - Rn);
6026 LoadWritePC (context, data);
6027 }
6028 else
6029 return false;
6030 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006031 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00006032 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
6033 {
6034 // R[t] = data;
6035 context.type = eContextRegisterLoad;
6036 context.SetRegisterPlusOffset (base_reg, address - Rn);
6037 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6038 return false;
6039 }
6040 else // Can only apply before ARMv7
6041 {
6042 // if CurrentInstrSet() == InstrSet_ARM then
6043 if (CurrentInstrSet () == eModeARM)
6044 {
6045 // R[t] = ROR(data, 8*UInt(address<1:0>));
Johnny Chena4438a72011-06-02 22:50:51 +00006046 data = ROR (data, Bits32 (address, 1, 0), &success);
6047 if (!success)
6048 return false;
Caroline Ticefe479112011-02-18 18:52:37 +00006049 context.type = eContextRegisterLoad;
6050 context.SetImmediate (data);
6051 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6052 return false;
6053 }
6054 else
6055 {
6056 // R[t] = bits(32) UNKNOWN;
6057 WriteBits32Unknown (t);
6058 }
6059 }
6060 }
6061 return true;
6062}
Caroline Tice21b604b2011-02-18 21:06:04 +00006063
6064// LDRB (immediate, Thumb)
6065bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006066EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00006067{
6068#if 0
6069 if ConditionPassed() then
6070 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6071 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6072 address = if index then offset_addr else R[n];
6073 R[t] = ZeroExtend(MemU[address,1], 32);
6074 if wback then R[n] = offset_addr;
6075#endif
6076
6077 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00006078
Greg Clayton7bc39082011-03-24 23:53:38 +00006079 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00006080 {
6081 uint32_t t;
6082 uint32_t n;
6083 uint32_t imm32;
6084 bool index;
6085 bool add;
6086 bool wback;
6087
6088 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6089 switch (encoding)
6090 {
6091 case eEncodingT1:
6092 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6093 t = Bits32 (opcode, 2, 0);
6094 n = Bits32 (opcode, 5, 3);
6095 imm32 = Bits32 (opcode, 10, 6);
6096
6097 // index = TRUE; add = TRUE; wback = FALSE;
6098 index = true;
6099 add = true;
6100 wback= false;
6101
6102 break;
6103
6104 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006105 // if Rt == '1111' then SEE PLD;
6106 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006107 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6108 t = Bits32 (opcode, 15, 12);
6109 n = Bits32 (opcode, 19, 16);
6110 imm32 = Bits32 (opcode, 11, 0);
6111
6112 // index = TRUE; add = TRUE; wback = FALSE;
6113 index = true;
6114 add = true;
6115 wback = false;
6116
6117 // if t == 13 then UNPREDICTABLE;
6118 if (t == 13)
6119 return false;
6120
6121 break;
6122
6123 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006124 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6125 // if Rn == '1111' then SEE LDRB (literal);
6126 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6127 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006128 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6129 return false;
6130
6131 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6132 t = Bits32 (opcode, 15, 12);
6133 n = Bits32 (opcode, 19, 16);
6134 imm32 = Bits32 (opcode, 7, 0);
6135
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006136 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006137 index = BitIsSet (opcode, 10);
6138 add = BitIsSet (opcode, 9);
6139 wback = BitIsSet (opcode, 8);
6140
6141 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6142 if (BadReg (t) || (wback && (n == t)))
6143 return false;
6144
6145 break;
6146
6147 default:
6148 return false;
6149 }
6150
6151 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6152 if (!success)
6153 return false;
6154
6155 addr_t address;
6156 addr_t offset_addr;
6157
6158 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6159 if (add)
6160 offset_addr = Rn + imm32;
6161 else
6162 offset_addr = Rn - imm32;
6163
6164 // address = if index then offset_addr else R[n];
6165 if (index)
6166 address = offset_addr;
6167 else
6168 address = Rn;
6169
6170 // R[t] = ZeroExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006171 RegisterInfo base_reg;
6172 RegisterInfo data_reg;
6173 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6174 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice21b604b2011-02-18 21:06:04 +00006175
6176 EmulateInstruction::Context context;
6177 context.type = eContextRegisterLoad;
6178 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6179
6180 uint64_t data = MemURead (context, address, 1, 0, &success);
6181 if (!success)
6182 return false;
6183
6184 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6185 return false;
6186
6187 // if wback then R[n] = offset_addr;
6188 if (wback)
6189 {
6190 context.type = eContextAdjustBaseRegister;
6191 context.SetAddress (offset_addr);
6192 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6193 return false;
6194 }
6195 }
6196 return true;
6197}
Caroline Ticef55261f2011-02-18 22:24:22 +00006198
6199// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6200// zero-extends it to form a 32-bit word and writes it to a register.
6201bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006202EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006203{
6204#if 0
6205 if ConditionPassed() then
6206 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6207 base = Align(PC,4);
6208 address = if add then (base + imm32) else (base - imm32);
6209 R[t] = ZeroExtend(MemU[address,1], 32);
6210#endif
6211
6212 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006213
Greg Clayton7bc39082011-03-24 23:53:38 +00006214 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006215 {
6216 uint32_t t;
6217 uint32_t imm32;
6218 bool add;
6219 switch (encoding)
6220 {
6221 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006222 // if Rt == '1111' then SEE PLD;
6223 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006224 t = Bits32 (opcode, 15, 12);
6225 imm32 = Bits32 (opcode, 11, 0);
6226 add = BitIsSet (opcode, 23);
6227
6228 // if t == 13 then UNPREDICTABLE;
6229 if (t == 13)
6230 return false;
6231
6232 break;
6233
6234 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006235 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006236 t = Bits32 (opcode, 15, 12);
6237 imm32 = Bits32 (opcode, 11, 0);
6238 add = BitIsSet (opcode, 23);
6239
6240 // if t == 15 then UNPREDICTABLE;
6241 if (t == 15)
6242 return false;
6243 break;
6244
6245 default:
6246 return false;
6247 }
6248
6249 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006250 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006251 if (!success)
6252 return false;
6253
6254 uint32_t base = AlignPC (pc_val);
6255
6256 addr_t address;
6257 // address = if add then (base + imm32) else (base - imm32);
6258 if (add)
6259 address = base + imm32;
6260 else
6261 address = base - imm32;
6262
6263 // R[t] = ZeroExtend(MemU[address,1], 32);
6264 EmulateInstruction::Context context;
6265 context.type = eContextRelativeBranchImmediate;
6266 context.SetImmediate (address - base);
6267
6268 uint64_t data = MemURead (context, address, 1, 0, &success);
6269 if (!success)
6270 return false;
6271
6272 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6273 return false;
6274 }
6275 return true;
6276}
Caroline Tice30fec122011-02-18 23:52:21 +00006277
6278// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6279// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6280// optionally be shifted.
6281bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006282EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006283{
6284#if 0
6285 if ConditionPassed() then
6286 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6287 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6288 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6289 address = if index then offset_addr else R[n];
6290 R[t] = ZeroExtend(MemU[address,1],32);
6291 if wback then R[n] = offset_addr;
6292#endif
6293
6294 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006295
Greg Clayton7bc39082011-03-24 23:53:38 +00006296 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006297 {
6298 uint32_t t;
6299 uint32_t n;
6300 uint32_t m;
6301 bool index;
6302 bool add;
6303 bool wback;
6304 ARM_ShifterType shift_t;
6305 uint32_t shift_n;
6306
6307 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6308 switch (encoding)
6309 {
6310 case eEncodingT1:
6311 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6312 t = Bits32 (opcode, 2, 0);
6313 n = Bits32 (opcode, 5, 3);
6314 m = Bits32 (opcode, 8, 6);
6315
6316 // index = TRUE; add = TRUE; wback = FALSE;
6317 index = true;
6318 add = true;
6319 wback = false;
6320
6321 // (shift_t, shift_n) = (SRType_LSL, 0);
6322 shift_t = SRType_LSL;
6323 shift_n = 0;
6324 break;
6325
6326 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006327 // if Rt == '1111' then SEE PLD;
6328 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006329 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6330 t = Bits32 (opcode, 15, 12);
6331 n = Bits32 (opcode, 19, 16);
6332 m = Bits32 (opcode, 3, 0);
6333
6334 // index = TRUE; add = TRUE; wback = FALSE;
6335 index = true;
6336 add = true;
6337 wback = false;
6338
6339 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6340 shift_t = SRType_LSL;
6341 shift_n = Bits32 (opcode, 5, 4);
6342
6343 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6344 if ((t == 13) || BadReg (m))
6345 return false;
6346 break;
6347
6348 case eEncodingA1:
6349 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006350 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006351 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6352 t = Bits32 (opcode, 15, 12);
6353 n = Bits32 (opcode, 19, 16);
6354 m = Bits32 (opcode, 3, 0);
6355
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006356 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006357 index = BitIsSet (opcode, 24);
6358 add = BitIsSet (opcode, 23);
6359 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6360
6361 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6362 uint32_t type = Bits32 (opcode, 6, 5);
6363 uint32_t imm5 = Bits32 (opcode, 11, 7);
6364 shift_n = DecodeImmShift (type, imm5, shift_t);
6365
6366 // if t == 15 || m == 15 then UNPREDICTABLE;
6367 if ((t == 15) || (m == 15))
6368 return false;
6369
6370 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6371 if (wback && ((n == 15) || (n == t)))
6372 return false;
6373 }
6374 break;
6375
6376 default:
6377 return false;
6378 }
6379
6380 addr_t offset_addr;
6381 addr_t address;
6382
6383 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6384 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6385 if (!success)
6386 return false;
6387
Johnny Chena4438a72011-06-02 22:50:51 +00006388 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6389 if (!success)
6390 return false;
Caroline Tice30fec122011-02-18 23:52:21 +00006391
6392 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6393 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6394 if (!success)
6395 return false;
6396
6397 if (add)
6398 offset_addr = Rn + offset;
6399 else
6400 offset_addr = Rn - offset;
6401
6402 // address = if index then offset_addr else R[n];
6403 if (index)
6404 address = offset_addr;
6405 else
6406 address = Rn;
6407
6408 // R[t] = ZeroExtend(MemU[address,1],32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006409 RegisterInfo base_reg;
6410 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice30fec122011-02-18 23:52:21 +00006411
6412 EmulateInstruction::Context context;
6413 context.type = eContextRegisterLoad;
6414 context.SetRegisterPlusOffset (base_reg, address - Rn);
6415
6416 uint64_t data = MemURead (context, address, 1, 0, &success);
6417 if (!success)
6418 return false;
6419
6420 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6421 return false;
6422
6423 // if wback then R[n] = offset_addr;
6424 if (wback)
6425 {
6426 context.type = eContextAdjustBaseRegister;
6427 context.SetAddress (offset_addr);
6428 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6429 return false;
6430 }
6431 }
6432 return true;
6433}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006434
6435// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6436// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6437// post-indexed, or pre-indexed addressing.
6438bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006439EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006440{
6441#if 0
6442 if ConditionPassed() then
6443 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6444 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6445 address = if index then offset_addr else R[n];
6446 data = MemU[address,2];
6447 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006448 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006449 R[t] = ZeroExtend(data, 32);
6450 else // Can only apply before ARMv7
6451 R[t] = bits(32) UNKNOWN;
6452#endif
6453
6454
6455 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006456
Greg Clayton7bc39082011-03-24 23:53:38 +00006457 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006458 {
6459 uint32_t t;
6460 uint32_t n;
6461 uint32_t imm32;
6462 bool index;
6463 bool add;
6464 bool wback;
6465
6466 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6467 switch (encoding)
6468 {
6469 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006470 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006471 t = Bits32 (opcode, 2, 0);
6472 n = Bits32 (opcode, 5, 3);
6473 imm32 = Bits32 (opcode, 10, 6) << 1;
6474
6475 // index = TRUE; add = TRUE; wback = FALSE;
6476 index = true;
6477 add = true;
6478 wback = false;
6479
6480 break;
6481
6482 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006483 // if Rt == '1111' then SEE "Unallocated memory hints";
6484 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006485 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6486 t = Bits32 (opcode, 15, 12);
6487 n = Bits32 (opcode, 19, 16);
6488 imm32 = Bits32 (opcode, 11, 0);
6489
6490 // index = TRUE; add = TRUE; wback = FALSE;
6491 index = true;
6492 add = true;
6493 wback = false;
6494
6495 // if t == 13 then UNPREDICTABLE;
6496 if (t == 13)
6497 return false;
6498 break;
6499
6500 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006501 // if Rn == '1111' then SEE LDRH (literal);
6502 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6503 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6504 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006505 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6506 return false;
6507
6508 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6509 t = Bits32 (opcode, 15, 12);
6510 n = Bits32 (opcode, 19, 16);
6511 imm32 = Bits32 (opcode, 7, 0);
6512
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006513 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006514 index = BitIsSet (opcode, 10);
6515 add = BitIsSet (opcode, 9);
6516 wback = BitIsSet (opcode, 8);
6517
6518 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6519 if (BadReg (t) || (wback && (n == t)))
6520 return false;
6521 break;
6522
6523 default:
6524 return false;
6525 }
6526
6527 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6528 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6529 if (!success)
6530 return false;
6531
6532 addr_t offset_addr;
6533 addr_t address;
6534
6535 if (add)
6536 offset_addr = Rn + imm32;
6537 else
6538 offset_addr = Rn - imm32;
6539
6540 // address = if index then offset_addr else R[n];
6541 if (index)
6542 address = offset_addr;
6543 else
6544 address = Rn;
6545
6546 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006547 RegisterInfo base_reg;
6548 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006549
6550 EmulateInstruction::Context context;
6551 context.type = eContextRegisterLoad;
6552 context.SetRegisterPlusOffset (base_reg, address - Rn);
6553
6554 uint64_t data = MemURead (context, address, 2, 0, &success);
6555 if (!success)
6556 return false;
6557
6558 // if wback then R[n] = offset_addr;
6559 if (wback)
6560 {
6561 context.type = eContextAdjustBaseRegister;
6562 context.SetAddress (offset_addr);
6563 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6564 return false;
6565 }
6566
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006567 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006568 if (UnalignedSupport () || BitIsClear (address, 0))
6569 {
6570 // R[t] = ZeroExtend(data, 32);
6571 context.type = eContextRegisterLoad;
6572 context.SetRegisterPlusOffset (base_reg, address - Rn);
6573 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6574 return false;
6575 }
6576 else // Can only apply before ARMv7
6577 {
6578 // R[t] = bits(32) UNKNOWN;
6579 WriteBits32Unknown (t);
6580 }
6581 }
6582 return true;
6583}
Caroline Ticefe479112011-02-18 18:52:37 +00006584
Caroline Tice952b5382011-02-28 23:15:24 +00006585// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6586// zero-extends it to form a 32-bit word, and writes it to a register.
6587bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006588EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006589{
6590#if 0
6591 if ConditionPassed() then
6592 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6593 base = Align(PC,4);
6594 address = if add then (base + imm32) else (base - imm32);
6595 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006596 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006597 R[t] = ZeroExtend(data, 32);
6598 else // Can only apply before ARMv7
6599 R[t] = bits(32) UNKNOWN;
6600#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006601
Caroline Tice952b5382011-02-28 23:15:24 +00006602 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006603
Greg Clayton7bc39082011-03-24 23:53:38 +00006604 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006605 {
6606 uint32_t t;
6607 uint32_t imm32;
6608 bool add;
6609
6610 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6611 switch (encoding)
6612 {
6613 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006614 // if Rt == '1111' then SEE "Unallocated memory hints";
6615 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006616 t = Bits32 (opcode, 15, 12);
6617 imm32 = Bits32 (opcode, 11, 0);
6618 add = BitIsSet (opcode, 23);
6619
6620 // if t == 13 then UNPREDICTABLE;
6621 if (t == 13)
6622 return false;
6623
6624 break;
6625
6626 case eEncodingA1:
6627 {
6628 uint32_t imm4H = Bits32 (opcode, 11, 8);
6629 uint32_t imm4L = Bits32 (opcode, 3, 0);
6630
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006631 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006632 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006633 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006634 add = BitIsSet (opcode, 23);
6635
6636 // if t == 15 then UNPREDICTABLE;
6637 if (t == 15)
6638 return false;
6639 break;
6640 }
6641
6642 default:
6643 return false;
6644 }
6645
6646 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006647 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006648 if (!success)
6649 return false;
6650
6651 addr_t base = AlignPC (pc_value);
6652 addr_t address;
6653
6654 // address = if add then (base + imm32) else (base - imm32);
6655 if (add)
6656 address = base + imm32;
6657 else
6658 address = base - imm32;
6659
6660 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006661 RegisterInfo base_reg;
6662 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice952b5382011-02-28 23:15:24 +00006663
6664 EmulateInstruction::Context context;
6665 context.type = eContextRegisterLoad;
6666 context.SetRegisterPlusOffset (base_reg, address - base);
6667
6668 uint64_t data = MemURead (context, address, 2, 0, &success);
6669 if (!success)
6670 return false;
6671
6672
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006673 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006674 if (UnalignedSupport () || BitIsClear (address, 0))
6675 {
6676 // R[t] = ZeroExtend(data, 32);
6677 context.type = eContextRegisterLoad;
6678 context.SetRegisterPlusOffset (base_reg, address - base);
6679 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6680 return false;
6681
6682 }
6683 else // Can only apply before ARMv7
6684 {
6685 // R[t] = bits(32) UNKNOWN;
6686 WriteBits32Unknown (t);
6687 }
6688 }
6689 return true;
6690}
6691
Caroline Tice0e6bc952011-03-01 18:00:42 +00006692// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6693// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6694// be shifted left by 0, 1, 2, or 3 bits.
6695bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006696EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006697{
6698#if 0
6699 if ConditionPassed() then
6700 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6701 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6702 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6703 address = if index then offset_addr else R[n];
6704 data = MemU[address,2];
6705 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006706 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006707 R[t] = ZeroExtend(data, 32);
6708 else // Can only apply before ARMv7
6709 R[t] = bits(32) UNKNOWN;
6710#endif
6711
6712 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006713
Greg Clayton7bc39082011-03-24 23:53:38 +00006714 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006715 {
6716 uint32_t t;
6717 uint32_t n;
6718 uint32_t m;
6719 bool index;
6720 bool add;
6721 bool wback;
6722 ARM_ShifterType shift_t;
6723 uint32_t shift_n;
6724
6725 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6726 switch (encoding)
6727 {
6728 case eEncodingT1:
6729 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6730 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6731 t = Bits32 (opcode, 2, 0);
6732 n = Bits32 (opcode, 5, 3);
6733 m = Bits32 (opcode, 8, 6);
6734
6735 // index = TRUE; add = TRUE; wback = FALSE;
6736 index = true;
6737 add = true;
6738 wback = false;
6739
6740 // (shift_t, shift_n) = (SRType_LSL, 0);
6741 shift_t = SRType_LSL;
6742 shift_n = 0;
6743
6744 break;
6745
6746 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006747 // if Rn == '1111' then SEE LDRH (literal);
6748 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006749 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6750 t = Bits32 (opcode, 15, 12);
6751 n = Bits32 (opcode, 19, 16);
6752 m = Bits32 (opcode, 3, 0);
6753
6754 // index = TRUE; add = TRUE; wback = FALSE;
6755 index = true;
6756 add = true;
6757 wback = false;
6758
6759 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6760 shift_t = SRType_LSL;
6761 shift_n = Bits32 (opcode, 5, 4);
6762
6763 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6764 if ((t == 13) || BadReg (m))
6765 return false;
6766 break;
6767
6768 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006769 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006770 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6771 t = Bits32 (opcode, 15, 12);
6772 n = Bits32 (opcode, 19, 16);
6773 m = Bits32 (opcode, 3, 0);
6774
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006775 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006776 index = BitIsSet (opcode, 24);
6777 add = BitIsSet (opcode, 23);
6778 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6779
6780 // (shift_t, shift_n) = (SRType_LSL, 0);
6781 shift_t = SRType_LSL;
6782 shift_n = 0;
6783
6784 // if t == 15 || m == 15 then UNPREDICTABLE;
6785 if ((t == 15) || (m == 15))
6786 return false;
6787
6788 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6789 if (wback && ((n == 15) || (n == t)))
6790 return false;
6791
6792 break;
6793
6794 default:
6795 return false;
6796 }
6797
6798 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6799
6800 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6801 if (!success)
6802 return false;
6803
Johnny Chena4438a72011-06-02 22:50:51 +00006804 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6805 if (!success)
6806 return false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006807
6808 addr_t offset_addr;
6809 addr_t address;
6810
6811 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6812 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6813 if (!success)
6814 return false;
6815
6816 if (add)
6817 offset_addr = Rn + offset;
6818 else
6819 offset_addr = Rn - offset;
6820
6821 // address = if index then offset_addr else R[n];
6822 if (index)
6823 address = offset_addr;
6824 else
6825 address = Rn;
6826
6827 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006828 RegisterInfo base_reg;
6829 RegisterInfo offset_reg;
6830 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6831 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice0e6bc952011-03-01 18:00:42 +00006832
6833 EmulateInstruction::Context context;
6834 context.type = eContextRegisterLoad;
6835 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6836 uint64_t data = MemURead (context, address, 2, 0, &success);
6837 if (!success)
6838 return false;
6839
6840 // if wback then R[n] = offset_addr;
6841 if (wback)
6842 {
6843 context.type = eContextAdjustBaseRegister;
6844 context.SetAddress (offset_addr);
6845 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6846 return false;
6847 }
6848
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006849 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006850 if (UnalignedSupport() || BitIsClear (address, 0))
6851 {
6852 // R[t] = ZeroExtend(data, 32);
6853 context.type = eContextRegisterLoad;
6854 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6855 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6856 return false;
6857 }
6858 else // Can only apply before ARMv7
6859 {
6860 // R[t] = bits(32) UNKNOWN;
6861 WriteBits32Unknown (t);
6862 }
6863 }
6864 return true;
6865}
6866
Caroline Ticea5e28af2011-03-01 21:53:03 +00006867// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6868// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6869// or pre-indexed addressing.
6870bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006871EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006872{
6873#if 0
6874 if ConditionPassed() then
6875 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6876 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6877 address = if index then offset_addr else R[n];
6878 R[t] = SignExtend(MemU[address,1], 32);
6879 if wback then R[n] = offset_addr;
6880#endif
6881
6882 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006883
Greg Clayton7bc39082011-03-24 23:53:38 +00006884 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006885 {
6886 uint32_t t;
6887 uint32_t n;
6888 uint32_t imm32;
6889 bool index;
6890 bool add;
6891 bool wback;
6892
6893 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6894 switch (encoding)
6895 {
6896 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006897 // if Rt == '1111' then SEE PLI;
6898 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006899 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6900 t = Bits32 (opcode, 15, 12);
6901 n = Bits32 (opcode, 19, 16);
6902 imm32 = Bits32 (opcode, 11, 0);
6903
6904 // index = TRUE; add = TRUE; wback = FALSE;
6905 index = true;
6906 add = true;
6907 wback = false;
6908
6909 // if t == 13 then UNPREDICTABLE;
6910 if (t == 13)
6911 return false;
6912
6913 break;
6914
6915 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006916 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6917 // if Rn == '1111' then SEE LDRSB (literal);
6918 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6919 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006920 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6921 return false;
6922
6923 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6924 t = Bits32 (opcode, 15, 12);
6925 n = Bits32 (opcode, 19, 16);
6926 imm32 = Bits32 (opcode, 7, 0);
6927
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006928 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006929 index = BitIsSet (opcode, 10);
6930 add = BitIsSet (opcode, 9);
6931 wback = BitIsSet (opcode, 8);
6932
6933 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006934 if (((t == 13) || ((t == 15)
6935 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6936 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006937 return false;
6938
6939 break;
6940
6941 case eEncodingA1:
6942 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006943 // if Rn == '1111' then SEE LDRSB (literal);
6944 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006945 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6946 t = Bits32 (opcode, 15, 12);
6947 n = Bits32 (opcode, 19, 16);
6948
6949 uint32_t imm4H = Bits32 (opcode, 11, 8);
6950 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006951 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006952
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006953 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006954 index = BitIsSet (opcode, 24);
6955 add = BitIsSet (opcode, 23);
6956 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6957
6958 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6959 if ((t == 15) || (wback && (n == t)))
6960 return false;
6961
6962 break;
6963 }
6964
6965 default:
6966 return false;
6967 }
6968
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006969 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006970 if (!success)
6971 return false;
6972
6973 addr_t offset_addr;
6974 addr_t address;
6975
6976 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6977 if (add)
6978 offset_addr = Rn + imm32;
6979 else
6980 offset_addr = Rn - imm32;
6981
6982 // address = if index then offset_addr else R[n];
6983 if (index)
6984 address = offset_addr;
6985 else
6986 address = Rn;
6987
6988 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006989 RegisterInfo base_reg;
6990 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006991
6992 EmulateInstruction::Context context;
6993 context.type = eContextRegisterLoad;
6994 context.SetRegisterPlusOffset (base_reg, address - Rn);
6995
6996 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6997 if (!success)
6998 return false;
6999
7000 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7001 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7002 return false;
7003
7004 // if wback then R[n] = offset_addr;
7005 if (wback)
7006 {
7007 context.type = eContextAdjustBaseRegister;
7008 context.SetAddress (offset_addr);
7009 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7010 return false;
7011 }
7012 }
7013
7014 return true;
7015}
Caroline Tice0e6bc952011-03-01 18:00:42 +00007016
Caroline Tice5f593912011-03-01 22:25:17 +00007017// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
7018// sign-extends it to form a 32-bit word, and writes tit to a register.
7019bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007020EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00007021{
7022#if 0
7023 if ConditionPassed() then
7024 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7025 base = Align(PC,4);
7026 address = if add then (base + imm32) else (base - imm32);
7027 R[t] = SignExtend(MemU[address,1], 32);
7028#endif
7029
7030 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00007031
Greg Clayton7bc39082011-03-24 23:53:38 +00007032 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00007033 {
7034 uint32_t t;
7035 uint32_t imm32;
7036 bool add;
7037
7038 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7039 switch (encoding)
7040 {
7041 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007042 // if Rt == '1111' then SEE PLI;
7043 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007044 t = Bits32 (opcode, 15, 12);
7045 imm32 = Bits32 (opcode, 11, 0);
7046 add = BitIsSet (opcode, 23);
7047
7048 // if t == 13 then UNPREDICTABLE;
7049 if (t == 13)
7050 return false;
7051
7052 break;
7053
7054 case eEncodingA1:
7055 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007056 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007057 t = Bits32 (opcode, 15, 12);
7058 uint32_t imm4H = Bits32 (opcode, 11, 8);
7059 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007060 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00007061 add = BitIsSet (opcode, 23);
7062
7063 // if t == 15 then UNPREDICTABLE;
7064 if (t == 15)
7065 return false;
7066
7067 break;
7068 }
7069
7070 default:
7071 return false;
7072 }
7073
7074 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007075 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007076 if (!success)
7077 return false;
7078 uint64_t base = AlignPC (pc_value);
7079
7080 // address = if add then (base + imm32) else (base - imm32);
7081 addr_t address;
7082 if (add)
7083 address = base + imm32;
7084 else
7085 address = base - imm32;
7086
7087 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007088 RegisterInfo base_reg;
7089 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice5f593912011-03-01 22:25:17 +00007090
7091 EmulateInstruction::Context context;
7092 context.type = eContextRegisterLoad;
7093 context.SetRegisterPlusOffset (base_reg, address - base);
7094
7095 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7096 if (!success)
7097 return false;
7098
7099 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7100 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7101 return false;
7102 }
7103 return true;
7104}
7105
Caroline Tice672f3112011-03-01 23:55:59 +00007106// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7107// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7108// shifted left by 0, 1, 2, or 3 bits.
7109bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007110EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007111{
7112#if 0
7113 if ConditionPassed() then
7114 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7115 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7116 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7117 address = if index then offset_addr else R[n];
7118 R[t] = SignExtend(MemU[address,1], 32);
7119 if wback then R[n] = offset_addr;
7120#endif
7121
7122 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007123
Greg Clayton7bc39082011-03-24 23:53:38 +00007124 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007125 {
7126 uint32_t t;
7127 uint32_t n;
7128 uint32_t m;
7129 bool index;
7130 bool add;
7131 bool wback;
7132 ARM_ShifterType shift_t;
7133 uint32_t shift_n;
7134
7135 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7136 switch (encoding)
7137 {
7138 case eEncodingT1:
7139 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7140 t = Bits32 (opcode, 2, 0);
7141 n = Bits32 (opcode, 5, 3);
7142 m = Bits32 (opcode, 8, 6);
7143
7144 // index = TRUE; add = TRUE; wback = FALSE;
7145 index = true;
7146 add = true;
7147 wback = false;
7148
7149 // (shift_t, shift_n) = (SRType_LSL, 0);
7150 shift_t = SRType_LSL;
7151 shift_n = 0;
7152
7153 break;
7154
7155 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007156 // if Rt == '1111' then SEE PLI;
7157 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007158 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7159 t = Bits32 (opcode, 15, 12);
7160 n = Bits32 (opcode, 19, 16);
7161 m = Bits32 (opcode, 3, 0);
7162
7163 // index = TRUE; add = TRUE; wback = FALSE;
7164 index = true;
7165 add = true;
7166 wback = false;
7167
7168 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7169 shift_t = SRType_LSL;
7170 shift_n = Bits32 (opcode, 5, 4);
7171
7172 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7173 if ((t == 13) || BadReg (m))
7174 return false;
7175 break;
7176
7177 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007178 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007179 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7180 t = Bits32 (opcode, 15, 12);
7181 n = Bits32 (opcode, 19, 16);
7182 m = Bits32 (opcode, 3, 0);
7183
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007184 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007185 index = BitIsSet (opcode, 24);
7186 add = BitIsSet (opcode, 23);
7187 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7188
7189 // (shift_t, shift_n) = (SRType_LSL, 0);
7190 shift_t = SRType_LSL;
7191 shift_n = 0;
7192
7193 // if t == 15 || m == 15 then UNPREDICTABLE;
7194 if ((t == 15) || (m == 15))
7195 return false;
7196
7197 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7198 if (wback && ((n == 15) || (n == t)))
7199 return false;
7200 break;
7201
7202 default:
7203 return false;
7204 }
7205
7206 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7207 if (!success)
7208 return false;
7209
7210 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00007211 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7212 if (!success)
7213 return false;
Caroline Tice672f3112011-03-01 23:55:59 +00007214
7215 addr_t offset_addr;
7216 addr_t address;
7217
7218 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7219 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7220 if (!success)
7221 return false;
7222
7223 if (add)
7224 offset_addr = Rn + offset;
7225 else
7226 offset_addr = Rn - offset;
7227
7228 // address = if index then offset_addr else R[n];
7229 if (index)
7230 address = offset_addr;
7231 else
7232 address = Rn;
7233
7234 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007235 RegisterInfo base_reg;
7236 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7237 RegisterInfo offset_reg;
7238 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice672f3112011-03-01 23:55:59 +00007239
7240 EmulateInstruction::Context context;
7241 context.type = eContextRegisterLoad;
7242 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7243
7244 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7245 if (!success)
7246 return false;
7247
7248 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7249 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7250 return false;
7251
7252 // if wback then R[n] = offset_addr;
7253 if (wback)
7254 {
7255 context.type = eContextAdjustBaseRegister;
7256 context.SetAddress (offset_addr);
7257 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7258 return false;
7259 }
7260 }
7261 return true;
7262}
7263
Caroline Tice78fb5632011-03-02 00:39:42 +00007264// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7265// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7266// pre-indexed addressing.
7267bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007268EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007269{
7270#if 0
7271 if ConditionPassed() then
7272 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7273 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7274 address = if index then offset_addr else R[n];
7275 data = MemU[address,2];
7276 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007277 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007278 R[t] = SignExtend(data, 32);
7279 else // Can only apply before ARMv7
7280 R[t] = bits(32) UNKNOWN;
7281#endif
7282
7283 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007284
Greg Clayton7bc39082011-03-24 23:53:38 +00007285 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007286 {
7287 uint32_t t;
7288 uint32_t n;
7289 uint32_t imm32;
7290 bool index;
7291 bool add;
7292 bool wback;
7293
7294 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7295 switch (encoding)
7296 {
7297 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007298 // if Rn == '1111' then SEE LDRSH (literal);
7299 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007300 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7301 t = Bits32 (opcode, 15, 12);
7302 n = Bits32 (opcode, 19, 16);
7303 imm32 = Bits32 (opcode, 11, 0);
7304
7305 // index = TRUE; add = TRUE; wback = FALSE;
7306 index = true;
7307 add = true;
7308 wback = false;
7309
7310 // if t == 13 then UNPREDICTABLE;
7311 if (t == 13)
7312 return false;
7313
7314 break;
7315
7316 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007317 // if Rn == '1111' then SEE LDRSH (literal);
7318 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7319 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7320 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007321 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7322 return false;
7323
7324 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7325 t = Bits32 (opcode, 15, 12);
7326 n = Bits32 (opcode, 19, 16);
7327 imm32 = Bits32 (opcode, 7, 0);
7328
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007329 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007330 index = BitIsSet (opcode, 10);
7331 add = BitIsSet (opcode, 9);
7332 wback = BitIsSet (opcode, 8);
7333
7334 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7335 if (BadReg (t) || (wback && (n == t)))
7336 return false;
7337
7338 break;
7339
7340 case eEncodingA1:
7341 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007342 // if Rn == '1111' then SEE LDRSH (literal);
7343 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007344 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7345 t = Bits32 (opcode, 15, 12);
7346 n = Bits32 (opcode, 19, 16);
7347 uint32_t imm4H = Bits32 (opcode, 11,8);
7348 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007349 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007350
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007351 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007352 index = BitIsSet (opcode, 24);
7353 add = BitIsSet (opcode, 23);
7354 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7355
7356 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7357 if ((t == 15) || (wback && (n == t)))
7358 return false;
7359
7360 break;
7361 }
7362
7363 default:
7364 return false;
7365 }
7366
7367 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7368 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7369 if (!success)
7370 return false;
7371
7372 addr_t offset_addr;
7373 if (add)
7374 offset_addr = Rn + imm32;
7375 else
7376 offset_addr = Rn - imm32;
7377
7378 // address = if index then offset_addr else R[n];
7379 addr_t address;
7380 if (index)
7381 address = offset_addr;
7382 else
7383 address = Rn;
7384
7385 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007386 RegisterInfo base_reg;
7387 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice78fb5632011-03-02 00:39:42 +00007388
7389 EmulateInstruction::Context context;
7390 context.type = eContextRegisterLoad;
7391 context.SetRegisterPlusOffset (base_reg, address - Rn);
7392
7393 uint64_t data = MemURead (context, address, 2, 0, &success);
7394 if (!success)
7395 return false;
7396
7397 // if wback then R[n] = offset_addr;
7398 if (wback)
7399 {
7400 context.type = eContextAdjustBaseRegister;
7401 context.SetAddress (offset_addr);
7402 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7403 return false;
7404 }
7405
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007406 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007407 if (UnalignedSupport() || BitIsClear (address, 0))
7408 {
7409 // R[t] = SignExtend(data, 32);
7410 int64_t signed_data = llvm::SignExtend64<16>(data);
7411 context.type = eContextRegisterLoad;
7412 context.SetRegisterPlusOffset (base_reg, address - Rn);
7413 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7414 return false;
7415 }
7416 else // Can only apply before ARMv7
7417 {
7418 // R[t] = bits(32) UNKNOWN;
7419 WriteBits32Unknown (t);
7420 }
7421 }
7422 return true;
7423}
7424
Caroline Ticed2fac092011-03-02 19:45:34 +00007425// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7426// sign-extends it to from a 32-bit word, and writes it to a register.
7427bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007428EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007429{
7430#if 0
7431 if ConditionPassed() then
7432 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7433 base = Align(PC,4);
7434 address = if add then (base + imm32) else (base - imm32);
7435 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007436 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007437 R[t] = SignExtend(data, 32);
7438 else // Can only apply before ARMv7
7439 R[t] = bits(32) UNKNOWN;
7440#endif
7441
7442 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007443
Greg Clayton7bc39082011-03-24 23:53:38 +00007444 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007445 {
7446 uint32_t t;
7447 uint32_t imm32;
7448 bool add;
7449
7450 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7451 switch (encoding)
7452 {
7453 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007454 // if Rt == '1111' then SEE "Unallocated memory hints";
7455 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007456 t = Bits32 (opcode, 15, 12);
7457 imm32 = Bits32 (opcode, 11, 0);
7458 add = BitIsSet (opcode, 23);
7459
7460 // if t == 13 then UNPREDICTABLE;
7461 if (t == 13)
7462 return false;
7463
7464 break;
7465
7466 case eEncodingA1:
7467 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007468 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007469 t = Bits32 (opcode, 15, 12);
7470 uint32_t imm4H = Bits32 (opcode, 11, 8);
7471 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007472 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007473 add = BitIsSet (opcode, 23);
7474
7475 // if t == 15 then UNPREDICTABLE;
7476 if (t == 15)
7477 return false;
7478
7479 break;
7480 }
7481 default:
7482 return false;
7483 }
7484
7485 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007486 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007487 if (!success)
7488 return false;
7489
7490 uint64_t base = AlignPC (pc_value);
7491
7492 addr_t address;
7493 // address = if add then (base + imm32) else (base - imm32);
7494 if (add)
7495 address = base + imm32;
7496 else
7497 address = base - imm32;
7498
7499 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007500 RegisterInfo base_reg;
7501 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Ticed2fac092011-03-02 19:45:34 +00007502
7503 EmulateInstruction::Context context;
7504 context.type = eContextRegisterLoad;
7505 context.SetRegisterPlusOffset (base_reg, imm32);
7506
7507 uint64_t data = MemURead (context, address, 2, 0, &success);
7508 if (!success)
7509 return false;
7510
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007511 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007512 if (UnalignedSupport() || BitIsClear (address, 0))
7513 {
7514 // R[t] = SignExtend(data, 32);
7515 int64_t signed_data = llvm::SignExtend64<16>(data);
7516 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7517 return false;
7518 }
7519 else // Can only apply before ARMv7
7520 {
7521 // R[t] = bits(32) UNKNOWN;
7522 WriteBits32Unknown (t);
7523 }
7524 }
7525 return true;
7526}
7527
Caroline Tice291a3e92011-03-02 21:13:44 +00007528// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7529// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7530// shifted left by 0, 1, 2, or 3 bits.
7531bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007532EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007533{
7534#if 0
7535 if ConditionPassed() then
7536 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7537 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7538 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7539 address = if index then offset_addr else R[n];
7540 data = MemU[address,2];
7541 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007542 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007543 R[t] = SignExtend(data, 32);
7544 else // Can only apply before ARMv7
7545 R[t] = bits(32) UNKNOWN;
7546#endif
7547
7548 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007549
Greg Clayton7bc39082011-03-24 23:53:38 +00007550 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007551 {
7552 uint32_t t;
7553 uint32_t n;
7554 uint32_t m;
7555 bool index;
7556 bool add;
7557 bool wback;
7558 ARM_ShifterType shift_t;
7559 uint32_t shift_n;
7560
7561 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7562 switch (encoding)
7563 {
7564 case eEncodingT1:
7565 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7566 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7567 t = Bits32 (opcode, 2, 0);
7568 n = Bits32 (opcode, 5, 3);
7569 m = Bits32 (opcode, 8, 6);
7570
7571 // index = TRUE; add = TRUE; wback = FALSE;
7572 index = true;
7573 add = true;
7574 wback = false;
7575
7576 // (shift_t, shift_n) = (SRType_LSL, 0);
7577 shift_t = SRType_LSL;
7578 shift_n = 0;
7579
7580 break;
7581
7582 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007583 // if Rn == '1111' then SEE LDRSH (literal);
7584 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007585 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7586 t = Bits32 (opcode, 15, 12);
7587 n = Bits32 (opcode, 19, 16);
7588 m = Bits32 (opcode, 3, 0);
7589
7590 // index = TRUE; add = TRUE; wback = FALSE;
7591 index = true;
7592 add = true;
7593 wback = false;
7594
7595 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7596 shift_t = SRType_LSL;
7597 shift_n = Bits32 (opcode, 5, 4);
7598
7599 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7600 if ((t == 13) || BadReg (m))
7601 return false;
7602
7603 break;
7604
7605 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007606 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007607 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7608 t = Bits32 (opcode, 15, 12);
7609 n = Bits32 (opcode, 19, 16);
7610 m = Bits32 (opcode, 3, 0);
7611
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007612 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007613 index = BitIsSet (opcode, 24);
7614 add = BitIsSet (opcode, 23);
7615 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7616
7617 // (shift_t, shift_n) = (SRType_LSL, 0);
7618 shift_t = SRType_LSL;
7619 shift_n = 0;
7620
7621 // if t == 15 || m == 15 then UNPREDICTABLE;
7622 if ((t == 15) || (m == 15))
7623 return false;
7624
7625 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7626 if (wback && ((n == 15) || (n == t)))
7627 return false;
7628
7629 break;
7630
7631 default:
7632 break;
7633 }
7634
7635 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7636 if (!success)
7637 return false;
7638
7639 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7640 if (!success)
7641 return false;
7642
7643 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00007644 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7645 if (!success)
7646 return false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007647
7648 addr_t offset_addr;
7649 addr_t address;
7650
7651 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7652 if (add)
7653 offset_addr = Rn + offset;
7654 else
7655 offset_addr = Rn - offset;
7656
7657 // address = if index then offset_addr else R[n];
7658 if (index)
7659 address = offset_addr;
7660 else
7661 address = Rn;
7662
7663 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007664 RegisterInfo base_reg;
7665 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007666
Greg Claytonc07d4512011-04-26 23:48:45 +00007667 RegisterInfo offset_reg;
7668 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007669
7670 EmulateInstruction::Context context;
7671 context.type = eContextRegisterLoad;
7672 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7673
7674 uint64_t data = MemURead (context, address, 2, 0, &success);
7675 if (!success)
7676 return false;
7677
7678 // if wback then R[n] = offset_addr;
7679 if (wback)
7680 {
7681 context.type = eContextAdjustBaseRegister;
7682 context.SetAddress (offset_addr);
7683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7684 return false;
7685 }
7686
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007687 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007688 if (UnalignedSupport() || BitIsClear (address, 0))
7689 {
7690 // R[t] = SignExtend(data, 32);
7691 context.type = eContextRegisterLoad;
7692 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7693
7694 int64_t signed_data = llvm::SignExtend64<16>(data);
7695 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7696 return false;
7697 }
7698 else // Can only apply before ARMv7
7699 {
7700 // R[t] = bits(32) UNKNOWN;
7701 WriteBits32Unknown (t);
7702 }
7703 }
7704 return true;
7705}
Caroline Tice6bf65162011-03-03 17:42:58 +00007706
7707// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7708// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7709bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007710EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007711{
7712#if 0
7713 if ConditionPassed() then
7714 EncodingSpecificOperations();
7715 rotated = ROR(R[m], rotation);
7716 R[d] = SignExtend(rotated<7:0>, 32);
7717#endif
7718
7719 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007720
Greg Clayton7bc39082011-03-24 23:53:38 +00007721 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007722 {
7723 uint32_t d;
7724 uint32_t m;
7725 uint32_t rotation;
7726
7727 // EncodingSpecificOperations();
7728 switch (encoding)
7729 {
7730 case eEncodingT1:
7731 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7732 d = Bits32 (opcode, 2, 0);
7733 m = Bits32 (opcode, 5, 3);
7734 rotation = 0;
7735
7736 break;
7737
7738 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007739 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007740 d = Bits32 (opcode, 11, 8);
7741 m = Bits32 (opcode, 3, 0);
7742 rotation = Bits32 (opcode, 5, 4) << 3;
7743
7744 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7745 if (BadReg (d) || BadReg (m))
7746 return false;
7747
7748 break;
7749
7750 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007751 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007752 d = Bits32 (opcode, 15, 12);
7753 m = Bits32 (opcode, 3, 0);
7754 rotation = Bits32 (opcode, 11, 10) << 3;
7755
7756 // if d == 15 || m == 15 then UNPREDICTABLE;
7757 if ((d == 15) || (m == 15))
7758 return false;
7759
7760 break;
7761
7762 default:
7763 return false;
7764 }
7765
Caroline Tice868198b2011-03-03 18:04:49 +00007766 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7767 if (!success)
7768 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007769
7770 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007771 uint64_t rotated = ROR (Rm, rotation, &success);
7772 if (!success)
7773 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007774
7775 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007776 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007777
Greg Claytonc07d4512011-04-26 23:48:45 +00007778 RegisterInfo source_reg;
7779 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice6bf65162011-03-03 17:42:58 +00007780
7781 EmulateInstruction::Context context;
7782 context.type = eContextRegisterLoad;
7783 context.SetRegister (source_reg);
7784
Caroline Tice8ce96d92011-03-03 18:27:17 +00007785 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007786 return false;
7787 }
7788 return true;
7789}
Caroline Tice291a3e92011-03-02 21:13:44 +00007790
Caroline Tice868198b2011-03-03 18:04:49 +00007791// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7792// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7793bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007794EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007795{
7796#if 0
7797 if ConditionPassed() then
7798 EncodingSpecificOperations();
7799 rotated = ROR(R[m], rotation);
7800 R[d] = SignExtend(rotated<15:0>, 32);
7801#endif
7802
7803 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007804
Greg Clayton7bc39082011-03-24 23:53:38 +00007805 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007806 {
7807 uint32_t d;
7808 uint32_t m;
7809 uint32_t rotation;
7810
7811 // EncodingSpecificOperations();
7812 switch (encoding)
7813 {
7814 case eEncodingT1:
7815 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7816 d = Bits32 (opcode, 2, 0);
7817 m = Bits32 (opcode, 5, 3);
7818 rotation = 0;
7819
7820 break;
7821
7822 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007823 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007824 d = Bits32 (opcode, 11, 8);
7825 m = Bits32 (opcode, 3, 0);
7826 rotation = Bits32 (opcode, 5, 4) << 3;
7827
7828 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7829 if (BadReg (d) || BadReg (m))
7830 return false;
7831
7832 break;
7833
7834 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007835 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007836 d = Bits32 (opcode, 15, 12);
7837 m = Bits32 (opcode, 3, 0);
7838 rotation = Bits32 (opcode, 11, 10) << 3;
7839
7840 // if d == 15 || m == 15 then UNPREDICTABLE;
7841 if ((d == 15) || (m == 15))
7842 return false;
7843
7844 break;
7845
7846 default:
7847 return false;
7848 }
7849
7850 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7851 if (!success)
7852 return false;
7853
7854 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007855 uint64_t rotated = ROR (Rm, rotation, &success);
7856 if (!success)
7857 return false;
Caroline Tice868198b2011-03-03 18:04:49 +00007858
7859 // R[d] = SignExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007860 RegisterInfo source_reg;
7861 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice868198b2011-03-03 18:04:49 +00007862
7863 EmulateInstruction::Context context;
7864 context.type = eContextRegisterLoad;
7865 context.SetRegister (source_reg);
7866
Caroline Tice8ce96d92011-03-03 18:27:17 +00007867 int64_t data = llvm::SignExtend64<16> (rotated);
7868 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007869 return false;
7870 }
7871
7872 return true;
7873}
7874
Caroline Tice8ce96d92011-03-03 18:27:17 +00007875// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7876// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7877bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007878EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007879{
7880#if 0
7881 if ConditionPassed() then
7882 EncodingSpecificOperations();
7883 rotated = ROR(R[m], rotation);
7884 R[d] = ZeroExtend(rotated<7:0>, 32);
7885#endif
7886
7887 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007888
Greg Clayton7bc39082011-03-24 23:53:38 +00007889 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007890 {
7891 uint32_t d;
7892 uint32_t m;
7893 uint32_t rotation;
7894
7895 // EncodingSpecificOperations();
7896 switch (encoding)
7897 {
7898 case eEncodingT1:
7899 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7900 d = Bits32 (opcode, 2, 0);
7901 m = Bits32 (opcode, 5, 3);
7902 rotation = 0;
7903
7904 break;
7905
7906 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007907 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007908 d = Bits32 (opcode, 11, 8);
7909 m = Bits32 (opcode, 3, 0);
7910 rotation = Bits32 (opcode, 5, 4) << 3;
7911
7912 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7913 if (BadReg (d) || BadReg (m))
7914 return false;
7915
7916 break;
7917
7918 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007919 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007920 d = Bits32 (opcode, 15, 12);
7921 m = Bits32 (opcode, 3, 0);
7922 rotation = Bits32 (opcode, 11, 10) << 3;
7923
7924 // if d == 15 || m == 15 then UNPREDICTABLE;
7925 if ((d == 15) || (m == 15))
7926 return false;
7927
7928 break;
7929
7930 default:
7931 return false;
7932 }
7933
7934 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7935 if (!success)
7936 return false;
7937
7938 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007939 uint64_t rotated = ROR (Rm, rotation, &success);
7940 if (!success)
7941 return false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007942
7943 // R[d] = ZeroExtend(rotated<7:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007944 RegisterInfo source_reg;
7945 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007946
7947 EmulateInstruction::Context context;
7948 context.type = eContextRegisterLoad;
7949 context.SetRegister (source_reg);
7950
7951 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7952 return false;
7953 }
7954 return true;
7955}
7956
Caroline Tice11555f22011-03-03 18:48:58 +00007957// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7958// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7959bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007960EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007961{
7962#if 0
7963 if ConditionPassed() then
7964 EncodingSpecificOperations();
7965 rotated = ROR(R[m], rotation);
7966 R[d] = ZeroExtend(rotated<15:0>, 32);
7967#endif
7968
7969 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007970
Greg Clayton7bc39082011-03-24 23:53:38 +00007971 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007972 {
7973 uint32_t d;
7974 uint32_t m;
7975 uint32_t rotation;
7976
7977 switch (encoding)
7978 {
7979 case eEncodingT1:
7980 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7981 d = Bits32 (opcode, 2, 0);
7982 m = Bits32 (opcode, 5, 3);
7983 rotation = 0;
7984
7985 break;
7986
7987 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007988 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007989 d = Bits32 (opcode, 11, 8);
7990 m = Bits32 (opcode, 3, 0);
7991 rotation = Bits32 (opcode, 5, 4) << 3;
7992
7993 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7994 if (BadReg (d) || BadReg (m))
7995 return false;
7996
7997 break;
7998
7999 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008000 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00008001 d = Bits32 (opcode, 15, 12);
8002 m = Bits32 (opcode, 3, 0);
8003 rotation = Bits32 (opcode, 11, 10) << 3;
8004
8005 // if d == 15 || m == 15 then UNPREDICTABLE;
8006 if ((d == 15) || (m == 15))
8007 return false;
8008
8009 break;
8010
8011 default:
8012 return false;
8013 }
8014
8015 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8016 if (!success)
8017 return false;
8018
8019 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00008020 uint64_t rotated = ROR (Rm, rotation, &success);
8021 if (!success)
8022 return false;
Caroline Tice11555f22011-03-03 18:48:58 +00008023
8024 // R[d] = ZeroExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00008025 RegisterInfo source_reg;
8026 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice11555f22011-03-03 18:48:58 +00008027
8028 EmulateInstruction::Context context;
8029 context.type = eContextRegisterLoad;
8030 context.SetRegister (source_reg);
8031
8032 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
8033 return false;
8034 }
8035 return true;
8036}
Caroline Ticeb27771d2011-03-03 22:37:46 +00008037
8038// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
8039// word respectively.
8040bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008041EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00008042{
8043#if 0
8044 if ConditionPassed() then
8045 EncodingSpecificOperations();
8046 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8047 UNPREDICTABLE;
8048 else
8049 address = if increment then R[n] else R[n]-8;
8050 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008051 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008052 BranchWritePC(MemA[address,4]);
8053 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8054#endif
8055
8056 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008057
Greg Clayton7bc39082011-03-24 23:53:38 +00008058 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00008059 {
8060 uint32_t n;
8061 bool wback;
8062 bool increment;
8063 bool wordhigher;
8064
8065 // EncodingSpecificOperations();
8066 switch (encoding)
8067 {
8068 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008069 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008070 n = Bits32 (opcode, 19, 16);
8071 wback = BitIsSet (opcode, 21);
8072 increment = false;
8073 wordhigher = false;
8074
8075 // if n == 15 then UNPREDICTABLE;
8076 if (n == 15)
8077 return false;
8078
8079 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8080 if (InITBlock() && !LastInITBlock())
8081 return false;
8082
8083 break;
8084
8085 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008086 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008087 n = Bits32 (opcode, 19, 16);
8088 wback = BitIsSet (opcode, 21);
8089 increment = true;
8090 wordhigher = false;
8091
8092 // if n == 15 then UNPREDICTABLE;
8093 if (n == 15)
8094 return false;
8095
8096 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8097 if (InITBlock() && !LastInITBlock())
8098 return false;
8099
8100 break;
8101
8102 case eEncodingA1:
8103 // n = UInt(Rn);
8104 n = Bits32 (opcode, 19, 16);
8105
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008106 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008107 wback = BitIsSet (opcode, 21);
8108 increment = BitIsSet (opcode, 23);
8109 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8110
8111 // if n == 15 then UNPREDICTABLE;
8112 if (n == 15)
8113 return false;
8114
8115 break;
8116
8117 default:
8118 return false;
8119 }
8120
8121 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8122 if (!CurrentModeIsPrivileged ())
8123 // UNPREDICTABLE;
8124 return false;
8125 else
8126 {
8127 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8128 if (!success)
8129 return false;
8130
8131 addr_t address;
8132 // address = if increment then R[n] else R[n]-8;
8133 if (increment)
8134 address = Rn;
8135 else
8136 address = Rn - 8;
8137
8138 // if wordhigher then address = address+4;
8139 if (wordhigher)
8140 address = address + 4;
8141
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008142 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Greg Claytonc07d4512011-04-26 23:48:45 +00008143 RegisterInfo base_reg;
8144 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008145
8146 EmulateInstruction::Context context;
8147 context.type = eContextReturnFromException;
8148 context.SetRegisterPlusOffset (base_reg, address - Rn);
8149
8150 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8151 if (!success)
8152 return false;
8153
8154 CPSRWriteByInstr (data, 15, true);
8155
8156 // BranchWritePC(MemA[address,4]);
8157 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8158 if (!success)
8159 return false;
8160
8161 BranchWritePC (context, data2);
8162
8163 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8164 if (wback)
8165 {
8166 context.type = eContextAdjustBaseRegister;
8167 if (increment)
8168 {
8169 context.SetOffset (8);
8170 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8171 return false;
8172 }
8173 else
8174 {
8175 context.SetOffset (-8);
8176 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8177 return false;
8178 }
8179 } // if wback
8180 }
8181 } // if ConditionPassed()
8182 return true;
8183}
Caroline Tice11555f22011-03-03 18:48:58 +00008184
Johnny Chen2115b412011-02-21 23:42:44 +00008185// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8186// and writes the result to the destination register. It can optionally update the condition flags based on
8187// the result.
8188bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008189EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008190{
8191#if 0
8192 // ARM pseudo code...
8193 if ConditionPassed() then
8194 EncodingSpecificOperations();
8195 result = R[n] EOR imm32;
8196 if d == 15 then // Can only occur for ARM encoding
8197 ALUWritePC(result); // setflags is always FALSE here
8198 else
8199 R[d] = result;
8200 if setflags then
8201 APSR.N = result<31>;
8202 APSR.Z = IsZeroBit(result);
8203 APSR.C = carry;
8204 // APSR.V unchanged
8205#endif
8206
8207 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008208
Greg Clayton7bc39082011-03-24 23:53:38 +00008209 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008210 {
8211 uint32_t Rd, Rn;
8212 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8213 bool setflags;
8214 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8215 switch (encoding)
8216 {
8217 case eEncodingT1:
8218 Rd = Bits32(opcode, 11, 8);
8219 Rn = Bits32(opcode, 19, 16);
8220 setflags = BitIsSet(opcode, 20);
8221 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8222 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8223 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008224 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008225 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8226 return false;
8227 break;
8228 case eEncodingA1:
8229 Rd = Bits32(opcode, 15, 12);
8230 Rn = Bits32(opcode, 19, 16);
8231 setflags = BitIsSet(opcode, 20);
8232 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008233
Johnny Chen2115b412011-02-21 23:42:44 +00008234 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008235 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008236 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008237 break;
8238 default:
8239 return false;
8240 }
8241
8242 // Read the first operand.
8243 uint32_t val1 = ReadCoreReg(Rn, &success);
8244 if (!success)
8245 return false;
8246
8247 uint32_t result = val1 ^ imm32;
8248
8249 EmulateInstruction::Context context;
8250 context.type = EmulateInstruction::eContextImmediate;
8251 context.SetNoArgs ();
8252
8253 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8254 return false;
8255 }
8256 return true;
8257}
8258
8259// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8260// optionally-shifted register value, and writes the result to the destination register.
8261// It can optionally update the condition flags based on the result.
8262bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008263EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008264{
8265#if 0
8266 // ARM pseudo code...
8267 if ConditionPassed() then
8268 EncodingSpecificOperations();
8269 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8270 result = R[n] EOR shifted;
8271 if d == 15 then // Can only occur for ARM encoding
8272 ALUWritePC(result); // setflags is always FALSE here
8273 else
8274 R[d] = result;
8275 if setflags then
8276 APSR.N = result<31>;
8277 APSR.Z = IsZeroBit(result);
8278 APSR.C = carry;
8279 // APSR.V unchanged
8280#endif
8281
8282 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008283
Greg Clayton7bc39082011-03-24 23:53:38 +00008284 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008285 {
8286 uint32_t Rd, Rn, Rm;
8287 ARM_ShifterType shift_t;
8288 uint32_t shift_n; // the shift applied to the value read from Rm
8289 bool setflags;
8290 uint32_t carry;
8291 switch (encoding)
8292 {
8293 case eEncodingT1:
8294 Rd = Rn = Bits32(opcode, 2, 0);
8295 Rm = Bits32(opcode, 5, 3);
8296 setflags = !InITBlock();
8297 shift_t = SRType_LSL;
8298 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008299 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008300 case eEncodingT2:
8301 Rd = Bits32(opcode, 11, 8);
8302 Rn = Bits32(opcode, 19, 16);
8303 Rm = Bits32(opcode, 3, 0);
8304 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008305 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8306 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008307 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008308 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008309 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8310 return false;
8311 break;
8312 case eEncodingA1:
8313 Rd = Bits32(opcode, 15, 12);
8314 Rn = Bits32(opcode, 19, 16);
8315 Rm = Bits32(opcode, 3, 0);
8316 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008317 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008318
Johnny Chen2115b412011-02-21 23:42:44 +00008319 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008320 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008321 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008322 break;
8323 default:
8324 return false;
8325 }
8326
8327 // Read the first operand.
8328 uint32_t val1 = ReadCoreReg(Rn, &success);
8329 if (!success)
8330 return false;
8331
8332 // Read the second operand.
8333 uint32_t val2 = ReadCoreReg(Rm, &success);
8334 if (!success)
8335 return false;
8336
Johnny Chena4438a72011-06-02 22:50:51 +00008337 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8338 if (!success)
8339 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00008340 uint32_t result = val1 ^ shifted;
8341
8342 EmulateInstruction::Context context;
8343 context.type = EmulateInstruction::eContextImmediate;
8344 context.SetNoArgs ();
8345
8346 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8347 return false;
8348 }
8349 return true;
8350}
8351
Johnny Chen7c5234d2011-02-18 23:41:11 +00008352// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8353// writes the result to the destination register. It can optionally update the condition flags based
8354// on the result.
8355bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008356EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008357{
8358#if 0
8359 // ARM pseudo code...
8360 if ConditionPassed() then
8361 EncodingSpecificOperations();
8362 result = R[n] OR imm32;
8363 if d == 15 then // Can only occur for ARM encoding
8364 ALUWritePC(result); // setflags is always FALSE here
8365 else
8366 R[d] = result;
8367 if setflags then
8368 APSR.N = result<31>;
8369 APSR.Z = IsZeroBit(result);
8370 APSR.C = carry;
8371 // APSR.V unchanged
8372#endif
8373
8374 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008375
Greg Clayton7bc39082011-03-24 23:53:38 +00008376 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008377 {
8378 uint32_t Rd, Rn;
8379 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8380 bool setflags;
8381 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8382 switch (encoding)
8383 {
8384 case eEncodingT1:
8385 Rd = Bits32(opcode, 11, 8);
8386 Rn = Bits32(opcode, 19, 16);
8387 setflags = BitIsSet(opcode, 20);
8388 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008389 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008390 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008391 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008392 if (BadReg(Rd) || Rn == 13)
8393 return false;
8394 break;
8395 case eEncodingA1:
8396 Rd = Bits32(opcode, 15, 12);
8397 Rn = Bits32(opcode, 19, 16);
8398 setflags = BitIsSet(opcode, 20);
8399 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008400
Johnny Chen7c5234d2011-02-18 23:41:11 +00008401 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008402 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008403 break;
8404 default:
8405 return false;
8406 }
8407
8408 // Read the first operand.
8409 uint32_t val1 = ReadCoreReg(Rn, &success);
8410 if (!success)
8411 return false;
8412
8413 uint32_t result = val1 | imm32;
8414
8415 EmulateInstruction::Context context;
8416 context.type = EmulateInstruction::eContextImmediate;
8417 context.SetNoArgs ();
8418
8419 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8420 return false;
8421 }
8422 return true;
8423}
8424
8425// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8426// value, and writes the result to the destination register. It can optionally update the condition flags based
8427// on the result.
8428bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008429EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008430{
8431#if 0
8432 // ARM pseudo code...
8433 if ConditionPassed() then
8434 EncodingSpecificOperations();
8435 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8436 result = R[n] OR shifted;
8437 if d == 15 then // Can only occur for ARM encoding
8438 ALUWritePC(result); // setflags is always FALSE here
8439 else
8440 R[d] = result;
8441 if setflags then
8442 APSR.N = result<31>;
8443 APSR.Z = IsZeroBit(result);
8444 APSR.C = carry;
8445 // APSR.V unchanged
8446#endif
8447
8448 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008449
Greg Clayton7bc39082011-03-24 23:53:38 +00008450 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008451 {
8452 uint32_t Rd, Rn, Rm;
8453 ARM_ShifterType shift_t;
8454 uint32_t shift_n; // the shift applied to the value read from Rm
8455 bool setflags;
8456 uint32_t carry;
8457 switch (encoding)
8458 {
8459 case eEncodingT1:
8460 Rd = Rn = Bits32(opcode, 2, 0);
8461 Rm = Bits32(opcode, 5, 3);
8462 setflags = !InITBlock();
8463 shift_t = SRType_LSL;
8464 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008465 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008466 case eEncodingT2:
8467 Rd = Bits32(opcode, 11, 8);
8468 Rn = Bits32(opcode, 19, 16);
8469 Rm = Bits32(opcode, 3, 0);
8470 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008471 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8472 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008473 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008474 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008475 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8476 return false;
8477 break;
8478 case eEncodingA1:
8479 Rd = Bits32(opcode, 15, 12);
8480 Rn = Bits32(opcode, 19, 16);
8481 Rm = Bits32(opcode, 3, 0);
8482 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008483 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008484
Johnny Chen7c5234d2011-02-18 23:41:11 +00008485 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008486 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008487 break;
8488 default:
8489 return false;
8490 }
8491
8492 // Read the first operand.
8493 uint32_t val1 = ReadCoreReg(Rn, &success);
8494 if (!success)
8495 return false;
8496
8497 // Read the second operand.
8498 uint32_t val2 = ReadCoreReg(Rm, &success);
8499 if (!success)
8500 return false;
8501
Johnny Chena4438a72011-06-02 22:50:51 +00008502 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8503 if (!success)
8504 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00008505 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008506
8507 EmulateInstruction::Context context;
8508 context.type = EmulateInstruction::eContextImmediate;
8509 context.SetNoArgs ();
8510
8511 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8512 return false;
8513 }
8514 return true;
8515}
8516
Johnny Chened32e7c2011-02-22 23:42:58 +00008517// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8518// the destination register. It can optionally update the condition flags based on the result.
8519bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008520EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008521{
8522#if 0
8523 // ARM pseudo code...
8524 if ConditionPassed() then
8525 EncodingSpecificOperations();
8526 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8527 if d == 15 then // Can only occur for ARM encoding
8528 ALUWritePC(result); // setflags is always FALSE here
8529 else
8530 R[d] = result;
8531 if setflags then
8532 APSR.N = result<31>;
8533 APSR.Z = IsZeroBit(result);
8534 APSR.C = carry;
8535 APSR.V = overflow;
8536#endif
8537
8538 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008539
8540 uint32_t Rd; // the destination register
8541 uint32_t Rn; // the first operand
8542 bool setflags;
8543 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8544 switch (encoding) {
8545 case eEncodingT1:
8546 Rd = Bits32(opcode, 2, 0);
8547 Rn = Bits32(opcode, 5, 3);
8548 setflags = !InITBlock();
8549 imm32 = 0;
8550 break;
8551 case eEncodingT2:
8552 Rd = Bits32(opcode, 11, 8);
8553 Rn = Bits32(opcode, 19, 16);
8554 setflags = BitIsSet(opcode, 20);
8555 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8556 if (BadReg(Rd) || BadReg(Rn))
8557 return false;
8558 break;
8559 case eEncodingA1:
8560 Rd = Bits32(opcode, 15, 12);
8561 Rn = Bits32(opcode, 19, 16);
8562 setflags = BitIsSet(opcode, 20);
8563 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008564
Johnny Chened32e7c2011-02-22 23:42:58 +00008565 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008566 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008567 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008568 break;
8569 default:
8570 return false;
8571 }
8572 // Read the register value from the operand register Rn.
8573 uint32_t reg_val = ReadCoreReg(Rn, &success);
8574 if (!success)
8575 return false;
8576
8577 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8578
8579 EmulateInstruction::Context context;
8580 context.type = EmulateInstruction::eContextImmediate;
8581 context.SetNoArgs ();
8582
8583 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8584 return false;
8585
8586 return true;
8587}
8588
8589// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8590// result to the destination register. It can optionally update the condition flags based on the result.
8591bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008592EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008593{
8594#if 0
8595 // ARM pseudo code...
8596 if ConditionPassed() then
8597 EncodingSpecificOperations();
8598 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8599 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8600 if d == 15 then // Can only occur for ARM encoding
8601 ALUWritePC(result); // setflags is always FALSE here
8602 else
8603 R[d] = result;
8604 if setflags then
8605 APSR.N = result<31>;
8606 APSR.Z = IsZeroBit(result);
8607 APSR.C = carry;
8608 APSR.V = overflow;
8609#endif
8610
8611 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008612
8613 uint32_t Rd; // the destination register
8614 uint32_t Rn; // the first operand
8615 uint32_t Rm; // the second operand
8616 bool setflags;
8617 ARM_ShifterType shift_t;
8618 uint32_t shift_n; // the shift applied to the value read from Rm
8619 switch (encoding) {
8620 case eEncodingT1:
8621 Rd = Bits32(opcode, 11, 8);
8622 Rn = Bits32(opcode, 19, 16);
8623 Rm = Bits32(opcode, 3, 0);
8624 setflags = BitIsSet(opcode, 20);
8625 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8626 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8627 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8628 return false;
8629 break;
8630 case eEncodingA1:
8631 Rd = Bits32(opcode, 15, 12);
8632 Rn = Bits32(opcode, 19, 16);
8633 Rm = Bits32(opcode, 3, 0);
8634 setflags = BitIsSet(opcode, 20);
8635 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008636
Johnny Chened32e7c2011-02-22 23:42:58 +00008637 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008638 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008639 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008640 break;
8641 default:
8642 return false;
8643 }
8644 // Read the register value from register Rn.
8645 uint32_t val1 = ReadCoreReg(Rn, &success);
8646 if (!success)
8647 return false;
8648
8649 // Read the register value from register Rm.
8650 uint32_t val2 = ReadCoreReg(Rm, &success);
8651 if (!success)
8652 return false;
8653
Johnny Chena4438a72011-06-02 22:50:51 +00008654 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8655 if (!success)
8656 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008657 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8658
8659 EmulateInstruction::Context context;
8660 context.type = EmulateInstruction::eContextImmediate;
8661 context.SetNoArgs();
8662 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8663 return false;
8664
8665 return true;
8666}
8667
Johnny Chen90e607b2011-02-23 00:07:09 +00008668// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8669// an immediate value, and writes the result to the destination register. It can optionally update the condition
8670// flags based on the result.
8671bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008672EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008673{
8674#if 0
8675 // ARM pseudo code...
8676 if ConditionPassed() then
8677 EncodingSpecificOperations();
8678 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8679 if d == 15 then
8680 ALUWritePC(result); // setflags is always FALSE here
8681 else
8682 R[d] = result;
8683 if setflags then
8684 APSR.N = result<31>;
8685 APSR.Z = IsZeroBit(result);
8686 APSR.C = carry;
8687 APSR.V = overflow;
8688#endif
8689
8690 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008691
8692 uint32_t Rd; // the destination register
8693 uint32_t Rn; // the first operand
8694 bool setflags;
8695 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8696 switch (encoding) {
8697 case eEncodingA1:
8698 Rd = Bits32(opcode, 15, 12);
8699 Rn = Bits32(opcode, 19, 16);
8700 setflags = BitIsSet(opcode, 20);
8701 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008702
Johnny Chen90e607b2011-02-23 00:07:09 +00008703 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008704 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008705 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008706 break;
8707 default:
8708 return false;
8709 }
8710 // Read the register value from the operand register Rn.
8711 uint32_t reg_val = ReadCoreReg(Rn, &success);
8712 if (!success)
8713 return false;
8714
8715 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8716
8717 EmulateInstruction::Context context;
8718 context.type = EmulateInstruction::eContextImmediate;
8719 context.SetNoArgs ();
8720
8721 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8722 return false;
8723
8724 return true;
8725}
8726
8727// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8728// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8729// condition flags based on the result.
8730bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008731EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008732{
8733#if 0
8734 // ARM pseudo code...
8735 if ConditionPassed() then
8736 EncodingSpecificOperations();
8737 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8738 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8739 if d == 15 then
8740 ALUWritePC(result); // setflags is always FALSE here
8741 else
8742 R[d] = result;
8743 if setflags then
8744 APSR.N = result<31>;
8745 APSR.Z = IsZeroBit(result);
8746 APSR.C = carry;
8747 APSR.V = overflow;
8748#endif
8749
8750 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008751
8752 uint32_t Rd; // the destination register
8753 uint32_t Rn; // the first operand
8754 uint32_t Rm; // the second operand
8755 bool setflags;
8756 ARM_ShifterType shift_t;
8757 uint32_t shift_n; // the shift applied to the value read from Rm
8758 switch (encoding) {
8759 case eEncodingA1:
8760 Rd = Bits32(opcode, 15, 12);
8761 Rn = Bits32(opcode, 19, 16);
8762 Rm = Bits32(opcode, 3, 0);
8763 setflags = BitIsSet(opcode, 20);
8764 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008765
Johnny Chen90e607b2011-02-23 00:07:09 +00008766 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008767 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008768 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008769 break;
8770 default:
8771 return false;
8772 }
8773 // Read the register value from register Rn.
8774 uint32_t val1 = ReadCoreReg(Rn, &success);
8775 if (!success)
8776 return false;
8777
8778 // Read the register value from register Rm.
8779 uint32_t val2 = ReadCoreReg(Rm, &success);
8780 if (!success)
8781 return false;
8782
Johnny Chena4438a72011-06-02 22:50:51 +00008783 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8784 if (!success)
8785 return false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008786 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8787
8788 EmulateInstruction::Context context;
8789 context.type = EmulateInstruction::eContextImmediate;
8790 context.SetNoArgs();
8791 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8792 return false;
8793
8794 return true;
8795}
8796
Johnny Chen9b381772011-02-23 01:01:21 +00008797// Subtract with Carry (immediate) subtracts an immediate value and the value of
8798// NOT (Carry flag) from a register value, and writes the result to the destination register.
8799// It can optionally update the condition flags based on the result.
8800bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008801EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008802{
8803#if 0
8804 // ARM pseudo code...
8805 if ConditionPassed() then
8806 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008807 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008808 if d == 15 then // Can only occur for ARM encoding
8809 ALUWritePC(result); // setflags is always FALSE here
8810 else
8811 R[d] = result;
8812 if setflags then
8813 APSR.N = result<31>;
8814 APSR.Z = IsZeroBit(result);
8815 APSR.C = carry;
8816 APSR.V = overflow;
8817#endif
8818
8819 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008820
8821 uint32_t Rd; // the destination register
8822 uint32_t Rn; // the first operand
8823 bool setflags;
8824 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8825 switch (encoding) {
8826 case eEncodingT1:
8827 Rd = Bits32(opcode, 11, 8);
8828 Rn = Bits32(opcode, 19, 16);
8829 setflags = BitIsSet(opcode, 20);
8830 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8831 if (BadReg(Rd) || BadReg(Rn))
8832 return false;
8833 break;
8834 case eEncodingA1:
8835 Rd = Bits32(opcode, 15, 12);
8836 Rn = Bits32(opcode, 19, 16);
8837 setflags = BitIsSet(opcode, 20);
8838 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008839
Johnny Chen9b381772011-02-23 01:01:21 +00008840 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008841 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008842 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008843 break;
8844 default:
8845 return false;
8846 }
8847 // Read the register value from the operand register Rn.
8848 uint32_t reg_val = ReadCoreReg(Rn, &success);
8849 if (!success)
8850 return false;
8851
8852 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8853
8854 EmulateInstruction::Context context;
8855 context.type = EmulateInstruction::eContextImmediate;
8856 context.SetNoArgs ();
8857
8858 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8859 return false;
8860
8861 return true;
8862}
8863
8864// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8865// NOT (Carry flag) from a register value, and writes the result to the destination register.
8866// It can optionally update the condition flags based on the result.
8867bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008868EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008869{
8870#if 0
8871 // ARM pseudo code...
8872 if ConditionPassed() then
8873 EncodingSpecificOperations();
8874 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8875 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8876 if d == 15 then // Can only occur for ARM encoding
8877 ALUWritePC(result); // setflags is always FALSE here
8878 else
8879 R[d] = result;
8880 if setflags then
8881 APSR.N = result<31>;
8882 APSR.Z = IsZeroBit(result);
8883 APSR.C = carry;
8884 APSR.V = overflow;
8885#endif
8886
8887 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008888
8889 uint32_t Rd; // the destination register
8890 uint32_t Rn; // the first operand
8891 uint32_t Rm; // the second operand
8892 bool setflags;
8893 ARM_ShifterType shift_t;
8894 uint32_t shift_n; // the shift applied to the value read from Rm
8895 switch (encoding) {
8896 case eEncodingT1:
8897 Rd = Rn = Bits32(opcode, 2, 0);
8898 Rm = Bits32(opcode, 5, 3);
8899 setflags = !InITBlock();
8900 shift_t = SRType_LSL;
8901 shift_n = 0;
8902 break;
8903 case eEncodingT2:
8904 Rd = Bits32(opcode, 11, 8);
8905 Rn = Bits32(opcode, 19, 16);
8906 Rm = Bits32(opcode, 3, 0);
8907 setflags = BitIsSet(opcode, 20);
8908 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8909 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8910 return false;
8911 break;
8912 case eEncodingA1:
8913 Rd = Bits32(opcode, 15, 12);
8914 Rn = Bits32(opcode, 19, 16);
8915 Rm = Bits32(opcode, 3, 0);
8916 setflags = BitIsSet(opcode, 20);
8917 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008918
Johnny Chen9b381772011-02-23 01:01:21 +00008919 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008920 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008921 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008922 break;
8923 default:
8924 return false;
8925 }
8926 // Read the register value from register Rn.
8927 uint32_t val1 = ReadCoreReg(Rn, &success);
8928 if (!success)
8929 return false;
8930
8931 // Read the register value from register Rm.
8932 uint32_t val2 = ReadCoreReg(Rm, &success);
8933 if (!success)
8934 return false;
8935
Johnny Chena4438a72011-06-02 22:50:51 +00008936 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8937 if (!success)
8938 return false;
Johnny Chen9b381772011-02-23 01:01:21 +00008939 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8940
8941 EmulateInstruction::Context context;
8942 context.type = EmulateInstruction::eContextImmediate;
8943 context.SetNoArgs();
8944 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8945 return false;
8946
8947 return true;
8948}
8949
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008950// This instruction subtracts an immediate value from a register value, and writes the result
8951// to the destination register. It can optionally update the condition flags based on the result.
8952bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008953EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008954{
8955#if 0
8956 // ARM pseudo code...
8957 if ConditionPassed() then
8958 EncodingSpecificOperations();
8959 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8960 R[d] = result;
8961 if setflags then
8962 APSR.N = result<31>;
8963 APSR.Z = IsZeroBit(result);
8964 APSR.C = carry;
8965 APSR.V = overflow;
8966#endif
8967
8968 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008969
8970 uint32_t Rd; // the destination register
8971 uint32_t Rn; // the first operand
8972 bool setflags;
8973 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8974 switch (encoding) {
8975 case eEncodingT1:
8976 Rd = Bits32(opcode, 2, 0);
8977 Rn = Bits32(opcode, 5, 3);
8978 setflags = !InITBlock();
8979 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8980 break;
8981 case eEncodingT2:
8982 Rd = Rn = Bits32(opcode, 10, 8);
8983 setflags = !InITBlock();
8984 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8985 break;
8986 case eEncodingT3:
8987 Rd = Bits32(opcode, 11, 8);
8988 Rn = Bits32(opcode, 19, 16);
8989 setflags = BitIsSet(opcode, 20);
8990 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8991
8992 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8993 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008994 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008995
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008996 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008997 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008998 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008999
9000 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9001 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9002 return false;
9003 break;
9004 case eEncodingT4:
9005 Rd = Bits32(opcode, 11, 8);
9006 Rn = Bits32(opcode, 19, 16);
9007 setflags = BitIsSet(opcode, 20);
9008 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9009
9010 // if Rn == '1111' then SEE ADR;
9011 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00009012 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009013
9014 // if Rn == '1101' then SEE SUB (SP minus immediate);
9015 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009016 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009017
9018 if (BadReg(Rd))
9019 return false;
9020 break;
9021 default:
9022 return false;
9023 }
9024 // Read the register value from the operand register Rn.
9025 uint32_t reg_val = ReadCoreReg(Rn, &success);
9026 if (!success)
9027 return false;
9028
9029 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9030
9031 EmulateInstruction::Context context;
9032 context.type = EmulateInstruction::eContextImmediate;
9033 context.SetNoArgs ();
9034
9035 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9036 return false;
9037
9038 return true;
9039}
9040
9041// This instruction subtracts an immediate value from a register value, and writes the result
9042// to the destination register. It can optionally update the condition flags based on the result.
9043bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009044EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009045{
9046#if 0
9047 // ARM pseudo code...
9048 if ConditionPassed() then
9049 EncodingSpecificOperations();
9050 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9051 if d == 15 then
9052 ALUWritePC(result); // setflags is always FALSE here
9053 else
9054 R[d] = result;
9055 if setflags then
9056 APSR.N = result<31>;
9057 APSR.Z = IsZeroBit(result);
9058 APSR.C = carry;
9059 APSR.V = overflow;
9060#endif
9061
9062 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009063
9064 uint32_t Rd; // the destination register
9065 uint32_t Rn; // the first operand
9066 bool setflags;
9067 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9068 switch (encoding) {
9069 case eEncodingA1:
9070 Rd = Bits32(opcode, 15, 12);
9071 Rn = Bits32(opcode, 19, 16);
9072 setflags = BitIsSet(opcode, 20);
9073 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9074
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009075 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009076 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00009077 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009078
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009079 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009080 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009081 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009082
9083 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009084 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00009085 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009086 break;
9087 default:
9088 return false;
9089 }
9090 // Read the register value from the operand register Rn.
9091 uint32_t reg_val = ReadCoreReg(Rn, &success);
9092 if (!success)
9093 return false;
9094
9095 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9096
9097 EmulateInstruction::Context context;
9098 context.type = EmulateInstruction::eContextImmediate;
9099 context.SetNoArgs ();
9100
9101 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9102 return false;
9103
9104 return true;
9105}
9106
Johnny Chen2115b412011-02-21 23:42:44 +00009107// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9108// immediate value. It updates the condition flags based on the result, and discards the result.
9109bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009110EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009111{
9112#if 0
9113 // ARM pseudo code...
9114 if ConditionPassed() then
9115 EncodingSpecificOperations();
9116 result = R[n] EOR imm32;
9117 APSR.N = result<31>;
9118 APSR.Z = IsZeroBit(result);
9119 APSR.C = carry;
9120 // APSR.V unchanged
9121#endif
9122
9123 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009124
Greg Clayton7bc39082011-03-24 23:53:38 +00009125 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009126 {
9127 uint32_t Rn;
9128 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9129 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9130 switch (encoding)
9131 {
9132 case eEncodingT1:
9133 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009134 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009135 if (BadReg(Rn))
9136 return false;
9137 break;
9138 case eEncodingA1:
9139 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009140 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009141 break;
9142 default:
9143 return false;
9144 }
9145
9146 // Read the first operand.
9147 uint32_t val1 = ReadCoreReg(Rn, &success);
9148 if (!success)
9149 return false;
9150
9151 uint32_t result = val1 ^ imm32;
9152
9153 EmulateInstruction::Context context;
9154 context.type = EmulateInstruction::eContextImmediate;
9155 context.SetNoArgs ();
9156
9157 if (!WriteFlags(context, result, carry))
9158 return false;
9159 }
9160 return true;
9161}
9162
9163// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9164// optionally-shifted register value. It updates the condition flags based on the result, and discards
9165// the result.
9166bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009167EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009168{
9169#if 0
9170 // ARM pseudo code...
9171 if ConditionPassed() then
9172 EncodingSpecificOperations();
9173 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9174 result = R[n] EOR shifted;
9175 APSR.N = result<31>;
9176 APSR.Z = IsZeroBit(result);
9177 APSR.C = carry;
9178 // APSR.V unchanged
9179#endif
9180
9181 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009182
Greg Clayton7bc39082011-03-24 23:53:38 +00009183 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009184 {
9185 uint32_t Rn, Rm;
9186 ARM_ShifterType shift_t;
9187 uint32_t shift_n; // the shift applied to the value read from Rm
9188 uint32_t carry;
9189 switch (encoding)
9190 {
9191 case eEncodingT1:
9192 Rn = Bits32(opcode, 19, 16);
9193 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009194 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009195 if (BadReg(Rn) || BadReg(Rm))
9196 return false;
9197 break;
9198 case eEncodingA1:
9199 Rn = Bits32(opcode, 19, 16);
9200 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009201 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009202 break;
9203 default:
9204 return false;
9205 }
9206
9207 // Read the first operand.
9208 uint32_t val1 = ReadCoreReg(Rn, &success);
9209 if (!success)
9210 return false;
9211
9212 // Read the second operand.
9213 uint32_t val2 = ReadCoreReg(Rm, &success);
9214 if (!success)
9215 return false;
9216
Johnny Chena4438a72011-06-02 22:50:51 +00009217 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9218 if (!success)
9219 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00009220 uint32_t result = val1 ^ shifted;
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
Johnny Chende3cce32011-02-21 21:24:49 +00009232// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9233// It updates the condition flags based on the result, and discards the result.
9234bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009235EmulateInstructionARM::EmulateTSTImm (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 result = R[n] AND imm32;
9242 APSR.N = result<31>;
9243 APSR.Z = IsZeroBit(result);
9244 APSR.C = carry;
9245 // APSR.V unchanged
9246#endif
9247
9248 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009249
Greg Clayton7bc39082011-03-24 23:53:38 +00009250 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009251 {
9252 uint32_t Rn;
9253 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9254 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9255 switch (encoding)
9256 {
9257 case eEncodingT1:
9258 Rn = Bits32(opcode, 19, 16);
9259 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9260 if (BadReg(Rn))
9261 return false;
9262 break;
9263 case eEncodingA1:
9264 Rn = Bits32(opcode, 19, 16);
9265 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9266 break;
9267 default:
9268 return false;
9269 }
9270
9271 // Read the first operand.
9272 uint32_t val1 = ReadCoreReg(Rn, &success);
9273 if (!success)
9274 return false;
9275
9276 uint32_t result = val1 & imm32;
9277
9278 EmulateInstruction::Context context;
9279 context.type = EmulateInstruction::eContextImmediate;
9280 context.SetNoArgs ();
9281
9282 if (!WriteFlags(context, result, carry))
9283 return false;
9284 }
9285 return true;
9286}
9287
9288// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9289// It updates the condition flags based on the result, and discards the result.
9290bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009291EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009292{
9293#if 0
9294 // ARM pseudo code...
9295 if ConditionPassed() then
9296 EncodingSpecificOperations();
9297 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9298 result = R[n] AND shifted;
9299 APSR.N = result<31>;
9300 APSR.Z = IsZeroBit(result);
9301 APSR.C = carry;
9302 // APSR.V unchanged
9303#endif
9304
9305 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009306
Greg Clayton7bc39082011-03-24 23:53:38 +00009307 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009308 {
9309 uint32_t Rn, Rm;
9310 ARM_ShifterType shift_t;
9311 uint32_t shift_n; // the shift applied to the value read from Rm
9312 uint32_t carry;
9313 switch (encoding)
9314 {
9315 case eEncodingT1:
9316 Rn = Bits32(opcode, 2, 0);
9317 Rm = Bits32(opcode, 5, 3);
9318 shift_t = SRType_LSL;
9319 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009320 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009321 case eEncodingT2:
9322 Rn = Bits32(opcode, 19, 16);
9323 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009324 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009325 if (BadReg(Rn) || BadReg(Rm))
9326 return false;
9327 break;
9328 case eEncodingA1:
9329 Rn = Bits32(opcode, 19, 16);
9330 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009331 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009332 break;
9333 default:
9334 return false;
9335 }
9336
9337 // Read the first operand.
9338 uint32_t val1 = ReadCoreReg(Rn, &success);
9339 if (!success)
9340 return false;
9341
9342 // Read the second operand.
9343 uint32_t val2 = ReadCoreReg(Rm, &success);
9344 if (!success)
9345 return false;
9346
Johnny Chena4438a72011-06-02 22:50:51 +00009347 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9348 if (!success)
9349 return false;
Johnny Chende3cce32011-02-21 21:24:49 +00009350 uint32_t result = val1 & shifted;
9351
9352 EmulateInstruction::Context context;
9353 context.type = EmulateInstruction::eContextImmediate;
9354 context.SetNoArgs ();
9355
9356 if (!WriteFlags(context, result, carry))
9357 return false;
9358 }
9359 return true;
9360}
Caroline Ticed05b4902011-03-29 21:24:06 +00009361
9362// A8.6.216 SUB (SP minus register)
9363bool
9364EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9365{
9366#if 0
9367 if ConditionPassed() then
9368 EncodingSpecificOperations();
9369 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009370 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009371 if d == 15 then // Can only occur for ARM encoding
9372 ALUWritePC(result); // setflags is always FALSE here
9373 else
9374 R[d] = result;
9375 if setflags then
9376 APSR.N = result<31>;
9377 APSR.Z = IsZeroBit(result);
9378 APSR.C = carry;
9379 APSR.V = overflow;
9380#endif
9381
9382 bool success = false;
9383
9384 if (ConditionPassed(opcode))
9385 {
9386 uint32_t d;
9387 uint32_t m;
9388 bool setflags;
9389 ARM_ShifterType shift_t;
9390 uint32_t shift_n;
9391
9392 switch (encoding)
9393 {
9394 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009395 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009396 d = Bits32 (opcode, 11, 8);
9397 m = Bits32 (opcode, 3, 0);
9398 setflags = BitIsSet (opcode, 20);
9399
9400 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9401 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9402
9403 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9404 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9405 return false;
9406
9407 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9408 if ((d == 15) || BadReg (m))
9409 return false;
9410 break;
9411
9412 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009413 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009414 d = Bits32 (opcode, 15, 12);
9415 m = Bits32 (opcode, 3, 0);
9416 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009417
Greg Clayton061b79d2011-05-09 20:18:18 +00009418 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009419 if (d == 15 && setflags)
9420 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009421
9422 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9423 shift_n = DecodeImmShiftARM (opcode, shift_t);
9424 break;
9425
9426 default:
9427 return false;
9428 }
9429
9430 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9431 uint32_t Rm = ReadCoreReg (m, &success);
9432 if (!success)
9433 return false;
9434
Johnny Chena4438a72011-06-02 22:50:51 +00009435 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9436 if (!success)
9437 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009438
Greg Clayton061b79d2011-05-09 20:18:18 +00009439 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009440 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9441 if (!success)
9442 return false;
9443
9444 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9445
9446 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009447 context.type = eContextArithmetic;
9448 RegisterInfo sp_reg;
9449 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9450 RegisterInfo dwarf_reg;
9451 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +00009452 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9453
Caroline Ticeef440002011-03-30 05:40:56 +00009454 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009455 return false;
9456 }
9457 return true;
9458}
9459
9460
9461// A8.6.7 ADD (register-shifted register)
9462bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009463EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009464{
9465#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009466 if ConditionPassed() then
9467 EncodingSpecificOperations();
9468 shift_n = UInt(R[s]<7:0>);
9469 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009470 (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009471 R[d] = result;
9472 if setflags then
9473 APSR.N = result<31>;
9474 APSR.Z = IsZeroBit(result);
9475 APSR.C = carry;
9476 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009477#endif
9478
Caroline Ticec08ed382011-03-29 23:03:16 +00009479 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009480
9481 if (ConditionPassed(opcode))
9482 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009483 uint32_t d;
9484 uint32_t n;
9485 uint32_t m;
9486 uint32_t s;
9487 bool setflags;
9488 ARM_ShifterType shift_t;
9489
Caroline Ticed05b4902011-03-29 21:24:06 +00009490 switch (encoding)
9491 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009492 case eEncodingA1:
9493 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9494 d = Bits32 (opcode, 15, 12);
9495 n = Bits32 (opcode, 19, 16);
9496 m = Bits32 (opcode, 3, 0);
9497 s = Bits32 (opcode, 11, 8);
9498
Greg Clayton061b79d2011-05-09 20:18:18 +00009499 // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
Caroline Ticec08ed382011-03-29 23:03:16 +00009500 setflags = BitIsSet (opcode, 20);
9501 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9502
9503 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9504 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9505 return false;
9506 break;
9507
9508 default:
9509 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009510 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009511
9512 // shift_n = UInt(R[s]<7:0>);
9513 uint32_t Rs = ReadCoreReg (s, &success);
9514 if (!success)
9515 return false;
9516
9517 uint32_t shift_n = Bits32 (Rs, 7, 0);
9518
9519 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9520 uint32_t Rm = ReadCoreReg (m, &success);
9521 if (!success)
9522 return false;
9523
Johnny Chena4438a72011-06-02 22:50:51 +00009524 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9525 if (!success)
9526 return false;
9527
Greg Clayton061b79d2011-05-09 20:18:18 +00009528 // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009529 uint32_t Rn = ReadCoreReg (n, &success);
9530 if (!success)
9531 return false;
9532
9533 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9534
9535 // R[d] = result;
9536 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009537 context.type = eContextArithmetic;
9538 RegisterInfo reg_n;
9539 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9540 RegisterInfo reg_m;
9541 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009542
9543 context.SetRegisterRegisterOperands (reg_n, reg_m);
9544
9545 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9546 return false;
9547
9548 // if setflags then
9549 // APSR.N = result<31>;
9550 // APSR.Z = IsZeroBit(result);
9551 // APSR.C = carry;
9552 // APSR.V = overflow;
9553 if (setflags)
9554 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009555 }
9556 return true;
9557}
9558
9559// A8.6.213 SUB (register)
9560bool
9561EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9562{
9563#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009564 if ConditionPassed() then
9565 EncodingSpecificOperations();
9566 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009567 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009568 if d == 15 then // Can only occur for ARM encoding
9569 ALUWritePC(result); // setflags is always FALSE here
9570 else
9571 R[d] = result;
9572 if setflags then
9573 APSR.N = result<31>;
9574 APSR.Z = IsZeroBit(result);
9575 APSR.C = carry;
9576 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009577#endif
9578
Caroline Tice4cccd532011-03-29 23:44:20 +00009579 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009580
9581 if (ConditionPassed(opcode))
9582 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009583 uint32_t d;
9584 uint32_t n;
9585 uint32_t m;
9586 bool setflags;
9587 ARM_ShifterType shift_t;
9588 uint32_t shift_n;
9589
Caroline Ticed05b4902011-03-29 21:24:06 +00009590 switch (encoding)
9591 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009592 case eEncodingT1:
9593 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9594 d = Bits32 (opcode, 2, 0);
9595 n = Bits32 (opcode, 5, 3);
9596 m = Bits32 (opcode, 8, 6);
9597 setflags = !InITBlock();
9598
9599 // (shift_t, shift_n) = (SRType_LSL, 0);
9600 shift_t = SRType_LSL;
9601 shift_n = 0;
9602
9603 break;
9604
9605 case eEncodingT2:
Greg Clayton061b79d2011-05-09 20:18:18 +00009606 // if Rd == Ô1111Õ && S == Ô1Õ then SEE CMP (register);
9607 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9608 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009609 d = Bits32 (opcode, 11, 8);
9610 n = Bits32 (opcode, 19, 16);
9611 m = Bits32 (opcode, 3, 0);
9612 setflags = BitIsSet (opcode, 20);
9613
9614 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9615 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9616
9617 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9618 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9619 return false;
9620
9621 break;
9622
9623 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009624 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9625 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009626 d = Bits32 (opcode, 15, 12);
9627 n = Bits32 (opcode, 19, 16);
9628 m = Bits32 (opcode, 3, 0);
9629 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009630
Greg Clayton061b79d2011-05-09 20:18:18 +00009631 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009632 if ((d == 15) && setflags)
9633 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009634
9635 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9636 shift_n = DecodeImmShiftARM (opcode, shift_t);
9637
9638 break;
9639
9640 default:
9641 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009642 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009643
9644 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9645 uint32_t Rm = ReadCoreReg (m, &success);
9646 if (!success)
9647 return false;
9648
Johnny Chena4438a72011-06-02 22:50:51 +00009649 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9650 if (!success)
9651 return false;
Caroline Tice4cccd532011-03-29 23:44:20 +00009652
Greg Clayton061b79d2011-05-09 20:18:18 +00009653 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009654 uint32_t Rn = ReadCoreReg (n, &success);
9655 if (!success)
9656 return false;
9657
9658 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9659
9660 // if d == 15 then // Can only occur for ARM encoding
9661 // ALUWritePC(result); // setflags is always FALSE here
9662 // else
9663 // R[d] = result;
9664 // if setflags then
9665 // APSR.N = result<31>;
9666 // APSR.Z = IsZeroBit(result);
9667 // APSR.C = carry;
9668 // APSR.V = overflow;
9669
9670 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009671 context.type = eContextArithmetic;
9672 RegisterInfo reg_n;
9673 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9674 RegisterInfo reg_m;
9675 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009676 context.SetRegisterRegisterOperands (reg_n, reg_m);
9677
Caroline Ticeef440002011-03-30 05:40:56 +00009678 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009679 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009680 }
9681 return true;
9682}
Caroline Tice4cccd532011-03-29 23:44:20 +00009683
Caroline Ticed05b4902011-03-29 21:24:06 +00009684// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009685// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9686// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009687bool
9688EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9689{
9690#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009691 if ConditionPassed() then
9692 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9693 address = R[n] + imm32;
9694 if ExclusiveMonitorsPass(address,4) then
9695 MemA[address,4] = R[t];
9696 R[d] = 0;
9697 else
9698 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009699#endif
9700
Caroline Tice5168b6c2011-03-30 05:15:46 +00009701 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009702
9703 if (ConditionPassed(opcode))
9704 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009705 uint32_t d;
9706 uint32_t t;
9707 uint32_t n;
9708 uint32_t imm32;
9709 const uint32_t addr_byte_size = GetAddressByteSize();
9710
Caroline Ticed05b4902011-03-29 21:24:06 +00009711 switch (encoding)
9712 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009713 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009714 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009715 d = Bits32 (opcode, 11, 8);
9716 t = Bits32 (opcode, 15, 12);
9717 n = Bits32 (opcode, 19, 16);
9718 imm32 = Bits32 (opcode, 7, 0) << 2;
9719
9720 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9721 if (BadReg (d) || BadReg (t) || (n == 15))
9722 return false;
9723
9724 // if d == n || d == t then UNPREDICTABLE;
9725 if ((d == n) || (d == t))
9726 return false;
9727
9728 break;
9729
9730 case eEncodingA1:
9731 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9732 d = Bits32 (opcode, 15, 12);
9733 t = Bits32 (opcode, 3, 0);
9734 n = Bits32 (opcode, 19, 16);
9735 imm32 = 0;
9736
9737 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9738 if ((d == 15) || (t == 15) || (n == 15))
9739 return false;
9740
9741 // if d == n || d == t then UNPREDICTABLE;
9742 if ((d == n) || (d == t))
9743 return false;
9744
9745 break;
9746
9747 default:
9748 return false;
9749 }
9750
9751 // address = R[n] + imm32;
9752 uint32_t Rn = ReadCoreReg (n, &success);
9753 if (!success)
9754 return false;
9755
9756 addr_t address = Rn + imm32;
9757
Greg Claytonc07d4512011-04-26 23:48:45 +00009758 RegisterInfo base_reg;
9759 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9760 RegisterInfo data_reg;
9761 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009762 EmulateInstruction::Context context;
9763 context.type = eContextRegisterStore;
9764 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9765
9766 // if ExclusiveMonitorsPass(address,4) then
9767 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9768 // always return true.
9769 if (true)
9770 {
9771 // MemA[address,4] = R[t];
9772 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9773 if (!success)
9774 return false;
9775
9776 if (!MemAWrite (context, address, Rt, addr_byte_size))
9777 return false;
9778
9779 // R[d] = 0;
9780 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9781 return false;
9782 }
9783 else
9784 {
9785 // R[d] = 1;
9786 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9787 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009788 }
9789 }
9790 return true;
9791}
9792
9793// A8.6.197 STRB (immediate, ARM)
9794bool
9795EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9796{
9797#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009798 if ConditionPassed() then
9799 EncodingSpecificOperations();
9800 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9801 address = if index then offset_addr else R[n];
9802 MemU[address,1] = R[t]<7:0>;
9803 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009804#endif
9805
Caroline Ticeef440002011-03-30 05:40:56 +00009806 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009807
9808 if (ConditionPassed(opcode))
9809 {
Caroline Ticeef440002011-03-30 05:40:56 +00009810 uint32_t t;
9811 uint32_t n;
9812 uint32_t imm32;
9813 bool index;
9814 bool add;
9815 bool wback;
9816
Caroline Ticed05b4902011-03-29 21:24:06 +00009817 switch (encoding)
9818 {
Caroline Ticeef440002011-03-30 05:40:56 +00009819 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009820 // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
Caroline Ticeef440002011-03-30 05:40:56 +00009821 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9822 t = Bits32 (opcode, 15, 12);
9823 n = Bits32 (opcode, 19, 16);
9824 imm32 = Bits32 (opcode, 11, 0);
9825
Greg Clayton061b79d2011-05-09 20:18:18 +00009826 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeef440002011-03-30 05:40:56 +00009827 index = BitIsSet (opcode, 24);
9828 add = BitIsSet (opcode, 23);
9829 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9830
9831 // if t == 15 then UNPREDICTABLE;
9832 if (t == 15)
9833 return false;
9834
9835 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9836 if (wback && ((n == 15) || (n == t)))
9837 return false;
9838
9839 break;
9840
9841 default:
9842 return false;
9843 }
9844
9845 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9846 uint32_t Rn = ReadCoreReg (n, &success);
9847 if (!success)
9848 return false;
9849
9850 addr_t offset_addr;
9851 if (add)
9852 offset_addr = Rn + imm32;
9853 else
9854 offset_addr = Rn - imm32;
9855
9856 // address = if index then offset_addr else R[n];
9857 addr_t address;
9858 if (index)
9859 address = offset_addr;
9860 else
9861 address = Rn;
9862
9863 // MemU[address,1] = R[t]<7:0>;
9864 uint32_t Rt = ReadCoreReg (t, &success);
9865 if (!success)
9866 return false;
9867
Greg Claytonc07d4512011-04-26 23:48:45 +00009868 RegisterInfo base_reg;
9869 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9870 RegisterInfo data_reg;
9871 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticeef440002011-03-30 05:40:56 +00009872 EmulateInstruction::Context context;
9873 context.type = eContextRegisterStore;
9874 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9875
9876 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9877 return false;
9878
9879 // if wback then R[n] = offset_addr;
9880 if (wback)
9881 {
Caroline Tice523c5542011-04-13 00:42:12 +00009882 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009883 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009884 }
9885 }
9886 return true;
9887}
9888
9889// A8.6.194 STR (immediate, ARM)
9890bool
9891EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9892{
9893#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009894 if ConditionPassed() then
9895 EncodingSpecificOperations();
9896 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9897 address = if index then offset_addr else R[n];
9898 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9899 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009900#endif
9901
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009902 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009903
9904 if (ConditionPassed(opcode))
9905 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009906 uint32_t t;
9907 uint32_t n;
9908 uint32_t imm32;
9909 bool index;
9910 bool add;
9911 bool wback;
9912
9913 const uint32_t addr_byte_size = GetAddressByteSize();
9914
Caroline Ticed05b4902011-03-29 21:24:06 +00009915 switch (encoding)
9916 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009917 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009918 // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
9919 // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009920 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9921 t = Bits32 (opcode, 15, 12);
9922 n = Bits32 (opcode, 19, 16);
9923 imm32 = Bits32 (opcode, 11, 0);
9924
Greg Clayton061b79d2011-05-09 20:18:18 +00009925 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009926 index = BitIsSet (opcode, 24);
9927 add = BitIsSet (opcode, 23);
9928 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9929
9930 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9931 if (wback && ((n == 15) || (n == t)))
9932 return false;
9933
9934 break;
9935
9936 default:
9937 return false;
9938 }
9939
9940 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9941 uint32_t Rn = ReadCoreReg (n, &success);
9942 if (!success)
9943 return false;
9944
9945 addr_t offset_addr;
9946 if (add)
9947 offset_addr = Rn + imm32;
9948 else
9949 offset_addr = Rn - imm32;
9950
9951 // address = if index then offset_addr else R[n];
9952 addr_t address;
9953 if (index)
9954 address = offset_addr;
9955 else
9956 address = Rn;
9957
Greg Claytonc07d4512011-04-26 23:48:45 +00009958 RegisterInfo base_reg;
9959 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9960 RegisterInfo data_reg;
9961 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009962 EmulateInstruction::Context context;
9963 context.type = eContextRegisterStore;
9964 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9965
9966 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9967 uint32_t Rt = ReadCoreReg (t, &success);
9968 if (!success)
9969 return false;
9970
9971 if (t == 15)
9972 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009973 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009974 if (!success)
9975 return false;
9976
9977 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9978 return false;
9979 }
9980 else
9981 {
9982 if (!MemUWrite (context, address, Rt, addr_byte_size))
9983 return false;
9984 }
9985
9986 // if wback then R[n] = offset_addr;
9987 if (wback)
9988 {
9989 context.type = eContextAdjustBaseRegister;
9990 context.SetImmediate (offset_addr);
9991
9992 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9993 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009994 }
9995 }
9996 return true;
9997}
9998
Caroline Ticed05b4902011-03-29 21:24:06 +00009999// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +000010000// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
10001// 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 +000010002bool
10003EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
10004{
10005#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +000010006 if ConditionPassed() then
10007 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10008 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10009 address = if index then offset_addr else R[n];
10010 R[t] = MemA[address,4];
10011 R[t2] = MemA[address+4,4];
10012 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010013#endif
10014
Caroline Tice1697dd72011-03-30 17:11:45 +000010015 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010016
10017 if (ConditionPassed(opcode))
10018 {
Caroline Tice1697dd72011-03-30 17:11:45 +000010019 uint32_t t;
10020 uint32_t t2;
10021 uint32_t n;
10022 uint32_t imm32;
10023 bool index;
10024 bool add;
10025 bool wback;
10026
Caroline Ticed05b4902011-03-29 21:24:06 +000010027 switch (encoding)
10028 {
Caroline Tice1697dd72011-03-30 17:11:45 +000010029 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010030 //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10031 //if Rn == Ô1111Õ then SEE LDRD (literal);
10032 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice1697dd72011-03-30 17:11:45 +000010033 t = Bits32 (opcode, 15, 12);
10034 t2 = Bits32 (opcode, 11, 8);
10035 n = Bits32 (opcode, 19, 16);
10036 imm32 = Bits32 (opcode, 7, 0) << 2;
10037
Greg Clayton061b79d2011-05-09 20:18:18 +000010038 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +000010039 index = BitIsSet (opcode, 24);
10040 add = BitIsSet (opcode, 23);
10041 wback = BitIsSet (opcode, 21);
10042
10043 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10044 if (wback && ((n == t) || (n == t2)))
10045 return false;
10046
10047 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10048 if (BadReg (t) || BadReg (t2) || (t == t2))
10049 return false;
10050
10051 break;
10052
10053 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010054 //if Rn == Ô1111Õ then SEE LDRD (literal);
10055 //if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010056 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10057 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010058 if (BitIsSet (t, 0))
10059 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +000010060 t2 = t + 1;
10061 n = Bits32 (opcode, 19, 16);
10062 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10063
Greg Clayton061b79d2011-05-09 20:18:18 +000010064 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +000010065 index = BitIsSet (opcode, 24);
10066 add = BitIsSet (opcode, 23);
10067 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10068
Greg Clayton061b79d2011-05-09 20:18:18 +000010069 //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010070 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10071 return false;
10072
10073 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10074 if (wback && ((n == t) || (n == t2)))
10075 return false;
10076
10077 //if t2 == 15 then UNPREDICTABLE;
10078 if (t2 == 15)
10079 return false;
10080
10081 break;
10082
10083 default:
10084 return false;
10085 }
10086
10087 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10088 uint32_t Rn = ReadCoreReg (n, &success);
10089 if (!success)
10090 return false;
10091
10092 addr_t offset_addr;
10093 if (add)
10094 offset_addr = Rn + imm32;
10095 else
10096 offset_addr = Rn - imm32;
10097
10098 //address = if index then offset_addr else R[n];
10099 addr_t address;
10100 if (index)
10101 address = offset_addr;
10102 else
10103 address = Rn;
10104
10105 //R[t] = MemA[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +000010106 RegisterInfo base_reg;
10107 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1697dd72011-03-30 17:11:45 +000010108
10109 EmulateInstruction::Context context;
10110 context.type = eContextRegisterLoad;
10111 context.SetRegisterPlusOffset (base_reg, address - Rn);
10112
10113 const uint32_t addr_byte_size = GetAddressByteSize();
10114 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10115 if (!success)
10116 return false;
10117
10118 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10119 return false;
10120
10121 //R[t2] = MemA[address+4,4];
10122
10123 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10124 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10125 if (!success)
10126 return false;
10127
10128 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10129 return false;
10130
10131 //if wback then R[n] = offset_addr;
10132 if (wback)
10133 {
10134 context.type = eContextAdjustBaseRegister;
10135 context.SetAddress (offset_addr);
10136
10137 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10138 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010139 }
10140 }
10141 return true;
10142}
10143
Caroline Ticed05b4902011-03-29 21:24:06 +000010144// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010145// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10146// 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 +000010147bool
10148EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10149{
10150#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010151 if ConditionPassed() then
10152 EncodingSpecificOperations();
10153 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10154 address = if index then offset_addr else R[n];
10155 R[t] = MemA[address,4];
10156 R[t2] = MemA[address+4,4];
10157 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010158#endif
10159
Caroline Ticeeab301f2011-03-30 17:54:52 +000010160 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010161
10162 if (ConditionPassed(opcode))
10163 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010164 uint32_t t;
10165 uint32_t t2;
10166 uint32_t n;
10167 uint32_t m;
10168 bool index;
10169 bool add;
10170 bool wback;
10171
Caroline Ticed05b4902011-03-29 21:24:06 +000010172 switch (encoding)
10173 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010174 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010175 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010176 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10177 t = Bits32 (opcode, 15, 12);
10178 if (BitIsSet (t, 0))
10179 return false;
10180 t2 = t + 1;
10181 n = Bits32 (opcode, 19, 16);
10182 m = Bits32 (opcode, 3, 0);
10183
Greg Clayton061b79d2011-05-09 20:18:18 +000010184 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010185 index = BitIsSet (opcode, 24);
10186 add = BitIsSet (opcode, 23);
10187 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10188
Greg Clayton061b79d2011-05-09 20:18:18 +000010189 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010190 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10191 return false;
10192
10193 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10194 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10195 return false;
10196
10197 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10198 if (wback && ((n == 15) || (n == t) || (n == t2)))
10199 return false;
10200
10201 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10202 if ((ArchVersion() < 6) && wback && (m == n))
10203 return false;
10204 break;
10205
10206 default:
10207 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010208 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010209
Caroline Ticeeab301f2011-03-30 17:54:52 +000010210 uint32_t Rn = ReadCoreReg (n, &success);
10211 if (!success)
10212 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010213 RegisterInfo base_reg;
10214 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010215
Caroline Ticeeab301f2011-03-30 17:54:52 +000010216 uint32_t Rm = ReadCoreReg (m, &success);
10217 if (!success)
10218 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010219 RegisterInfo offset_reg;
10220 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010221
Caroline Ticeeab301f2011-03-30 17:54:52 +000010222 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10223 addr_t offset_addr;
10224 if (add)
10225 offset_addr = Rn + Rm;
10226 else
10227 offset_addr = Rn - Rm;
10228
10229 // address = if index then offset_addr else R[n];
10230 addr_t address;
10231 if (index)
10232 address = offset_addr;
10233 else
10234 address = Rn;
10235
10236 EmulateInstruction::Context context;
10237 context.type = eContextRegisterLoad;
10238 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10239
10240 // R[t] = MemA[address,4];
10241 const uint32_t addr_byte_size = GetAddressByteSize();
10242 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10243 if (!success)
10244 return false;
10245
10246 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10247 return false;
10248
10249 // R[t2] = MemA[address+4,4];
10250
10251 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10252 if (!success)
10253 return false;
10254
10255 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10256 return false;
10257
10258 // if wback then R[n] = offset_addr;
10259 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010260 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010261 context.type = eContextAdjustBaseRegister;
10262 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010263
Caroline Ticeeab301f2011-03-30 17:54:52 +000010264 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10265 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010266 }
10267 }
10268 return true;
10269}
Caroline Ticed05b4902011-03-29 21:24:06 +000010270
10271// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010272// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10273// 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 +000010274bool
10275EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10276{
10277#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010278 if ConditionPassed() then
10279 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10280 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10281 address = if index then offset_addr else R[n];
10282 MemA[address,4] = R[t];
10283 MemA[address+4,4] = R[t2];
10284 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010285#endif
10286
Caroline Tice74467fe2011-03-30 19:02:56 +000010287 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010288
Caroline Tice74467fe2011-03-30 19:02:56 +000010289 if (ConditionPassed(opcode))
10290 {
10291 uint32_t t;
10292 uint32_t t2;
10293 uint32_t n;
10294 uint32_t imm32;
10295 bool index;
10296 bool add;
10297 bool wback;
10298
10299 switch (encoding)
10300 {
10301 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010302 // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10303 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice74467fe2011-03-30 19:02:56 +000010304 t = Bits32 (opcode, 15, 12);
10305 t2 = Bits32 (opcode, 11, 8);
10306 n = Bits32 (opcode, 19, 16);
10307 imm32 = Bits32 (opcode, 7, 0) << 2;
10308
Greg Clayton061b79d2011-05-09 20:18:18 +000010309 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010310 index = BitIsSet (opcode, 24);
10311 add = BitIsSet (opcode, 23);
10312 wback = BitIsSet (opcode, 21);
10313
10314 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10315 if (wback && ((n == t) || (n == t2)))
10316 return false;
10317
10318 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10319 if ((n == 15) || BadReg (t) || BadReg (t2))
10320 return false;
10321
10322 break;
10323
10324 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010325 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010326 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10327 t = Bits32 (opcode, 15, 12);
10328 if (BitIsSet (t, 0))
10329 return false;
10330
10331 t2 = t + 1;
10332 n = Bits32 (opcode, 19, 16);
10333 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10334
Greg Clayton061b79d2011-05-09 20:18:18 +000010335 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010336 index = BitIsSet (opcode, 24);
10337 add = BitIsSet (opcode, 23);
10338 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10339
Greg Clayton061b79d2011-05-09 20:18:18 +000010340 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010341 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10342 return false;
10343
10344 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10345 if (wback && ((n == 15) || (n == t) || (n == t2)))
10346 return false;
10347
10348 // if t2 == 15 then UNPREDICTABLE;
10349 if (t2 == 15)
10350 return false;
10351
10352 break;
10353
10354 default:
10355 return false;
10356 }
10357
Greg Claytonc07d4512011-04-26 23:48:45 +000010358 RegisterInfo base_reg;
10359 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010360
10361 uint32_t Rn = ReadCoreReg (n, &success);
10362 if (!success)
10363 return false;
10364
10365 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10366 addr_t offset_addr;
10367 if (add)
10368 offset_addr = Rn + imm32;
10369 else
10370 offset_addr = Rn - imm32;
10371
10372 //address = if index then offset_addr else R[n];
10373 addr_t address;
10374 if (index)
10375 address = offset_addr;
10376 else
10377 address = Rn;
10378
10379 //MemA[address,4] = R[t];
Greg Claytonc07d4512011-04-26 23:48:45 +000010380 RegisterInfo data_reg;
10381 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010382
10383 uint32_t data = ReadCoreReg (t, &success);
10384 if (!success)
10385 return false;
10386
10387 EmulateInstruction::Context context;
10388 context.type = eContextRegisterStore;
10389 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10390
10391 const uint32_t addr_byte_size = GetAddressByteSize();
10392
10393 if (!MemAWrite (context, address, data, addr_byte_size))
10394 return false;
10395
10396 //MemA[address+4,4] = R[t2];
Greg Claytonc07d4512011-04-26 23:48:45 +000010397 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010398 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10399
10400 data = ReadCoreReg (t2, &success);
10401 if (!success)
10402 return false;
10403
10404 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10405 return false;
10406
10407 //if wback then R[n] = offset_addr;
10408 if (wback)
10409 {
10410 context.type = eContextAdjustBaseRegister;
10411 context.SetAddress (offset_addr);
10412
10413 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10414 return false;
10415 }
10416 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010417 return true;
10418}
10419
10420
10421// A8.6.201 STRD (register)
10422bool
10423EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10424{
10425#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010426 if ConditionPassed() then
10427 EncodingSpecificOperations();
10428 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10429 address = if index then offset_addr else R[n];
10430 MemA[address,4] = R[t];
10431 MemA[address+4,4] = R[t2];
10432 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010433#endif
10434
Caroline Tice74467fe2011-03-30 19:02:56 +000010435 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010436
Caroline Tice74467fe2011-03-30 19:02:56 +000010437 if (ConditionPassed(opcode))
10438 {
10439 uint32_t t;
10440 uint32_t t2;
10441 uint32_t n;
10442 uint32_t m;
10443 bool index;
10444 bool add;
10445 bool wback;
10446
10447 switch (encoding)
10448 {
10449 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010450 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010451 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10452 t = Bits32 (opcode, 15, 12);
10453 if (BitIsSet (t, 0))
10454 return false;
10455
10456 t2 = t+1;
10457 n = Bits32 (opcode, 19, 16);
10458 m = Bits32 (opcode, 3, 0);
10459
Greg Clayton061b79d2011-05-09 20:18:18 +000010460 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010461 index = BitIsSet (opcode, 24);
10462 add = BitIsSet (opcode, 23);
10463 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10464
Greg Clayton061b79d2011-05-09 20:18:18 +000010465 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010466 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10467 return false;
10468
10469 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10470 if ((t2 == 15) || (m == 15))
10471 return false;
10472
10473 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10474 if (wback && ((n == 15) || (n == t) || (n == t2)))
10475 return false;
10476
10477 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010478 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010479 return false;
10480
10481 break;
10482
10483 default:
10484 return false;
10485 }
10486
Greg Claytonc07d4512011-04-26 23:48:45 +000010487 RegisterInfo base_reg;
10488 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10489 RegisterInfo offset_reg;
10490 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10491 RegisterInfo data_reg;
Caroline Tice74467fe2011-03-30 19:02:56 +000010492
10493 uint32_t Rn = ReadCoreReg (n, &success);
10494 if (!success)
10495 return false;
10496
10497 uint32_t Rm = ReadCoreReg (m, &success);
10498 if (!success)
10499 return false;
10500
10501 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10502 addr_t offset_addr;
10503 if (add)
10504 offset_addr = Rn + Rm;
10505 else
10506 offset_addr = Rn - Rm;
10507
10508 // address = if index then offset_addr else R[n];
10509 addr_t address;
10510 if (index)
10511 address = offset_addr;
10512 else
10513 address = Rn;
10514 // MemA[address,4] = R[t];
10515 uint32_t Rt = ReadCoreReg (t, &success);
10516 if (!success)
10517 return false;
10518
10519 EmulateInstruction::Context context;
10520 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +000010521 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010522 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10523
10524 const uint32_t addr_byte_size = GetAddressByteSize();
10525
10526 if (!MemAWrite (context, address, Rt, addr_byte_size))
10527 return false;
10528
10529 // MemA[address+4,4] = R[t2];
10530 uint32_t Rt2 = ReadCoreReg (t2, &success);
10531 if (!success)
10532 return false;
10533
Greg Claytonc07d4512011-04-26 23:48:45 +000010534 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010535
10536 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10537
10538 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10539 return false;
10540
10541 // if wback then R[n] = offset_addr;
10542 if (wback)
10543 {
10544 context.type = eContextAdjustBaseRegister;
10545 context.SetAddress (offset_addr);
10546
10547 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10548 return false;
10549
10550 }
10551 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010552 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010553}
10554
Caroline Tice4f605582011-03-31 00:02:51 +000010555// A8.6.319 VLDM
10556// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10557// an ARM core register.
10558bool
10559EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10560{
10561#if 0
10562 if ConditionPassed() then
10563 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10564 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010565 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010566 for r = 0 to regs-1
10567 if single_regs then
10568 S[d+r] = MemA[address,4]; address = address+4;
10569 else
10570 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10571 // Combine the word-aligned words in the correct order for current endianness.
10572 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10573#endif
10574
10575 bool success = false;
10576
10577 if (ConditionPassed(opcode))
10578 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010579 bool single_regs;
10580 bool add;
10581 bool wback;
10582 uint32_t d;
10583 uint32_t n;
10584 uint32_t imm32;
10585 uint32_t regs;
10586
Caroline Tice4f605582011-03-31 00:02:51 +000010587 switch (encoding)
10588 {
10589 case eEncodingT1:
10590 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010591 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10592 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10593 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10594 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010595 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10596 return false;
10597
10598 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010599 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice4f605582011-03-31 00:02:51 +000010600 single_regs = false;
10601 add = BitIsSet (opcode, 23);
10602 wback = BitIsSet (opcode, 21);
10603
Greg Clayton061b79d2011-05-09 20:18:18 +000010604 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice4f605582011-03-31 00:02:51 +000010605 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10606 n = Bits32 (opcode, 19, 16);
10607 imm32 = Bits32 (opcode, 7, 0) << 2;
10608
Greg Clayton061b79d2011-05-09 20:18:18 +000010609 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
Caroline Tice4f605582011-03-31 00:02:51 +000010610 regs = Bits32 (opcode, 7, 0) / 2;
10611
10612 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10613 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10614 return false;
10615
10616 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10617 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10618 return false;
10619
10620 break;
10621
10622 case eEncodingT2:
10623 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010624 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10625 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10626 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10627 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010628 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10629 return false;
10630
10631 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010632 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Tice4f605582011-03-31 00:02:51 +000010633 single_regs = true;
10634 add = BitIsSet (opcode, 23);
10635 wback = BitIsSet (opcode, 21);
10636 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10637 n = Bits32 (opcode, 19, 16);
10638
Greg Clayton061b79d2011-05-09 20:18:18 +000010639 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Tice4f605582011-03-31 00:02:51 +000010640 imm32 = Bits32 (opcode, 7, 0) << 2;
10641 regs = Bits32 (opcode, 7, 0);
10642
10643 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10644 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10645 return false;
10646
10647 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10648 if ((regs == 0) || ((d + regs) > 32))
10649 return false;
10650 break;
10651
10652 default:
10653 return false;
10654 }
10655
Greg Claytonc07d4512011-04-26 23:48:45 +000010656 RegisterInfo base_reg;
10657 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4f605582011-03-31 00:02:51 +000010658
10659 uint32_t Rn = ReadCoreReg (n, &success);
10660 if (!success)
10661 return false;
10662
10663 // address = if add then R[n] else R[n]-imm32;
10664 addr_t address;
10665 if (add)
10666 address = Rn;
10667 else
10668 address = Rn - imm32;
10669
Greg Claytonc07d4512011-04-26 23:48:45 +000010670 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010671 EmulateInstruction::Context context;
10672
10673 if (wback)
10674 {
10675 uint32_t value;
10676 if (add)
10677 value = Rn + imm32;
10678 else
10679 value = Rn - imm32;
10680
10681 context.type = eContextAdjustBaseRegister;
10682 context.SetImmediateSigned (value - Rn);
10683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10684 return false;
10685
10686 }
10687
10688 const uint32_t addr_byte_size = GetAddressByteSize();
10689 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10690
10691 context.type = eContextRegisterLoad;
10692
10693 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010694 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010695 {
10696 if (single_regs)
10697 {
10698 // S[d+r] = MemA[address,4]; address = address+4;
10699 context.SetRegisterPlusOffset (base_reg, address - Rn);
10700
10701 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10702 if (!success)
10703 return false;
10704
10705 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10706 return false;
10707
10708 address = address + 4;
10709 }
10710 else
10711 {
10712 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10713 context.SetRegisterPlusOffset (base_reg, address - Rn);
10714 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10715 if (!success)
10716 return false;
10717
10718 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10719 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10720 if (!success)
10721 return false;
10722
10723 address = address + 8;
10724 // // Combine the word-aligned words in the correct order for current endianness.
10725 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10726 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010727 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010728 {
10729 data = word1;
10730 data = (data << 32) | word2;
10731 }
10732 else
10733 {
10734 data = word2;
10735 data = (data << 32) | word1;
10736 }
10737
10738 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10739 return false;
10740 }
10741 }
10742 }
10743 return true;
10744}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010745
10746// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010747// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10748// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010749bool
10750EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10751{
10752#if 0
10753 if ConditionPassed() then
10754 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10755 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010756 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010757 for r = 0 to regs-1
10758 if single_regs then
10759 MemA[address,4] = S[d+r]; address = address+4;
10760 else
10761 // Store as two word-aligned words in the correct order for current endianness.
10762 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10763 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10764 address = address+8;
10765#endif
10766
10767 bool success = false;
10768
10769 if (ConditionPassed (opcode))
10770 {
10771 bool single_regs;
10772 bool add;
10773 bool wback;
10774 uint32_t d;
10775 uint32_t n;
10776 uint32_t imm32;
10777 uint32_t regs;
10778
10779 switch (encoding)
10780 {
10781 case eEncodingT1:
10782 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010783 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10784 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10785 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10786 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010787 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10788 return false;
10789
10790 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010791 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010792 single_regs = false;
10793 add = BitIsSet (opcode, 23);
10794 wback = BitIsSet (opcode, 21);
10795
Greg Clayton061b79d2011-05-09 20:18:18 +000010796 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010797 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10798 n = Bits32 (opcode, 19, 16);
10799 imm32 = Bits32 (opcode, 7, 0) << 2;
10800
Greg Clayton061b79d2011-05-09 20:18:18 +000010801 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010802 regs = Bits32 (opcode, 7, 0) / 2;
10803
10804 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10805 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10806 return false;
10807
10808 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10809 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10810 return false;
10811
10812 break;
10813
10814 case eEncodingT2:
10815 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010816 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10817 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10818 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10819 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010820 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10821 return false;
10822
10823 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010824 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010825 single_regs = true;
10826 add = BitIsSet (opcode, 23);
10827 wback = BitIsSet (opcode, 21);
10828 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10829 n = Bits32 (opcode, 19, 16);
10830
Greg Clayton061b79d2011-05-09 20:18:18 +000010831 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010832 imm32 = Bits32 (opcode, 7, 0) << 2;
10833 regs = Bits32 (opcode, 7, 0);
10834
10835 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10836 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10837 return false;
10838
10839 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10840 if ((regs == 0) || ((d + regs) > 32))
10841 return false;
10842
10843 break;
10844
10845 default:
10846 return false;
10847 }
10848
Greg Claytonc07d4512011-04-26 23:48:45 +000010849 RegisterInfo base_reg;
10850 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010851
10852 uint32_t Rn = ReadCoreReg (n, &success);
10853 if (!success)
10854 return false;
10855
10856 // address = if add then R[n] else R[n]-imm32;
10857 addr_t address;
10858 if (add)
10859 address = Rn;
10860 else
10861 address = Rn - imm32;
10862
10863 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +000010864 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010865 if (wback)
10866 {
10867 uint32_t value;
10868 if (add)
10869 value = Rn + imm32;
10870 else
10871 value = Rn - imm32;
10872
10873 context.type = eContextAdjustBaseRegister;
10874 context.SetRegisterPlusOffset (base_reg, value - Rn);
10875
10876 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10877 return false;
10878 }
10879
10880 const uint32_t addr_byte_size = GetAddressByteSize();
10881 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10882
10883 context.type = eContextRegisterStore;
10884 // for r = 0 to regs-1
10885 for (int r = 0; r < regs; ++r)
10886 {
Greg Claytonc07d4512011-04-26 23:48:45 +000010887
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010888 if (single_regs)
10889 {
10890 // MemA[address,4] = S[d+r]; address = address+4;
10891 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10892 if (!success)
10893 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010894
10895 RegisterInfo data_reg;
10896 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010897 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10898 if (!MemAWrite (context, address, data, addr_byte_size))
10899 return false;
10900
10901 address = address + 4;
10902 }
10903 else
10904 {
10905 // // Store as two word-aligned words in the correct order for current endianness.
10906 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10907 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10908 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10909 if (!success)
10910 return false;
10911
Greg Claytonc07d4512011-04-26 23:48:45 +000010912 RegisterInfo data_reg;
10913 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010914
Greg Clayton888a7332011-04-26 04:39:08 +000010915 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010916 {
10917 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10918 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10919 return false;
10920
10921 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10922 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10923 return false;
10924 }
10925 else
10926 {
10927 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10928 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10929 return false;
10930
10931 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10932 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10933 return false;
10934 }
10935 // address = address+8;
10936 address = address + 8;
10937 }
10938 }
10939 }
10940 return true;
10941}
10942
Caroline Tice917ad352011-03-31 05:05:30 +000010943// A8.6.320
10944// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10945// an optional offset.
10946bool
10947EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10948{
10949#if 0
10950 if ConditionPassed() then
10951 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10952 base = if n == 15 then Align(PC,4) else R[n];
10953 address = if add then (base + imm32) else (base - imm32);
10954 if single_reg then
10955 S[d] = MemA[address,4];
10956 else
10957 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10958 // Combine the word-aligned words in the correct order for current endianness.
10959 D[d] = if BigEndian() then word1:word2 else word2:word1;
10960#endif
10961
10962 bool success = false;
10963
10964 if (ConditionPassed (opcode))
10965 {
10966 bool single_reg;
10967 bool add;
10968 uint32_t imm32;
10969 uint32_t d;
10970 uint32_t n;
10971
10972 switch (encoding)
10973 {
10974 case eEncodingT1:
10975 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010976 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010977 single_reg = false;
10978 add = BitIsSet (opcode, 23);
10979 imm32 = Bits32 (opcode, 7, 0) << 2;
10980
10981 // d = UInt(D:Vd); n = UInt(Rn);
10982 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10983 n = Bits32 (opcode, 19, 16);
10984
10985 break;
10986
10987 case eEncodingT2:
10988 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010989 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010990 single_reg = true;
10991 add = BitIsSet (opcode, 23);
10992 imm32 = Bits32 (opcode, 7, 0) << 2;
10993
10994 // d = UInt(Vd:D); n = UInt(Rn);
10995 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10996 n = Bits32 (opcode, 19, 16);
10997
10998 break;
10999
11000 default:
11001 return false;
11002 }
Greg Claytonc07d4512011-04-26 23:48:45 +000011003 RegisterInfo base_reg;
11004 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice917ad352011-03-31 05:05:30 +000011005
11006 uint32_t Rn = ReadCoreReg (n, &success);
11007 if (!success)
11008 return false;
11009
11010 // base = if n == 15 then Align(PC,4) else R[n];
11011 uint32_t base;
11012 if (n == 15)
11013 base = AlignPC (Rn);
11014 else
11015 base = Rn;
11016
11017 // address = if add then (base + imm32) else (base - imm32);
11018 addr_t address;
11019 if (add)
11020 address = base + imm32;
11021 else
11022 address = base - imm32;
11023
11024 const uint32_t addr_byte_size = GetAddressByteSize();
11025 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11026
11027 EmulateInstruction::Context context;
11028 context.type = eContextRegisterLoad;
11029 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000011030
Caroline Tice917ad352011-03-31 05:05:30 +000011031 if (single_reg)
11032 {
11033 // S[d] = MemA[address,4];
11034 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
11035 if (!success)
11036 return false;
11037
11038 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
11039 return false;
11040 }
11041 else
11042 {
11043 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11044 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
11045 if (!success)
11046 return false;
11047
11048 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
11049 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
11050 if (!success)
11051 return false;
11052 // // Combine the word-aligned words in the correct order for current endianness.
11053 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11054 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000011055 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000011056 {
11057 data64 = word1;
11058 data64 = (data64 << 32) | word2;
11059 }
11060 else
11061 {
11062 data64 = word2;
11063 data64 = (data64 << 32) | word1;
11064 }
11065
11066 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
11067 return false;
11068 }
11069 }
11070 return true;
11071}
Caroline Tice424652f2011-03-31 05:38:36 +000011072
11073// A8.6.400 VSTR
11074// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
11075// optional offset.
11076bool
11077EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
11078{
11079#if 0
11080 if ConditionPassed() then
11081 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11082 address = if add then (R[n] + imm32) else (R[n] - imm32);
11083 if single_reg then
11084 MemA[address,4] = S[d];
11085 else
11086 // Store as two word-aligned words in the correct order for current endianness.
11087 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11088 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11089#endif
11090
11091 bool success = false;
11092
11093 if (ConditionPassed (opcode))
11094 {
11095 bool single_reg;
11096 bool add;
11097 uint32_t imm32;
11098 uint32_t d;
11099 uint32_t n;
11100
11101 switch (encoding)
11102 {
11103 case eEncodingT1:
11104 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011105 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011106 single_reg = false;
11107 add = BitIsSet (opcode, 23);
11108 imm32 = Bits32 (opcode, 7, 0) << 2;
11109
11110 // d = UInt(D:Vd); n = UInt(Rn);
11111 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11112 n = Bits32 (opcode, 19, 16);
11113
11114 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11115 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11116 return false;
11117
11118 break;
11119
11120 case eEncodingT2:
11121 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011122 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011123 single_reg = true;
11124 add = BitIsSet (opcode, 23);
11125 imm32 = Bits32 (opcode, 7, 0) << 2;
11126
11127 // d = UInt(Vd:D); n = UInt(Rn);
11128 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11129 n = Bits32 (opcode, 19, 16);
11130
11131 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11132 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11133 return false;
11134
11135 break;
11136
11137 default:
11138 return false;
11139 }
11140
Greg Claytonc07d4512011-04-26 23:48:45 +000011141 RegisterInfo base_reg;
11142 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011143
11144 uint32_t Rn = ReadCoreReg (n, &success);
11145 if (!success)
11146 return false;
11147
11148 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11149 addr_t address;
11150 if (add)
11151 address = Rn + imm32;
11152 else
11153 address = Rn - imm32;
11154
11155 const uint32_t addr_byte_size = GetAddressByteSize();
11156 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11157
Greg Claytonc07d4512011-04-26 23:48:45 +000011158 RegisterInfo data_reg;
11159 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011160 EmulateInstruction::Context context;
11161 context.type = eContextRegisterStore;
11162 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11163
11164 if (single_reg)
11165 {
11166 // MemA[address,4] = S[d];
11167 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11168 if (!success)
11169 return false;
11170
11171 if (!MemAWrite (context, address, data, addr_byte_size))
11172 return false;
11173 }
11174 else
11175 {
11176 // // Store as two word-aligned words in the correct order for current endianness.
11177 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11178 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11179 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11180 if (!success)
11181 return false;
11182
Greg Clayton888a7332011-04-26 04:39:08 +000011183 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011184 {
11185 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11186 return false;
11187
11188 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11189 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11190 return false;
11191 }
11192 else
11193 {
11194 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11195 return false;
11196
11197 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11198 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11199 return false;
11200 }
11201 }
11202 }
11203 return true;
11204}
Caroline Tice9121b352011-03-31 16:41:19 +000011205
11206// A8.6.307 VLDI1 (multiple single elements)
11207// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11208// element of each register is loaded.
11209bool
11210EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11211{
11212#if 0
11213 if ConditionPassed() then
11214 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11215 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11216 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11217 for r = 0 to regs-1
11218 for e = 0 to elements-1
11219 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11220 address = address + ebytes;
11221#endif
11222
11223 bool success = false;
11224
11225 if (ConditionPassed (opcode))
11226 {
11227 uint32_t regs;
11228 uint32_t alignment;
11229 uint32_t ebytes;
11230 uint32_t esize;
11231 uint32_t elements;
11232 uint32_t d;
11233 uint32_t n;
11234 uint32_t m;
11235 bool wback;
11236 bool register_index;
11237
11238 switch (encoding)
11239 {
11240 case eEncodingT1:
11241 case eEncodingA1:
11242 {
11243 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011244 // when Ô0111Õ
11245 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
11246 // when Ô1010Õ
11247 // regs = 2; if align == Ô11Õ then UNDEFINED;
11248 // when Ô0110Õ
11249 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
11250 // when Ô0010Õ
Caroline Tice9121b352011-03-31 16:41:19 +000011251 // regs = 4;
11252 // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011253 // SEE ÒRelated encodingsÓ;
Caroline Tice9121b352011-03-31 16:41:19 +000011254 uint32_t type = Bits32 (opcode, 11, 8);
11255 uint32_t align = Bits32 (opcode, 5, 4);
11256 if (type == 7) // '0111'
11257 {
11258 regs = 1;
11259 if (BitIsSet (align, 1))
11260 return false;
11261 }
11262 else if (type == 10) // '1010'
11263 {
11264 regs = 2;
11265 if (align == 3)
11266 return false;
11267
11268 }
11269 else if (type == 6) // '0110'
11270 {
11271 regs = 3;
11272 if (BitIsSet (align, 1))
11273 return false;
11274 }
11275 else if (type == 2) // '0010'
11276 {
11277 regs = 4;
11278 }
11279 else
11280 return false;
11281
Greg Clayton061b79d2011-05-09 20:18:18 +000011282 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice9121b352011-03-31 16:41:19 +000011283 if (align == 0)
11284 alignment = 1;
11285 else
11286 alignment = 4 << align;
11287
11288 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11289 ebytes = 1 << Bits32 (opcode, 7, 6);
11290 esize = 8 * ebytes;
11291 elements = 8 / ebytes;
11292
11293 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11294 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11295 n = Bits32 (opcode, 19, 15);
11296 m = Bits32 (opcode, 3, 0);
11297
11298 // wback = (m != 15); register_index = (m != 15 && m != 13);
11299 wback = (m != 15);
11300 register_index = ((m != 15) && (m != 13));
11301
11302 // if d+regs > 32 then UNPREDICTABLE;
11303 if ((d + regs) > 32)
11304 return false;
11305 }
11306 break;
11307
11308 default:
11309 return false;
11310 }
11311
Greg Claytonc07d4512011-04-26 23:48:45 +000011312 RegisterInfo base_reg;
11313 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice9121b352011-03-31 16:41:19 +000011314
11315 uint32_t Rn = ReadCoreReg (n, &success);
11316 if (!success)
11317 return false;
11318
11319 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11320 addr_t address = Rn;
11321 if ((address % alignment) != 0)
11322 return false;
11323
11324 EmulateInstruction::Context context;
11325 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11326 if (wback)
11327 {
11328 uint32_t Rm = ReadCoreReg (m, &success);
11329 if (!success)
11330 return false;
11331
11332 uint32_t offset;
11333 if (register_index)
11334 offset = Rm;
11335 else
11336 offset = 8 * regs;
11337
11338 uint32_t value = Rn + offset;
11339 context.type = eContextAdjustBaseRegister;
11340 context.SetRegisterPlusOffset (base_reg, offset);
11341
11342 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11343 return false;
11344
11345 }
11346
11347 // for r = 0 to regs-1
11348 for (int r = 0; r < regs; ++r)
11349 {
11350 // for e = 0 to elements-1
11351 uint64_t assembled_data = 0;
11352 for (int e = 0; e < elements; ++e)
11353 {
11354 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11355 context.type = eContextRegisterLoad;
11356 context.SetRegisterPlusOffset (base_reg, address - Rn);
11357 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11358 if (!success)
11359 return false;
11360
11361 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11362
11363 // address = address + ebytes;
11364 address = address + ebytes;
11365 }
11366 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11367 return false;
11368 }
11369 }
11370 return true;
11371}
11372
Caroline Ticeb6281b12011-03-31 17:58:23 +000011373// A8.6.308 VLD1 (single element to one lane)
11374//
11375bool
11376EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11377{
11378#if 0
11379 if ConditionPassed() then
11380 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11381 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11382 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11383 Elem[D[d],index,esize] = MemU[address,ebytes];
11384#endif
11385
11386 bool success = false;
11387
11388 if (ConditionPassed (opcode))
11389 {
11390 uint32_t ebytes;
11391 uint32_t esize;
11392 uint32_t index;
11393 uint32_t alignment;
11394 uint32_t d;
11395 uint32_t n;
11396 uint32_t m;
11397 bool wback;
11398 bool register_index;
11399
11400 switch (encoding)
11401 {
11402 case eEncodingT1:
11403 case eEncodingA1:
11404 {
11405 uint32_t size = Bits32 (opcode, 11, 10);
11406 uint32_t index_align = Bits32 (opcode, 7, 4);
Greg Clayton061b79d2011-05-09 20:18:18 +000011407 // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011408 if (size == 3)
11409 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011410 // case size of
11411 if (size == 0) // when '00'
11412 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011413 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011414 if (BitIsClear (index_align, 0))
11415 return false;
11416
11417 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11418 ebytes = 1;
11419 esize = 8;
11420 index = Bits32 (index_align, 3, 1);
11421 alignment = 1;
11422 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011423 else if (size == 1) // when Ô01Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011424 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011425 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011426 if (BitIsClear (index_align, 1))
11427 return false;
11428
11429 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11430 ebytes = 2;
11431 esize = 16;
11432 index = Bits32 (index_align, 3, 2);
11433
Greg Clayton061b79d2011-05-09 20:18:18 +000011434 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011435 if (BitIsClear (index_align, 0))
11436 alignment = 1;
11437 else
11438 alignment = 2;
11439 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011440 else if (size == 2) // when Ô10Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011441 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011442 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011443 if (BitIsClear (index_align, 2))
11444 return false;
11445
Greg Clayton061b79d2011-05-09 20:18:18 +000011446 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011447 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11448 return false;
11449
11450 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11451 ebytes = 4;
11452 esize = 32;
11453 index = Bit32 (index_align, 3);
11454
Greg Clayton061b79d2011-05-09 20:18:18 +000011455 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011456 if (Bits32 (index_align, 1, 0) == 0)
11457 alignment = 1;
11458 else
11459 alignment = 4;
11460 }
11461 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11462 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11463 n = Bits32 (opcode, 19, 16);
11464 m = Bits32 (opcode, 3, 0);
11465
11466 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11467 wback = (m != 15);
11468 register_index = ((m != 15) && (m != 13));
11469
11470 if (n == 15)
11471 return false;
11472
11473 }
11474 break;
11475
11476 default:
11477 return false;
11478 }
11479
Greg Claytonc07d4512011-04-26 23:48:45 +000011480 RegisterInfo base_reg;
11481 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011482
11483 uint32_t Rn = ReadCoreReg (n, &success);
11484 if (!success)
11485 return false;
11486
11487 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11488 addr_t address = Rn;
11489 if ((address % alignment) != 0)
11490 return false;
11491
11492 EmulateInstruction::Context context;
11493 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11494 if (wback)
11495 {
11496 uint32_t Rm = ReadCoreReg (m, &success);
11497 if (!success)
11498 return false;
11499
11500 uint32_t offset;
11501 if (register_index)
11502 offset = Rm;
11503 else
11504 offset = ebytes;
11505
11506 uint32_t value = Rn + offset;
11507
11508 context.type = eContextAdjustBaseRegister;
11509 context.SetRegisterPlusOffset (base_reg, offset);
11510
11511 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11512 return false;
11513 }
11514
11515 // Elem[D[d],index,esize] = MemU[address,ebytes];
11516 uint32_t element = MemURead (context, address, esize, 0, &success);
11517 if (!success)
11518 return false;
11519
11520 element = element << (index * esize);
11521
11522 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11523 if (!success)
11524 return false;
11525
11526 uint64_t all_ones = -1;
11527 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11528 // at element & to the right of element.
11529 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011530 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 +000011531 // now mask should be 0's where element goes & 1's
11532 // everywhere else.
11533
11534 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11535 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11536
11537 context.type = eContextRegisterLoad;
11538 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11539 return false;
11540 }
11541 return true;
11542}
11543
Caroline Tice1e542e32011-03-31 18:44:04 +000011544// A8.6.391 VST1 (multiple single elements)
11545// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11546// interleaving. Every element of each register is stored.
11547bool
11548EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11549{
11550#if 0
11551 if ConditionPassed() then
11552 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11553 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11554 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11555 for r = 0 to regs-1
11556 for e = 0 to elements-1
11557 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11558 address = address + ebytes;
11559#endif
11560
11561 bool success = false;
11562
11563 if (ConditionPassed (opcode))
11564 {
11565 uint32_t regs;
11566 uint32_t alignment;
11567 uint32_t ebytes;
11568 uint32_t esize;
11569 uint32_t elements;
11570 uint32_t d;
11571 uint32_t n;
11572 uint32_t m;
11573 bool wback;
11574 bool register_index;
11575
11576 switch (encoding)
11577 {
11578 case eEncodingT1:
11579 case eEncodingA1:
11580 {
11581 uint32_t type = Bits32 (opcode, 11, 8);
11582 uint32_t align = Bits32 (opcode, 5, 4);
11583
11584 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011585 if (type == 7) // when Ô0111Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011586 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011587 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011588 regs = 1;
11589 if (BitIsSet (align, 1))
11590 return false;
11591 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011592 else if (type == 10) // when Ô1010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011593 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011594 // regs = 2; if align == Ô11Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011595 regs = 2;
11596 if (align == 3)
11597 return false;
11598 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011599 else if (type == 6) // when Ô0110Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011600 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011601 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011602 regs = 3;
11603 if (BitIsSet (align, 1))
11604 return false;
11605 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011606 else if (type == 2) // when Ô0010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011607 // regs = 4;
11608 regs = 4;
11609 else // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011610 // SEE ÒRelated encodingsÓ;
Caroline Tice1e542e32011-03-31 18:44:04 +000011611 return false;
11612
Greg Clayton061b79d2011-05-09 20:18:18 +000011613 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice1e542e32011-03-31 18:44:04 +000011614 if (align == 0)
11615 alignment = 0;
11616 else
11617 alignment = 4 << align;
11618
11619 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11620 ebytes = 1 << Bits32 (opcode,7, 6);
11621 esize = 8 * ebytes;
11622 elements = 8 / ebytes;
11623
11624 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11625 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11626 n = Bits32 (opcode, 19, 16);
11627 m = Bits32 (opcode, 3, 0);
11628
11629 // wback = (m != 15); register_index = (m != 15 && m != 13);
11630 wback = (m != 15);
11631 register_index = ((m != 15) && (m != 13));
11632
11633 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11634 if ((d + regs) > 32)
11635 return false;
11636
11637 if (n == 15)
11638 return false;
11639
11640 }
11641 break;
11642
11643 default:
11644 return false;
11645 }
11646
Greg Claytonc07d4512011-04-26 23:48:45 +000011647 RegisterInfo base_reg;
11648 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011649
11650 uint32_t Rn = ReadCoreReg (n, &success);
11651 if (!success)
11652 return false;
11653
11654 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11655 addr_t address = Rn;
11656 if ((address % alignment) != 0)
11657 return false;
11658
11659 EmulateInstruction::Context context;
11660 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11661 if (wback)
11662 {
11663 uint32_t Rm = ReadCoreReg (m, &success);
11664 if (!success)
11665 return false;
11666
11667 uint32_t offset;
11668 if (register_index)
11669 offset = Rm;
11670 else
11671 offset = 8 * regs;
11672
11673 context.type = eContextAdjustBaseRegister;
11674 context.SetRegisterPlusOffset (base_reg, offset);
11675
11676 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11677 return false;
11678 }
11679
Greg Claytonc07d4512011-04-26 23:48:45 +000011680 RegisterInfo data_reg;
Caroline Tice1e542e32011-03-31 18:44:04 +000011681 context.type = eContextRegisterStore;
Caroline Tice1e542e32011-03-31 18:44:04 +000011682 // for r = 0 to regs-1
11683 for (int r = 0; r < regs; ++r)
11684 {
Greg Claytonc07d4512011-04-26 23:48:45 +000011685 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011686 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11687 if (!success)
11688 return false;
11689
11690 // for e = 0 to elements-1
11691 for (int e = 0; e < elements; ++e)
11692 {
11693 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011694 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011695
11696 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11697 if (!MemUWrite (context, address, word, ebytes))
11698 return false;
11699
11700 // address = address + ebytes;
11701 address = address + ebytes;
11702 }
11703 }
11704 }
11705 return true;
11706}
11707
Caroline Tice7b880942011-03-31 19:17:12 +000011708// A8.6.392 VST1 (single element from one lane)
11709// This instruction stores one element to memory from one element of a register.
11710bool
11711EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11712{
11713#if 0
11714 if ConditionPassed() then
11715 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11716 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11717 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11718 MemU[address,ebytes] = Elem[D[d],index,esize];
11719#endif
11720
11721 bool success = false;
11722
11723 if (ConditionPassed (opcode))
11724 {
11725 uint32_t ebytes;
11726 uint32_t esize;
11727 uint32_t index;
11728 uint32_t alignment;
11729 uint32_t d;
11730 uint32_t n;
11731 uint32_t m;
11732 bool wback;
11733 bool register_index;
11734
11735 switch (encoding)
11736 {
11737 case eEncodingT1:
11738 case eEncodingA1:
11739 {
11740 uint32_t size = Bits32 (opcode, 11, 10);
11741 uint32_t index_align = Bits32 (opcode, 7, 4);
11742
Greg Clayton061b79d2011-05-09 20:18:18 +000011743 // if size == Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011744 if (size == 3)
11745 return false;
11746
11747 // case size of
Greg Clayton061b79d2011-05-09 20:18:18 +000011748 if (size == 0) // when Ô00Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011749 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011750 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011751 if (BitIsClear (index_align, 0))
11752 return false;
11753 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11754 ebytes = 1;
11755 esize = 8;
11756 index = Bits32 (index_align, 3, 1);
11757 alignment = 1;
11758 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011759 else if (size == 1) // when Ô01Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011760 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011761 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011762 if (BitIsClear (index_align, 1))
11763 return false;
11764
11765 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11766 ebytes = 2;
11767 esize = 16;
11768 index = Bits32 (index_align, 3, 2);
11769
Greg Clayton061b79d2011-05-09 20:18:18 +000011770 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Tice7b880942011-03-31 19:17:12 +000011771 if (BitIsClear (index_align, 0))
11772 alignment = 1;
11773 else
11774 alignment = 2;
11775 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011776 else if (size == 2) // when Ô10Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011777 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011778 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011779 if (BitIsClear (index_align, 2))
11780 return false;
11781
Greg Clayton061b79d2011-05-09 20:18:18 +000011782 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011783 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11784 return false;
11785
11786 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11787 ebytes = 4;
11788 esize = 32;
11789 index = Bit32 (index_align, 3);
11790
Greg Clayton061b79d2011-05-09 20:18:18 +000011791 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Tice7b880942011-03-31 19:17:12 +000011792 if (Bits32 (index_align, 1, 0) == 0)
11793 alignment = 1;
11794 else
11795 alignment = 4;
11796 }
11797 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11798 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11799 n = Bits32 (opcode, 19, 16);
11800 m = Bits32 (opcode, 3, 0);
11801
11802 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11803 wback = (m != 15);
11804 register_index = ((m != 15) && (m != 13));
11805
11806 if (n == 15)
11807 return false;
11808 }
11809 break;
11810
11811 default:
11812 return false;
11813 }
11814
Greg Claytonc07d4512011-04-26 23:48:45 +000011815 RegisterInfo base_reg;
11816 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011817
11818 uint32_t Rn = ReadCoreReg (n, &success);
11819 if (!success)
11820 return false;
11821
11822 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11823 addr_t address = Rn;
11824 if ((address % alignment) != 0)
11825 return false;
11826
11827 EmulateInstruction::Context context;
11828 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11829 if (wback)
11830 {
11831 uint32_t Rm = ReadCoreReg (m, &success);
11832 if (!success)
11833 return false;
11834
11835 uint32_t offset;
11836 if (register_index)
11837 offset = Rm;
11838 else
11839 offset = ebytes;
11840
11841 context.type = eContextAdjustBaseRegister;
11842 context.SetRegisterPlusOffset (base_reg, offset);
11843
11844 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11845 return false;
11846 }
11847
11848 // MemU[address,ebytes] = Elem[D[d],index,esize];
11849 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11850 if (!success)
11851 return false;
11852
11853 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11854
Greg Claytonc07d4512011-04-26 23:48:45 +000011855 RegisterInfo data_reg;
11856 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011857 context.type = eContextRegisterStore;
11858 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11859
11860 if (!MemUWrite (context, address, word, ebytes))
11861 return false;
11862 }
11863 return true;
11864}
11865
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011866// A8.6.309 VLD1 (single element to all lanes)
11867// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011868bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011869EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011870{
11871#if 0
11872 if ConditionPassed() then
11873 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11874 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11875 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11876 replicated_element = Replicate(MemU[address,ebytes], elements);
11877 for r = 0 to regs-1
11878 D[d+r] = replicated_element;
11879#endif
11880
11881 bool success = false;
11882
11883 if (ConditionPassed (opcode))
11884 {
11885 uint32_t ebytes;
11886 uint32_t elements;
11887 uint32_t regs;
11888 uint32_t alignment;
11889 uint32_t d;
11890 uint32_t n;
11891 uint32_t m;
11892 bool wback;
11893 bool register_index;
11894
11895 switch (encoding)
11896 {
11897 case eEncodingT1:
11898 case eEncodingA1:
11899 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011900 //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
Caroline Tice93767b82011-03-31 21:15:29 +000011901 uint32_t size = Bits32 (opcode, 7, 6);
11902 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11903 return false;
11904
Greg Clayton061b79d2011-05-09 20:18:18 +000011905 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
Caroline Tice93767b82011-03-31 21:15:29 +000011906 ebytes = 1 << size;
11907 elements = 8 / ebytes;
11908 if (BitIsClear (opcode, 5))
11909 regs = 1;
11910 else
11911 regs = 2;
11912
Greg Clayton061b79d2011-05-09 20:18:18 +000011913 //alignment = if a == Ô0Õ then 1 else ebytes;
Caroline Tice93767b82011-03-31 21:15:29 +000011914 if (BitIsClear (opcode, 4))
11915 alignment = 1;
11916 else
11917 alignment = ebytes;
11918
11919 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11920 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11921 n = Bits32 (opcode, 19, 16);
11922 m = Bits32 (opcode, 3, 0);
11923
11924 //wback = (m != 15); register_index = (m != 15 && m != 13);
11925 wback = (m != 15);
11926 register_index = ((m != 15) && (m != 13));
11927
11928 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11929 if ((d + regs) > 32)
11930 return false;
11931
11932 if (n == 15)
11933 return false;
11934 }
11935 break;
11936
11937 default:
11938 break;
11939 }
11940
Greg Claytonc07d4512011-04-26 23:48:45 +000011941 RegisterInfo base_reg;
11942 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice93767b82011-03-31 21:15:29 +000011943
11944 uint32_t Rn = ReadCoreReg (n, &success);
11945 if (!success)
11946 return false;
11947
11948 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11949 addr_t address = Rn;
11950 if ((address % alignment) != 0)
11951 return false;
11952
11953 EmulateInstruction::Context context;
11954 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11955 if (wback)
11956 {
11957 uint32_t Rm = ReadCoreReg (m, &success);
11958 if (!success)
11959 return false;
11960
11961 uint32_t offset;
11962 if (register_index)
11963 offset = Rm;
11964 else
11965 offset = ebytes;
11966
11967 context.type = eContextAdjustBaseRegister;
11968 context.SetRegisterPlusOffset (base_reg, offset);
11969
11970 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11971 return false;
11972 }
11973
11974 // replicated_element = Replicate(MemU[address,ebytes], elements);
11975
11976 context.type = eContextRegisterLoad;
11977 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11978 if (!success)
11979 return false;
11980
11981 uint64_t replicated_element;
11982 uint32_t esize = ebytes * 8;
11983 for (int e = 0; e < elements; ++e)
11984 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11985
11986 // for r = 0 to regs-1
11987 for (int r = 0; r < regs; ++r)
11988 {
11989 // D[d+r] = replicated_element;
11990 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11991 return false;
11992 }
11993 }
11994 return true;
11995}
11996
Caroline Tice1f954f52011-04-11 15:51:10 +000011997// B6.2.13 SUBS PC, LR and related instructions
11998//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
11999// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
12000bool
12001EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
12002{
12003#if 0
12004 if ConditionPassed() then
12005 EncodingSpecificOperations();
12006 if CurrentInstrSet() == InstrSet_ThumbEE then
12007 UNPREDICTABLE;
12008 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12009 case opcode of
Greg Clayton061b79d2011-05-09 20:18:18 +000012010 when Ô0000Õ result = R[n] AND operand2; // AND
12011 when Ô0001Õ result = R[n] EOR operand2; // EOR
12012 when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
12013 when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
12014 when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
12015 when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12016 when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12017 when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12018 when Ô1100Õ result = R[n] OR operand2; // ORR
12019 when Ô1101Õ result = operand2; // MOV
12020 when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
12021 when Ô1111Õ result = NOT(operand2); // MVN
12022 CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012023 BranchWritePC(result);
12024#endif
12025
12026 bool success = false;
12027
12028 if (ConditionPassed (opcode))
12029 {
12030 uint32_t n;
12031 uint32_t m;
12032 uint32_t imm32;
12033 bool register_form;
12034 ARM_ShifterType shift_t;
12035 uint32_t shift_n;
12036 uint32_t code;
12037
12038 switch (encoding)
12039 {
12040 case eEncodingT1:
12041 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
Greg Clayton061b79d2011-05-09 20:18:18 +000012042 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012043 n = 14;
12044 imm32 = Bits32 (opcode, 7, 0);
12045 register_form = false;
12046 code = 2;
12047
12048 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12049 if (InITBlock() && !LastInITBlock())
12050 return false;
12051
12052 break;
12053
12054 case eEncodingA1:
12055 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12056 n = Bits32 (opcode, 19, 16);
12057 imm32 = ARMExpandImm (opcode);
12058 register_form = false;
12059 code = Bits32 (opcode, 24, 21);
12060
12061 break;
12062
12063 case eEncodingA2:
12064 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12065 n = Bits32 (opcode, 19, 16);
12066 m = Bits32 (opcode, 3, 0);
12067 register_form = true;
12068
12069 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12070 shift_n = DecodeImmShiftARM (opcode, shift_t);
12071
12072 break;
12073
12074 default:
12075 return false;
12076 }
12077
12078 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12079 uint32_t operand2;
12080 if (register_form)
12081 {
12082 uint32_t Rm = ReadCoreReg (m, &success);
12083 if (!success)
12084 return false;
12085
Johnny Chena4438a72011-06-02 22:50:51 +000012086 operand2 = Shift (Rm, shift_t, shift_n, APSR_C, &success);
12087 if (!success)
12088 return false;
Caroline Tice1f954f52011-04-11 15:51:10 +000012089 }
12090 else
12091 {
12092 operand2 = imm32;
12093 }
12094
12095 uint32_t Rn = ReadCoreReg (n, &success);
12096 if (!success)
12097 return false;
12098
12099 AddWithCarryResult result;
12100
12101 // case opcode of
12102 switch (code)
12103 {
Greg Clayton061b79d2011-05-09 20:18:18 +000012104 case 0: // when Ô0000Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012105 // result = R[n] AND operand2; // AND
12106 result.result = Rn & operand2;
12107 break;
12108
Greg Clayton061b79d2011-05-09 20:18:18 +000012109 case 1: // when Ô0001Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012110 // result = R[n] EOR operand2; // EOR
12111 result.result = Rn ^ operand2;
12112 break;
12113
Greg Clayton061b79d2011-05-09 20:18:18 +000012114 case 2: // when Ô0010Õ
12115 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012116 result = AddWithCarry (Rn, ~(operand2), 1);
12117 break;
12118
Greg Clayton061b79d2011-05-09 20:18:18 +000012119 case 3: // when Ô0011Õ
12120 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
Caroline Tice1f954f52011-04-11 15:51:10 +000012121 result = AddWithCarry (~(Rn), operand2, 1);
12122 break;
12123
Greg Clayton061b79d2011-05-09 20:18:18 +000012124 case 4: // when Ô0100Õ
12125 // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
Caroline Tice1f954f52011-04-11 15:51:10 +000012126 result = AddWithCarry (Rn, operand2, 0);
12127 break;
12128
Greg Clayton061b79d2011-05-09 20:18:18 +000012129 case 5: // when Ô0101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012130 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12131 result = AddWithCarry (Rn, operand2, APSR_C);
12132 break;
12133
Greg Clayton061b79d2011-05-09 20:18:18 +000012134 case 6: // when Ô0110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012135 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12136 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12137 break;
12138
Greg Clayton061b79d2011-05-09 20:18:18 +000012139 case 7: // when Ô0111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012140 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12141 result = AddWithCarry (~(Rn), operand2, APSR_C);
12142 break;
12143
Greg Clayton061b79d2011-05-09 20:18:18 +000012144 case 10: // when Ô1100Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012145 // result = R[n] OR operand2; // ORR
12146 result.result = Rn | operand2;
12147 break;
12148
Greg Clayton061b79d2011-05-09 20:18:18 +000012149 case 11: // when Ô1101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012150 // result = operand2; // MOV
12151 result.result = operand2;
12152 break;
12153
Greg Clayton061b79d2011-05-09 20:18:18 +000012154 case 12: // when Ô1110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012155 // result = R[n] AND NOT(operand2); // BIC
12156 result.result = Rn & ~(operand2);
12157 break;
12158
Greg Clayton061b79d2011-05-09 20:18:18 +000012159 case 15: // when Ô1111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012160 // result = NOT(operand2); // MVN
12161 result.result = ~(operand2);
12162 break;
12163
12164 default:
12165 return false;
12166 }
Greg Clayton061b79d2011-05-09 20:18:18 +000012167 // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012168
12169 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12170 // the best.
12171 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12172 if (!success)
12173 return false;
12174
12175 CPSRWriteByInstr (spsr, 15, true);
12176
12177 // BranchWritePC(result);
12178 EmulateInstruction::Context context;
12179 context.type = eContextAdjustPC;
12180 context.SetImmediate (result.result);
12181
12182 BranchWritePC (context, result.result);
12183 }
12184 return true;
12185}
12186
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012187EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012188EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012189{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012190 static ARMOpcode
12191 g_arm_opcodes[] =
12192 {
12193 //----------------------------------------------------------------------
12194 // Prologue instructions
12195 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012196
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012197 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012198 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12199 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012200
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012201 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012202 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12203 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012204 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012205 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12206 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12207 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012208
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012209 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012210 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12211 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012212
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012213 // push one register
12214 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012215 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012216
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012217 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012218 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12219 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012220
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012221 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012222 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012223 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012224
Caroline Tice4f605582011-03-31 00:02:51 +000012225 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12226 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12227 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12228 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012229
12230 //----------------------------------------------------------------------
12231 // Supervisor Call (previously Software Interrupt)
12232 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012233 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012234
12235 //----------------------------------------------------------------------
12236 // Branch instructions
12237 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012238 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012239 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012240 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12241 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12242 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012243 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012244 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012245 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012246 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012247
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012248 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012249 // Data-processing instructions
12250 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012251 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012252 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012253 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012254 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012255 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012256 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012257 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012258 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012259 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012260 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012261 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012262 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12263 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012264 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012265 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012266 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012267 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012268 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012269 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012270 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012271 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012272 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012273 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012274 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012275 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012276 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012277 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012278 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012279 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012280 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012281 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012282 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012283 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012284 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012285 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012286 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012287 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012288 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012289 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012290 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012291 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012292 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012293 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012294 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012295 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012296 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012297 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012298 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012299 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012300 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012301 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012302 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012303 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012304 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012305 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012306
Caroline Tice89c6d582011-03-29 19:53:44 +000012307 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012308 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12309 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012310 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012311 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012312 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012313 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012314 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012315 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012316 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012317 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012318 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012319 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012320 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012321 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012322 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012323 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012324 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012325 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012326 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012327 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012328 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012329 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012330 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012331 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012332 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012333 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012334 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012335 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012336 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012337 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012338 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012339 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012340 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012341 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012342 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012343 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012344
12345 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012346 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12347 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012348
12349 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012350 // Load instructions
12351 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012352 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12353 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12354 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12355 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12356 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12357 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12358 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12359 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12360 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12361 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12362 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12363 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12364 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12365 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12366 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12367 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12368 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12369 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012370 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12371 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12372 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12373 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012374 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12375 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012376 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012377
12378 //----------------------------------------------------------------------
12379 // Store instructions
12380 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012381 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12382 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12383 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12384 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12385 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12386 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12387 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12388 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12389 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012390 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012391 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012392 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12393 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12394 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12395 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12396 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012397 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012398
Caroline Tice6bf65162011-03-03 17:42:58 +000012399 //----------------------------------------------------------------------
12400 // Other instructions
12401 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012402 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12403 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12404 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12405 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12406 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012407
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012408 };
12409 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12410
12411 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12412 {
Greg Clayton888a7332011-04-26 04:39:08 +000012413 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12414 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012415 return &g_arm_opcodes[i];
12416 }
12417 return NULL;
12418}
Greg Clayton64c84432011-01-21 22:02:52 +000012419
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012420
12421EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012422EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012423{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012424
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012425 static ARMOpcode
12426 g_thumb_opcodes[] =
12427 {
12428 //----------------------------------------------------------------------
12429 // Prologue instructions
12430 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012431
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012432 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012433 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12434 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12435 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012436
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012437 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012438 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012439 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012440 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012441 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012442 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012443
Johnny Chen864a8e82011-02-18 00:07:39 +000012444 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012445 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012446
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012447 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012448 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12449 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12450 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12451 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12452 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012453
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012454 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012455 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12456 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012457
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012458 //----------------------------------------------------------------------
12459 // Epilogue instructions
12460 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012461
Caroline Tice4f605582011-03-31 00:02:51 +000012462 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12463 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12464 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12465 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12466 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12467 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12468 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012469
12470 //----------------------------------------------------------------------
12471 // Supervisor Call (previously Software Interrupt)
12472 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012473 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012474
12475 //----------------------------------------------------------------------
12476 // If Then makes up to four following instructions conditional.
12477 //----------------------------------------------------------------------
Greg Clayton04d397c2011-05-23 18:04:09 +000012478 // The next 5 opcode _must_ come before the if then instruction
12479 { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"},
12480 { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
12481 { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
12482 { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
12483 { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
12484 { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012485
12486 //----------------------------------------------------------------------
12487 // Branch instructions
12488 //----------------------------------------------------------------------
12489 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012490 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12491 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12492 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12493 { 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 +000012494 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012495 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012496 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012497 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12498 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012499 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012500 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012501 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012502 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012503 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012504 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012505 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012506 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012507 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012508 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012509
12510 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012511 // Data-processing instructions
12512 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012513 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012514 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012515 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012516 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12517 { 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 +000012518 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012519 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012520 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012521 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012522 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012523 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12524 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12525 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012526 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012527 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012528 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012529 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12530 { 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 +000012531 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012532 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012533 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012534 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12535 { 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 +000012536 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012537 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012538 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012539 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12540 { 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 +000012541 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012542 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012543 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012544 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12545 { 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 +000012546 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012547 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12548 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012549 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012550 { 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 +000012551 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012552 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012553 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012554 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12555 { 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 +000012556 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012557 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12558 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12559 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12560 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012561 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012562 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12563 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12564 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12565 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012566 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012567 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12568 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012569 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012570 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12571 { 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 +000012572 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012573 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012574 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012575 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012576 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012577 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012578 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012579 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12580 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012581
Johnny Chen7c5234d2011-02-18 23:41:11 +000012582
Johnny Chen338bf542011-02-10 19:29:03 +000012583 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012584 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012585 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012586 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012587 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012588 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012589 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012590 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12591 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12592 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012593 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012594 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012595 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012596 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12597 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012598 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012599 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012600 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012601 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12602 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012603 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012604 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12605 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012606 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012607 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012608 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012609 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012610 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012611 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12612 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012613 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012614 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12615 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012616 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012617 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12618 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012619 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012620 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12621 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012622 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012623 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12624 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012625 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012626 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12627 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012628 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012629 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012630 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012631 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012632 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012633 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12634 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012635 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012636 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012637 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012638 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012639
12640 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012641 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012642
12643 //----------------------------------------------------------------------
12644 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12645 // otherwise the wrong instructions will be selected.
12646 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012647
Caroline Tice080bf612011-04-05 18:46:00 +000012648 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12649 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12650
Johnny Chen26863dc2011-02-09 23:43:29 +000012651 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012652 // Load instructions
12653 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012654 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12655 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12656 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12657 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12658 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12659 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12660 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012661 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012662 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12663 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12664 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12665 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12666 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012667 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012668 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12669 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12670 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12671 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12672 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12673 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12674 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12675 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12676 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12677 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12678 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12679 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12680 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12681 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12682 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12683 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12684 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12685 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12686 { 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 +000012687 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012688 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12689 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12690 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12691 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012692 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12693 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012694 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012695
12696 //----------------------------------------------------------------------
12697 // Store instructions
12698 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012699 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12700 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12701 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12702 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12703 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12704 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12705 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12706 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12707 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12708 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12709 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12710 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12711 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12712 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12713 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12714 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012715 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12716 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12717 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12718 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12719 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012720 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012721
12722 //----------------------------------------------------------------------
12723 // Other instructions
12724 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012725 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12726 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12727 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12728 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12729 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12730 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12731 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12732 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012733 };
12734
12735 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12736 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12737 {
Greg Clayton888a7332011-04-26 04:39:08 +000012738 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12739 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012740 return &g_thumb_opcodes[i];
12741 }
12742 return NULL;
12743}
Greg Clayton64c84432011-01-21 22:02:52 +000012744
Greg Clayton31e2a382011-01-30 20:03:56 +000012745bool
Greg Clayton395fc332011-02-15 21:59:32 +000012746EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012747{
Caroline Tice080bf612011-04-05 18:46:00 +000012748 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012749 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012750 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012751 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012752 {
Greg Clayton395fc332011-02-15 21:59:32 +000012753 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12754 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12755 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12756 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12757 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12758 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12759 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12760 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12761 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12762 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Johnny Chen1d29a852011-04-26 18:51:57 +000012763 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12764 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
Greg Clayton31e2a382011-01-30 20:03:56 +000012765 }
12766 return m_arm_isa != 0;
12767}
12768
Caroline Tice080bf612011-04-05 18:46:00 +000012769bool
Greg Clayton888a7332011-04-26 04:39:08 +000012770EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012771{
Greg Clayton888a7332011-04-26 04:39:08 +000012772 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12773 {
12774 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12775 m_opcode_mode = eModeThumb;
12776 else
12777 {
12778 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012779
Greg Clayton888a7332011-04-26 04:39:08 +000012780 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12781 m_opcode_mode = eModeARM;
12782 else if (addr_class == eAddressClassCodeAlternateISA)
12783 m_opcode_mode = eModeThumb;
12784 else
12785 return false;
12786 }
12787 if (m_opcode_mode == eModeThumb)
12788 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12789 else
12790 m_opcode_cpsr = CPSR_MODE_USR;
12791 return true;
12792 }
12793 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012794}
Greg Clayton31e2a382011-01-30 20:03:56 +000012795
Greg Clayton64c84432011-01-21 22:02:52 +000012796bool
12797EmulateInstructionARM::ReadInstruction ()
12798{
12799 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012800 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012801 if (success)
12802 {
12803 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12804 if (success)
12805 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012806 Context read_inst_context;
12807 read_inst_context.type = eContextReadOpcode;
12808 read_inst_context.SetNoArgs ();
12809
Greg Claytonb3448432011-03-24 21:19:54 +000012810 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012811 {
Greg Claytonb3448432011-03-24 21:19:54 +000012812 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012813 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012814
12815 if (success)
12816 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012817 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012818 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012819 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012820 }
12821 else
12822 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012823 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012824 }
12825 }
12826 }
12827 else
12828 {
Greg Claytonb3448432011-03-24 21:19:54 +000012829 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012830 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012831 }
12832 }
12833 }
12834 if (!success)
12835 {
Greg Claytonb3448432011-03-24 21:19:54 +000012836 m_opcode_mode = eModeInvalid;
Greg Clayton3063c952011-04-29 22:50:31 +000012837 m_addr = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012838 }
12839 return success;
12840}
12841
Johnny Chenee9b1f72011-02-09 01:00:31 +000012842uint32_t
12843EmulateInstructionARM::ArchVersion ()
12844{
12845 return m_arm_isa;
12846}
12847
Greg Clayton64c84432011-01-21 22:02:52 +000012848bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012849EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012850{
Greg Clayton888a7332011-04-26 04:39:08 +000012851 // If we are ignoring conditions, then always return true.
12852 // this allows us to iterate over disassembly code and still
12853 // emulate an instruction even if we don't have all the right
12854 // bits set in the CPSR register...
12855 if (m_ignore_conditions)
12856 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000012857
Greg Clayton7bc39082011-03-24 23:53:38 +000012858 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012859
12860 if (cond == UINT32_MAX)
12861 return false;
12862
12863 bool result = false;
12864 switch (UnsignedBits(cond, 3, 1))
12865 {
Caroline Tice080bf612011-04-05 18:46:00 +000012866 case 0:
12867 if (m_opcode_cpsr == 0)
12868 return true;
12869 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12870 break;
12871 case 1:
12872 if (m_opcode_cpsr == 0)
12873 return true;
12874 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12875 break;
12876 case 2:
12877 if (m_opcode_cpsr == 0)
12878 return true;
12879 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12880 break;
12881 case 3:
12882 if (m_opcode_cpsr == 0)
12883 return true;
12884 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12885 break;
12886 case 4:
12887 if (m_opcode_cpsr == 0)
12888 return true;
12889 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12890 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012891 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012892 if (m_opcode_cpsr == 0)
12893 return true;
12894 else
12895 {
Greg Claytonb3448432011-03-24 21:19:54 +000012896 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12897 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012898 result = n == v;
12899 }
12900 break;
12901 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012902 if (m_opcode_cpsr == 0)
12903 return true;
12904 else
12905 {
Greg Claytonb3448432011-03-24 21:19:54 +000012906 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12907 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12908 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012909 }
12910 break;
12911 case 7:
12912 result = true;
12913 break;
12914 }
12915
12916 if (cond & 1)
12917 result = !result;
12918 return result;
12919}
12920
Johnny Chen9ee056b2011-02-08 00:06:35 +000012921uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012922EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012923{
Greg Claytonb3448432011-03-24 21:19:54 +000012924 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012925 {
12926 default:
12927 case eModeInvalid:
12928 break;
12929
12930 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012931 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012932
12933 case eModeThumb:
12934 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12935 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012936 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012937 const uint32_t byte_size = m_opcode.GetByteSize();
12938 if (byte_size == 2)
12939 {
12940 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12941 return Bits32(opcode, 11, 7);
12942 }
12943 else
12944 {
Greg Claytone1f47bb2011-06-02 22:23:35 +000012945 //assert (byte_size == 4);
Greg Clayton7bc39082011-03-24 23:53:38 +000012946 if (Bits32(opcode, 31, 27) == 0x1e &&
12947 Bits32(opcode, 15, 14) == 0x02 &&
12948 Bits32(opcode, 12, 12) == 0x00 &&
12949 Bits32(opcode, 25, 22) <= 0x0d)
12950 {
12951 return Bits32(opcode, 25, 22);
12952 }
12953 }
12954
12955 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012956 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012957 }
12958 return UINT32_MAX; // Return invalid value
12959}
12960
Johnny Chen9ee056b2011-02-08 00:06:35 +000012961bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012962EmulateInstructionARM::InITBlock()
12963{
12964 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12965}
12966
12967bool
12968EmulateInstructionARM::LastInITBlock()
12969{
12970 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12971}
12972
Caroline Ticeb27771d2011-03-03 22:37:46 +000012973bool
12974EmulateInstructionARM::BadMode (uint32_t mode)
12975{
12976
12977 switch (mode)
12978 {
12979 case 16: return false; // '10000'
12980 case 17: return false; // '10001'
12981 case 18: return false; // '10010'
12982 case 19: return false; // '10011'
12983 case 22: return false; // '10110'
12984 case 23: return false; // '10111'
12985 case 27: return false; // '11011'
12986 case 31: return false; // '11111'
12987 default: return true;
12988 }
12989 return true;
12990}
12991
12992bool
12993EmulateInstructionARM::CurrentModeIsPrivileged ()
12994{
Greg Claytonb3448432011-03-24 21:19:54 +000012995 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012996
12997 if (BadMode (mode))
12998 return false;
12999
13000 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000013001 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000013002
13003 return true;
13004}
13005
13006void
13007EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
13008{
13009 bool privileged = CurrentModeIsPrivileged();
13010
13011 uint32_t tmp_cpsr = 0;
13012
Greg Claytonb3448432011-03-24 21:19:54 +000013013 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000013014
13015 if (BitIsSet (bytemask, 3))
13016 {
13017 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
13018 if (affect_execstate)
13019 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
13020 }
13021
13022 if (BitIsSet (bytemask, 2))
13023 {
13024 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
13025 }
13026
13027 if (BitIsSet (bytemask, 1))
13028 {
13029 if (affect_execstate)
13030 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
13031 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
13032 if (privileged)
13033 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
13034 }
13035
13036 if (BitIsSet (bytemask, 0))
13037 {
13038 if (privileged)
13039 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
13040 if (affect_execstate)
13041 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
13042 if (privileged)
13043 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
13044 }
13045
Greg Claytonb3448432011-03-24 21:19:54 +000013046 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000013047}
13048
13049
Johnny Chen098ae2d2011-02-12 00:50:05 +000013050bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000013051EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
13052{
13053 addr_t target;
13054
Johnny Chenee9b1f72011-02-09 01:00:31 +000013055 // Check the current instruction set.
13056 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013057 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013058 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000013059 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013060
Johnny Chen9ee056b2011-02-08 00:06:35 +000013061 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013062 return false;
13063
13064 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013065}
13066
13067// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
13068bool
Johnny Chen668b4512011-02-15 21:08:58 +000013069EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013070{
13071 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000013072 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
13073 // we want to record it and issue a WriteRegister callback so the clients
13074 // can track the mode changes accordingly.
13075 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013076
13077 if (BitIsSet(addr, 0))
13078 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013079 if (CurrentInstrSet() != eModeThumb)
13080 {
13081 SelectInstrSet(eModeThumb);
13082 cpsr_changed = true;
13083 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013084 target = addr & 0xfffffffe;
Greg Claytonc07d4512011-04-26 23:48:45 +000013085 context.SetISA (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013086 }
13087 else if (BitIsClear(addr, 1))
13088 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013089 if (CurrentInstrSet() != eModeARM)
13090 {
13091 SelectInstrSet(eModeARM);
13092 cpsr_changed = true;
13093 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013094 target = addr & 0xfffffffc;
Greg Claytonc07d4512011-04-26 23:48:45 +000013095 context.SetISA (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013096 }
13097 else
13098 return false; // address<1:0> == '10' => UNPREDICTABLE
13099
Johnny Chen0f309db2011-02-09 19:11:32 +000013100 if (cpsr_changed)
13101 {
Johnny Chen558133b2011-02-09 23:59:17 +000013102 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000013103 return false;
13104 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013105 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013106 return false;
13107
13108 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013109}
Greg Clayton64c84432011-01-21 22:02:52 +000013110
Johnny Chenee9b1f72011-02-09 01:00:31 +000013111// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13112bool
Johnny Chen668b4512011-02-15 21:08:58 +000013113EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000013114{
13115 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000013116 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000013117 else
13118 return BranchWritePC((const Context)context, addr);
13119}
13120
Johnny Chen26863dc2011-02-09 23:43:29 +000013121// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13122bool
Johnny Chen668b4512011-02-15 21:08:58 +000013123EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000013124{
13125 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013126 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013127 else
13128 return BranchWritePC((const Context)context, addr);
13129}
13130
Johnny Chenee9b1f72011-02-09 01:00:31 +000013131EmulateInstructionARM::Mode
13132EmulateInstructionARM::CurrentInstrSet ()
13133{
Greg Claytonb3448432011-03-24 21:19:54 +000013134 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013135}
13136
Greg Claytonb3448432011-03-24 21:19:54 +000013137// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013138// ReadInstruction() is performed. This function has a side effect of updating
13139// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013140bool
13141EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13142{
Greg Claytonb3448432011-03-24 21:19:54 +000013143 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013144 switch (arm_or_thumb)
13145 {
13146 default:
13147 return false;
13148 eModeARM:
13149 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013150 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013151 break;
13152 eModeThumb:
13153 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013154 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013155 break;
13156 }
13157 return true;
13158}
13159
Johnny Chenef21b592011-02-10 01:52:38 +000013160// This function returns TRUE if the processor currently provides support for
13161// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13162// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13163bool
13164EmulateInstructionARM::UnalignedSupport()
13165{
13166 return (ArchVersion() >= ARMv7);
13167}
13168
Johnny Chenbf6ad172011-02-11 01:29:53 +000013169// The main addition and subtraction instructions can produce status information
13170// about both unsigned carry and signed overflow conditions. This status
13171// information can be used to synthesize multi-word additions and subtractions.
13172EmulateInstructionARM::AddWithCarryResult
13173EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13174{
13175 uint32_t result;
13176 uint8_t carry_out;
13177 uint8_t overflow;
13178
13179 uint64_t unsigned_sum = x + y + carry_in;
13180 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13181
13182 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013183// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013184 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013185
13186 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013187 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013188 else
13189 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013190
13191 AddWithCarryResult res = { result, carry_out, overflow };
13192 return res;
13193}
13194
Johnny Chen157b9592011-02-18 21:13:05 +000013195uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013196EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013197{
Johnny Chene39f22d2011-02-19 01:36:13 +000013198 uint32_t reg_kind, reg_num;
13199 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013200 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013201 case SP_REG:
13202 reg_kind = eRegisterKindGeneric;
13203 reg_num = LLDB_REGNUM_GENERIC_SP;
13204 break;
13205 case LR_REG:
13206 reg_kind = eRegisterKindGeneric;
13207 reg_num = LLDB_REGNUM_GENERIC_RA;
13208 break;
13209 case PC_REG:
13210 reg_kind = eRegisterKindGeneric;
13211 reg_num = LLDB_REGNUM_GENERIC_PC;
13212 break;
13213 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013214 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013215 {
13216 reg_kind = eRegisterKindDWARF;
13217 reg_num = dwarf_r0 + num;
13218 }
Johnny Chen157b9592011-02-18 21:13:05 +000013219 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013220 {
Greg Claytone1f47bb2011-06-02 22:23:35 +000013221 //assert(0 && "Invalid register number");
Johnny Chene39f22d2011-02-19 01:36:13 +000013222 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013223 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013224 }
13225 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013226 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013227
13228 // Read our register.
13229 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13230
13231 // When executing an ARM instruction , PC reads as the address of the current
13232 // instruction plus 8.
13233 // When executing a Thumb instruction , PC reads as the address of the current
13234 // instruction plus 4.
13235 if (num == 15)
13236 {
13237 if (CurrentInstrSet() == eModeARM)
13238 val += 8;
13239 else
13240 val += 4;
13241 }
Johnny Chen157b9592011-02-18 21:13:05 +000013242
13243 return val;
13244}
13245
Johnny Chenca67d1c2011-02-17 01:35:27 +000013246// Write the result to the ARM core register Rd, and optionally update the
13247// condition flags based on the result.
13248//
13249// This helper method tries to encapsulate the following pseudocode from the
13250// ARM Architecture Reference Manual:
13251//
13252// if d == 15 then // Can only occur for encoding A1
13253// ALUWritePC(result); // setflags is always FALSE here
13254// else
13255// R[d] = result;
13256// if setflags then
13257// APSR.N = result<31>;
13258// APSR.Z = IsZeroBit(result);
13259// APSR.C = carry;
13260// // APSR.V unchanged
13261//
13262// In the above case, the API client does not pass in the overflow arg, which
13263// defaults to ~0u.
13264bool
Johnny Chen10530c22011-02-17 22:37:12 +000013265EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13266 const uint32_t result,
13267 const uint32_t Rd,
13268 bool setflags,
13269 const uint32_t carry,
13270 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013271{
13272 if (Rd == 15)
13273 {
13274 if (!ALUWritePC (context, result))
13275 return false;
13276 }
13277 else
13278 {
Johnny Chena695f952011-02-23 21:24:25 +000013279 uint32_t reg_kind, reg_num;
13280 switch (Rd)
13281 {
13282 case SP_REG:
13283 reg_kind = eRegisterKindGeneric;
13284 reg_num = LLDB_REGNUM_GENERIC_SP;
13285 break;
13286 case LR_REG:
13287 reg_kind = eRegisterKindGeneric;
13288 reg_num = LLDB_REGNUM_GENERIC_RA;
13289 break;
13290 default:
13291 reg_kind = eRegisterKindDWARF;
13292 reg_num = dwarf_r0 + Rd;
13293 }
13294 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013295 return false;
13296 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013297 return WriteFlags (context, result, carry, overflow);
13298 }
13299 return true;
13300}
13301
13302// This helper method tries to encapsulate the following pseudocode from the
13303// ARM Architecture Reference Manual:
13304//
13305// APSR.N = result<31>;
13306// APSR.Z = IsZeroBit(result);
13307// APSR.C = carry;
13308// APSR.V = overflow
13309//
13310// Default arguments can be specified for carry and overflow parameters, which means
13311// not to update the respective flags.
13312bool
13313EmulateInstructionARM::WriteFlags (Context &context,
13314 const uint32_t result,
13315 const uint32_t carry,
13316 const uint32_t overflow)
13317{
Greg Claytonb3448432011-03-24 21:19:54 +000013318 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013319 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13320 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013321 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013322 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013323 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013324 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013325 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013326 {
13327 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13328 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013329 }
13330 return true;
13331}
13332
Greg Clayton64c84432011-01-21 22:02:52 +000013333bool
Greg Clayton888a7332011-04-26 04:39:08 +000013334EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013335{
Johnny Chenc315f862011-02-05 00:46:10 +000013336 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013337 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013338 m_it_session.ITAdvance();
13339
Greg Clayton888a7332011-04-26 04:39:08 +000013340 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013341
13342 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013343 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013344 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013345 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13346
13347 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013348 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013349
Greg Clayton888a7332011-04-26 04:39:08 +000013350 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13351 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013352
Greg Clayton888a7332011-04-26 04:39:08 +000013353 bool success = false;
13354 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013355 {
Greg Clayton888a7332011-04-26 04:39:08 +000013356 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
Greg Clayton061b79d2011-05-09 20:18:18 +000013357 dwarf_cpsr,
13358 0,
13359 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013360 }
13361
Greg Clayton888a7332011-04-26 04:39:08 +000013362 // Only return false if we are unable to read the CPSR if we care about conditions
13363 if (success == false && m_ignore_conditions == false)
13364 return false;
13365
13366 uint32_t orig_pc_value = 0;
13367 if (auto_advance_pc)
13368 {
13369 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13370 if (!success)
13371 return false;
13372 }
13373
13374 // Call the Emulate... function.
13375 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13376 if (!success)
13377 return false;
13378
13379 if (auto_advance_pc)
13380 {
13381 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13382 if (!success)
13383 return false;
13384
13385 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13386 {
13387 if (opcode_data->size == eSize32)
13388 after_pc_value += 4;
13389 else if (opcode_data->size == eSize16)
13390 after_pc_value += 2;
13391
13392 EmulateInstruction::Context context;
13393 context.type = eContextAdvancePC;
13394 context.SetNoArgs();
13395 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13396 return false;
13397
13398 }
13399 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013400 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013401}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013402
13403bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013404EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013405{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013406 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013407 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013408 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013409 return false;
13410 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013411
13412 static ConstString opcode_key ("opcode");
13413 static ConstString before_key ("before_state");
13414 static ConstString after_key ("after_state");
13415
13416 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013417
13418 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013419 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013420 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013421 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013422 return false;
13423 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013424 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013425
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013426 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13427 {
13428 m_opcode_mode = eModeARM;
13429 m_opcode.SetOpcode32 (test_opcode);
13430 }
13431 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13432 {
13433 m_opcode_mode = eModeThumb;
13434 if (test_opcode < 0x10000)
13435 m_opcode.SetOpcode16 (test_opcode);
13436 else
13437 m_opcode.SetOpcode32 (test_opcode);
13438
13439 }
13440 else
13441 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013442 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013443 return false;
13444 }
13445
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013446 EmulationStateARM before_state;
13447 EmulationStateARM after_state;
13448
Caroline Ticedfb2e202011-04-22 05:08:45 +000013449 value_sp = test_data->GetValueForKey (before_key);
13450 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013451 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013452 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013453 return false;
13454 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013455
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013456 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013457 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013458 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013459 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013460 return false;
13461 }
13462
Caroline Ticedfb2e202011-04-22 05:08:45 +000013463 value_sp = test_data->GetValueForKey (after_key);
13464 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013465 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013466 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013467 return false;
13468 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013469
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013470 state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013471 if (!after_state.LoadStateFromDictionary (state_dictionary))
13472 {
13473 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13474 return false;
13475 }
13476
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013477 SetBaton ((void *) &before_state);
13478 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13479 &EmulationStateARM::WritePseudoMemory,
13480 &EmulationStateARM::ReadPseudoRegister,
13481 &EmulationStateARM::WritePseudoRegister);
13482
Greg Clayton888a7332011-04-26 04:39:08 +000013483 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013484 if (!success)
13485 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013486 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013487 return false;
13488 }
13489
13490 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013491 if (!success)
13492 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13493
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013494 return success;
13495}
Greg Claytonc07d4512011-04-26 23:48:45 +000013496//
13497//
13498//const char *
13499//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13500//{
13501// if (reg_kind == eRegisterKindGeneric)
13502// {
13503// switch (reg_num)
13504// {
13505// case LLDB_REGNUM_GENERIC_PC: return "pc";
13506// case LLDB_REGNUM_GENERIC_SP: return "sp";
13507// case LLDB_REGNUM_GENERIC_FP: return "fp";
13508// case LLDB_REGNUM_GENERIC_RA: return "lr";
13509// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13510// default: return NULL;
13511// }
13512// }
13513// else if (reg_kind == eRegisterKindDWARF)
13514// {
13515// return GetARMDWARFRegisterName (reg_num);
13516// }
13517// return NULL;
13518//}
13519//
13520bool
13521EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
Greg Clayton888a7332011-04-26 04:39:08 +000013522{
Greg Clayton75906e42011-05-11 18:39:18 +000013523 unwind_plan.Clear();
Greg Claytonc07d4512011-04-26 23:48:45 +000013524 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13525
13526 UnwindPlan::Row row;
Greg Claytonc07d4512011-04-26 23:48:45 +000013527
13528 // Our previous Call Frame Address is the stack pointer
13529 row.SetCFARegister (dwarf_sp);
13530
13531 // Our previous PC is in the LR
Greg Clayton75906e42011-05-11 18:39:18 +000013532 row.SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
Greg Claytonc07d4512011-04-26 23:48:45 +000013533 unwind_plan.AppendRow (row);
13534
13535 // All other registers are the same.
13536
13537 unwind_plan.SetSourceName ("EmulateInstructionARM");
13538 return true;
Greg Clayton888a7332011-04-26 04:39:08 +000013539}
13540
Greg Claytonc07d4512011-04-26 23:48:45 +000013541
13542
13543