blob: 1633d44f8897ddacc60a7b7c24a7f96b3975a328 [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
Greg Clayton107e53d2011-07-06 04:07:21 +0000330 bool conditional = false;
Greg Clayton64c84432011-01-21 22:02:52 +0000331 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +0000332 if (ConditionPassed(opcode, &conditional))
Greg Clayton64c84432011-01-21 22:02:52 +0000333 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000334 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000335 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000336 if (!success)
337 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000338 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000339 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000340 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000341 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000342 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000343 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000344 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000345 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000346 // if BitCount(registers) < 1 then UNPREDICTABLE;
347 if (BitCount(registers) < 1)
348 return false;
349 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000350 case eEncodingT2:
351 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000352 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000353 // if BitCount(registers) < 2 then UNPREDICTABLE;
354 if (BitCount(registers) < 2)
355 return false;
356 break;
357 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000358 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000359 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000360 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000361 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000362 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000363 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000364 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000365 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000366 // Instead of return false, let's handle the following case as well,
367 // which amounts to pushing one reg onto the full descending stacks.
368 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000369 break;
370 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000371 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000372 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000373 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000374 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000375 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000376 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000377 default:
378 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000379 }
Johnny Chence1ca772011-01-25 01:13:00 +0000380 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000381 addr_t addr = sp - sp_offset;
382 uint32_t i;
383
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000384 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +0000385 if (conditional)
386 context.type = EmulateInstruction::eContextRegisterStore;
387 else
388 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000389 RegisterInfo reg_info;
390 RegisterInfo sp_reg;
391 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Clayton64c84432011-01-21 22:02:52 +0000392 for (i=0; i<15; ++i)
393 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000394 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000395 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000396 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
397 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000398 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000399 if (!success)
400 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000401 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000402 return false;
403 addr += addr_byte_size;
404 }
405 }
406
Johnny Chen7c1bf922011-02-08 23:49:37 +0000407 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000408 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000409 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info);
410 context.SetRegisterPlusOffset (reg_info, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000411 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000412 if (!success)
413 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000414 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000415 return false;
416 }
417
418 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000419 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000420
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000421 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000422 return false;
423 }
424 return true;
425}
426
Johnny Chenef85e912011-01-31 23:07:40 +0000427// Pop Multiple Registers loads multiple registers from the stack, loading from
428// consecutive memory locations staring at the address in SP, and updates
429// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000430bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000431EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000432{
433#if 0
434 // ARM pseudo code...
435 if (ConditionPassed())
436 {
437 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
438 address = SP;
439 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000440 if registers<i> == '1' then
Greg Claytonc07d4512011-04-26 23:48:45 +0000441 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000442 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000443 if UnalignedAllowed then
444 LoadWritePC(MemU[address,4]);
445 else
446 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000447 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
448 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000449 }
450#endif
451
452 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000453
Greg Clayton107e53d2011-07-06 04:07:21 +0000454 bool conditional = false;
455 if (ConditionPassed(opcode, &conditional))
456 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000457 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000458 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000459 if (!success)
460 return false;
461 uint32_t registers = 0;
462 uint32_t Rt; // the destination register
463 switch (encoding) {
464 case eEncodingT1:
465 registers = Bits32(opcode, 7, 0);
466 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000467 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000468 registers |= (1u << 15);
469 // if BitCount(registers) < 1 then UNPREDICTABLE;
470 if (BitCount(registers) < 1)
471 return false;
472 break;
473 case eEncodingT2:
474 // Ignore bit 13.
475 registers = Bits32(opcode, 15, 0) & ~0x2000;
476 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000477 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000478 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000479 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
480 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
481 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000482 break;
483 case eEncodingT3:
484 Rt = Bits32(opcode, 15, 12);
485 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000486 if (Rt == 13)
487 return false;
488 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000489 return false;
490 registers = (1u << Rt);
491 break;
492 case eEncodingA1:
493 registers = Bits32(opcode, 15, 0);
494 // Instead of return false, let's handle the following case as well,
495 // which amounts to popping one reg from the full descending stacks.
496 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
497
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000498 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000499 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000500 return false;
501 break;
502 case eEncodingA2:
503 Rt = Bits32(opcode, 15, 12);
504 // if t == 13 then UNPREDICTABLE;
505 if (Rt == dwarf_sp)
506 return false;
507 registers = (1u << Rt);
508 break;
509 default:
510 return false;
511 }
512 addr_t sp_offset = addr_byte_size * BitCount (registers);
513 addr_t addr = sp;
514 uint32_t i, data;
515
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000516 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +0000517 if (conditional)
518 context.type = EmulateInstruction::eContextRegisterLoad;
519 else
520 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000521
522 RegisterInfo sp_reg;
523 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
524
Johnny Chenef85e912011-01-31 23:07:40 +0000525 for (i=0; i<15; ++i)
526 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000527 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000528 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000529 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000530 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000531 if (!success)
532 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +0000533 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000534 return false;
535 addr += addr_byte_size;
536 }
537 }
538
Johnny Chen7c1bf922011-02-08 23:49:37 +0000539 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000540 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000541 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000542 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000543 if (!success)
544 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000545 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000546 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000547 return false;
548 addr += addr_byte_size;
549 }
550
551 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000552 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000553
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000554 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000555 return false;
556 }
557 return true;
558}
559
Johnny Chen5b442b72011-01-27 19:34:30 +0000560// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000561// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000562bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000563EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000564{
565#if 0
566 // ARM pseudo code...
567 if (ConditionPassed())
568 {
569 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000570 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000571 if d == 15 then
572 ALUWritePC(result); // setflags is always FALSE here
573 else
574 R[d] = result;
575 if setflags then
576 APSR.N = result<31>;
577 APSR.Z = IsZeroBit(result);
578 APSR.C = carry;
579 APSR.V = overflow;
580 }
581#endif
582
583 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000584
Greg Clayton7bc39082011-03-24 23:53:38 +0000585 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000586 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000587 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000588 if (!success)
589 return false;
590 uint32_t Rd; // the destination register
591 uint32_t imm32;
592 switch (encoding) {
593 case eEncodingT1:
594 Rd = 7;
595 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
596 break;
597 case eEncodingA1:
598 Rd = Bits32(opcode, 15, 12);
599 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
600 break;
601 default:
602 return false;
603 }
604 addr_t sp_offset = imm32;
605 addr_t addr = sp + sp_offset; // a pointer to the stack area
606
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000607 EmulateInstruction::Context context;
Greg Clayton75906e42011-05-11 18:39:18 +0000608 context.type = eContextSetFramePointer;
Greg Claytonc07d4512011-04-26 23:48:45 +0000609 RegisterInfo sp_reg;
610 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000611 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000612
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000613 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000614 return false;
615 }
616 return true;
617}
618
Johnny Chen2ccad832011-01-28 19:57:25 +0000619// Set r7 or ip to the current stack pointer.
620// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000621bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000622EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000623{
624#if 0
625 // ARM pseudo code...
626 if (ConditionPassed())
627 {
628 EncodingSpecificOperations();
629 result = R[m];
630 if d == 15 then
631 ALUWritePC(result); // setflags is always FALSE here
632 else
633 R[d] = result;
634 if setflags then
635 APSR.N = result<31>;
636 APSR.Z = IsZeroBit(result);
637 // APSR.C unchanged
638 // APSR.V unchanged
639 }
640#endif
641
642 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000643
Greg Clayton7bc39082011-03-24 23:53:38 +0000644 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000645 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000646 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000647 if (!success)
648 return false;
649 uint32_t Rd; // the destination register
650 switch (encoding) {
651 case eEncodingT1:
652 Rd = 7;
653 break;
654 case eEncodingA1:
655 Rd = 12;
656 break;
657 default:
658 return false;
659 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000660
661 EmulateInstruction::Context context;
Greg Clayton04d397c2011-05-23 18:04:09 +0000662 if (Rd == GetFramePointerRegisterNumber())
663 context.type = EmulateInstruction::eContextSetFramePointer;
664 else
665 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +0000666 RegisterInfo sp_reg;
667 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000668 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000669
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000670 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000671 return false;
672 }
673 return true;
674}
675
Johnny Chen1c13b622011-01-29 00:11:15 +0000676// Move from high register (r8-r15) to low register (r0-r7).
677// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000678bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000679EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000680{
Greg Clayton7bc39082011-03-24 23:53:38 +0000681 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000682}
683
684// Move from register to register.
685// MOV (register)
686bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000687EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000688{
Johnny Chen1c13b622011-01-29 00:11:15 +0000689#if 0
690 // ARM pseudo code...
691 if (ConditionPassed())
692 {
693 EncodingSpecificOperations();
694 result = R[m];
695 if d == 15 then
696 ALUWritePC(result); // setflags is always FALSE here
697 else
698 R[d] = result;
699 if setflags then
700 APSR.N = result<31>;
701 APSR.Z = IsZeroBit(result);
702 // APSR.C unchanged
703 // APSR.V unchanged
704 }
705#endif
706
707 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000708
Greg Clayton7bc39082011-03-24 23:53:38 +0000709 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000710 {
711 uint32_t Rm; // the source register
712 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000713 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000714 switch (encoding) {
715 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000716 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000717 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000718 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000719 if (Rd == 15 && InITBlock() && !LastInITBlock())
720 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000721 break;
722 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000723 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000724 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000725 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000726 if (InITBlock())
727 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000728 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000729 case eEncodingT3:
730 Rd = Bits32(opcode, 11, 8);
731 Rm = Bits32(opcode, 3, 0);
732 setflags = BitIsSet(opcode, 20);
733 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
734 if (setflags && (BadReg(Rd) || BadReg(Rm)))
735 return false;
736 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
737 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
738 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000739 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000740 case eEncodingA1:
741 Rd = Bits32(opcode, 15, 12);
742 Rm = Bits32(opcode, 3, 0);
743 setflags = BitIsSet(opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +0000744
Johnny Chen01d61572011-02-25 00:23:25 +0000745 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000746 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000747 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000748 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000749 default:
750 return false;
751 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000752 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000753 if (!success)
754 return false;
755
756 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000757 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000758 context.type = EmulateInstruction::eContextRegisterLoad;
Greg Claytonc07d4512011-04-26 23:48:45 +0000759 RegisterInfo dwarf_reg;
760 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000761 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000762
Johnny Chen10530c22011-02-17 22:37:12 +0000763 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000764 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000765 }
766 return true;
767}
768
Johnny Chen357c30f2011-02-14 22:04:25 +0000769// Move (immediate) writes an immediate value to the destination register. It
770// can optionally update the condition flags based on the value.
771// MOV (immediate)
772bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000773EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000774{
775#if 0
776 // ARM pseudo code...
777 if (ConditionPassed())
778 {
779 EncodingSpecificOperations();
780 result = imm32;
781 if d == 15 then // Can only occur for ARM encoding
782 ALUWritePC(result); // setflags is always FALSE here
783 else
784 R[d] = result;
785 if setflags then
786 APSR.N = result<31>;
787 APSR.Z = IsZeroBit(result);
788 APSR.C = carry;
789 // APSR.V unchanged
790 }
791#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000792
Greg Clayton7bc39082011-03-24 23:53:38 +0000793 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000794 {
795 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000796 uint32_t imm32; // the immediate value to be written to Rd
Johnny Chen65f39ed2011-08-12 01:10:45 +0000797 uint32_t carry = 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
798 // for setflags == false, this value is a don't care
799 // initialized to 0 to silence the static analyzer
Johnny Chen357c30f2011-02-14 22:04:25 +0000800 bool setflags;
801 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000802 case eEncodingT1:
803 Rd = Bits32(opcode, 10, 8);
804 setflags = !InITBlock();
805 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
806 carry = APSR_C;
807
808 break;
809
810 case eEncodingT2:
811 Rd = Bits32(opcode, 11, 8);
812 setflags = BitIsSet(opcode, 20);
813 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
814 if (BadReg(Rd))
815 return false;
816
817 break;
818
819 case eEncodingT3:
820 {
821 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
822 Rd = Bits32 (opcode, 11, 8);
823 setflags = false;
824 uint32_t imm4 = Bits32 (opcode, 19, 16);
825 uint32_t imm3 = Bits32 (opcode, 14, 12);
826 uint32_t i = Bit32 (opcode, 26);
827 uint32_t imm8 = Bits32 (opcode, 7, 0);
828 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
829
830 // if BadReg(d) then UNPREDICTABLE;
831 if (BadReg (Rd))
832 return false;
833 }
834 break;
835
836 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +0000837 // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
Caroline Tice89c6d582011-03-29 19:53:44 +0000838 Rd = Bits32 (opcode, 15, 12);
839 setflags = BitIsSet (opcode, 20);
840 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000841
Greg Clayton061b79d2011-05-09 20:18:18 +0000842 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +0000843 if ((Rd == 15) && setflags)
844 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000845
846 break;
847
848 case eEncodingA2:
849 {
850 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
851 Rd = Bits32 (opcode, 15, 12);
852 setflags = false;
853 uint32_t imm4 = Bits32 (opcode, 19, 16);
854 uint32_t imm12 = Bits32 (opcode, 11, 0);
855 imm32 = (imm4 << 12) | imm12;
856
857 // if d == 15 then UNPREDICTABLE;
858 if (Rd == 15)
859 return false;
860 }
861 break;
862
863 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000864 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000865 }
866 uint32_t result = imm32;
867
868 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000869 EmulateInstruction::Context context;
870 context.type = EmulateInstruction::eContextImmediate;
871 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000872
Johnny Chen10530c22011-02-17 22:37:12 +0000873 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000874 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000875 }
876 return true;
877}
878
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000879// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
880// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
881// unsigned values.
882//
883// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
884// limited to only a few forms of the instruction.
885bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000886EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000887{
888#if 0
889 if ConditionPassed() then
890 EncodingSpecificOperations();
891 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
892 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
893 result = operand1 * operand2;
894 R[d] = result<31:0>;
895 if setflags then
896 APSR.N = result<31>;
897 APSR.Z = IsZeroBit(result);
898 if ArchVersion() == 4 then
899 APSR.C = bit UNKNOWN;
900 // else APSR.C unchanged
901 // APSR.V always unchanged
902#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000903
Greg Clayton7bc39082011-03-24 23:53:38 +0000904 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000905 {
906 uint32_t d;
907 uint32_t n;
908 uint32_t m;
909 bool setflags;
910
911 // EncodingSpecificOperations();
912 switch (encoding)
913 {
914 case eEncodingT1:
915 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
916 d = Bits32 (opcode, 2, 0);
917 n = Bits32 (opcode, 5, 3);
918 m = Bits32 (opcode, 2, 0);
919 setflags = !InITBlock();
920
921 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
922 if ((ArchVersion() < ARMv6) && (d == n))
923 return false;
924
925 break;
926
927 case eEncodingT2:
928 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
929 d = Bits32 (opcode, 11, 8);
930 n = Bits32 (opcode, 19, 16);
931 m = Bits32 (opcode, 3, 0);
932 setflags = false;
933
934 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
935 if (BadReg (d) || BadReg (n) || BadReg (m))
936 return false;
937
938 break;
939
940 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000941 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000942 d = Bits32 (opcode, 19, 16);
943 n = Bits32 (opcode, 3, 0);
944 m = Bits32 (opcode, 11, 8);
945 setflags = BitIsSet (opcode, 20);
946
947 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
948 if ((d == 15) || (n == 15) || (m == 15))
949 return false;
950
951 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
952 if ((ArchVersion() < ARMv6) && (d == n))
953 return false;
954
955 break;
956
957 default:
958 return false;
959 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000960
961 bool success = false;
962
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000963 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
964 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
965 if (!success)
966 return false;
967
968 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
969 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
970 if (!success)
971 return false;
972
973 // result = operand1 * operand2;
974 uint64_t result = operand1 * operand2;
975
976 // R[d] = result<31:0>;
Greg Claytonc07d4512011-04-26 23:48:45 +0000977 RegisterInfo op1_reg;
978 RegisterInfo op2_reg;
979 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
980 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000981
982 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +0000983 context.type = eContextArithmetic;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000984 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
985
986 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
987 return false;
988
989 // if setflags then
990 if (setflags)
991 {
992 // APSR.N = result<31>;
993 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000994 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000995 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
996 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000997 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000998 {
999 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1000 return false;
1001 }
1002
1003 // if ArchVersion() == 4 then
1004 // APSR.C = bit UNKNOWN;
1005 }
1006 }
1007 return true;
1008}
1009
Johnny Chend642a6a2011-02-22 01:01:03 +00001010// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
1011// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +00001012bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001013EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +00001014{
1015#if 0
1016 // ARM pseudo code...
1017 if (ConditionPassed())
1018 {
1019 EncodingSpecificOperations();
1020 result = NOT(imm32);
1021 if d == 15 then // Can only occur for ARM encoding
1022 ALUWritePC(result); // setflags is always FALSE here
1023 else
1024 R[d] = result;
1025 if setflags then
1026 APSR.N = result<31>;
1027 APSR.Z = IsZeroBit(result);
1028 APSR.C = carry;
1029 // APSR.V unchanged
1030 }
1031#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001032
Greg Clayton7bc39082011-03-24 23:53:38 +00001033 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001034 {
1035 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +00001036 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1037 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001038 bool setflags;
1039 switch (encoding) {
1040 case eEncodingT1:
1041 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001042 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001043 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001044 break;
1045 case eEncodingA1:
1046 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001047 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001048 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +00001049
Johnny Chend642a6a2011-02-22 01:01:03 +00001050 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +00001051 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001052 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001053 break;
1054 default:
1055 return false;
1056 }
1057 uint32_t result = ~imm32;
1058
1059 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001060 EmulateInstruction::Context context;
1061 context.type = EmulateInstruction::eContextImmediate;
1062 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001063
Johnny Chen10530c22011-02-17 22:37:12 +00001064 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001065 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001066 }
1067 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001068}
1069
Johnny Chend642a6a2011-02-22 01:01:03 +00001070// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1071// It can optionally update the condition flags based on the result.
1072bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001073EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001074{
1075#if 0
1076 // ARM pseudo code...
1077 if (ConditionPassed())
1078 {
1079 EncodingSpecificOperations();
1080 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1081 result = NOT(shifted);
1082 if d == 15 then // Can only occur for ARM encoding
1083 ALUWritePC(result); // setflags is always FALSE here
1084 else
1085 R[d] = result;
1086 if setflags then
1087 APSR.N = result<31>;
1088 APSR.Z = IsZeroBit(result);
1089 APSR.C = carry;
1090 // APSR.V unchanged
1091 }
1092#endif
1093
Greg Clayton7bc39082011-03-24 23:53:38 +00001094 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001095 {
1096 uint32_t Rm; // the source register
1097 uint32_t Rd; // the destination register
1098 ARM_ShifterType shift_t;
1099 uint32_t shift_n; // the shift applied to the value read from Rm
1100 bool setflags;
1101 uint32_t carry; // the carry bit after the shift operation
1102 switch (encoding) {
1103 case eEncodingT1:
1104 Rd = Bits32(opcode, 2, 0);
1105 Rm = Bits32(opcode, 5, 3);
1106 setflags = !InITBlock();
1107 shift_t = SRType_LSL;
1108 shift_n = 0;
1109 if (InITBlock())
1110 return false;
1111 break;
1112 case eEncodingT2:
1113 Rd = Bits32(opcode, 11, 8);
1114 Rm = Bits32(opcode, 3, 0);
1115 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001116 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001117 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001118 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001119 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001120 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001121 case eEncodingA1:
1122 Rd = Bits32(opcode, 15, 12);
1123 Rm = Bits32(opcode, 3, 0);
1124 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001125 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001126 break;
1127 default:
1128 return false;
1129 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001130 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001131 uint32_t value = ReadCoreReg(Rm, &success);
1132 if (!success)
1133 return false;
1134
Johnny Chena4438a72011-06-02 22:50:51 +00001135 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1136 if (!success)
1137 return false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001138 uint32_t result = ~shifted;
1139
1140 // The context specifies that an immediate is to be moved into Rd.
1141 EmulateInstruction::Context context;
1142 context.type = EmulateInstruction::eContextImmediate;
1143 context.SetNoArgs ();
1144
1145 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1146 return false;
1147 }
1148 return true;
1149}
1150
Johnny Chen788e0552011-01-27 22:52:23 +00001151// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1152// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001153bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001154EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001155{
1156#if 0
1157 // ARM pseudo code...
1158 if (ConditionPassed())
1159 {
1160 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1161 base = Align(PC,4);
1162 address = if add then (base + imm32) else (base - imm32);
1163 data = MemU[address,4];
1164 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001165 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1166 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001167 R[t] = data;
1168 else // Can only apply before ARMv7
1169 if CurrentInstrSet() == InstrSet_ARM then
1170 R[t] = ROR(data, 8*UInt(address<1:0>));
1171 else
1172 R[t] = bits(32) UNKNOWN;
1173 }
1174#endif
1175
Greg Clayton7bc39082011-03-24 23:53:38 +00001176 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001177 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001178 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001179 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001180 if (!success)
1181 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001182
1183 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001184 EmulateInstruction::Context context;
1185 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001186 RegisterInfo pc_reg;
1187 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001188 context.SetRegisterPlusOffset (pc_reg, 0);
1189
Johnny Chenc9de9102011-02-11 19:12:30 +00001190 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001191 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001192 bool add; // +imm32 or -imm32?
1193 addr_t base; // the base address
1194 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001195 uint32_t data; // the literal data value from the PC relative load
1196 switch (encoding) {
1197 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001198 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001199 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001200 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001201 break;
1202 case eEncodingT2:
1203 Rt = Bits32(opcode, 15, 12);
1204 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1205 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001206 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001207 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001208 break;
1209 default:
1210 return false;
1211 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001212
Johnny Chene39f22d2011-02-19 01:36:13 +00001213 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001214 if (add)
1215 address = base + imm32;
1216 else
1217 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001218
1219 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001220 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001221 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001222 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001223
1224 if (Rt == 15)
1225 {
1226 if (Bits32(address, 1, 0) == 0)
1227 {
1228 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001229 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001230 return false;
1231 }
1232 else
1233 return false;
1234 }
1235 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1236 {
1237 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1238 return false;
1239 }
1240 else // We don't handle ARM for now.
1241 return false;
1242
Johnny Chen788e0552011-01-27 22:52:23 +00001243 }
1244 return true;
1245}
1246
Johnny Chen5b442b72011-01-27 19:34:30 +00001247// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001248// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001249bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001250EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001251{
1252#if 0
1253 // ARM pseudo code...
1254 if (ConditionPassed())
1255 {
1256 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001257 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001258 if d == 15 then // Can only occur for ARM encoding
1259 ALUWritePC(result); // setflags is always FALSE here
1260 else
1261 R[d] = result;
1262 if setflags then
1263 APSR.N = result<31>;
1264 APSR.Z = IsZeroBit(result);
1265 APSR.C = carry;
1266 APSR.V = overflow;
1267 }
1268#endif
1269
1270 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001271
Greg Clayton7bc39082011-03-24 23:53:38 +00001272 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001273 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001274 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001275 if (!success)
1276 return false;
1277 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001278 uint32_t d;
1279 bool setflags;
1280 switch (encoding)
1281 {
1282 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001283 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001284 d = Bits32 (opcode, 10, 8);
1285 setflags = false;
1286 imm32 = (Bits32 (opcode, 7, 0) << 2);
1287
1288 break;
1289
1290 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001291 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001292 d = 13;
1293 setflags = false;
1294 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1295
1296 break;
1297
1298 default:
1299 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001300 }
1301 addr_t sp_offset = imm32;
1302 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1303
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001304 EmulateInstruction::Context context;
1305 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +00001306 RegisterInfo sp_reg;
1307 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001308 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001309
Caroline Ticee2212882011-03-22 22:38:28 +00001310 if (d == 15)
1311 {
1312 if (!ALUWritePC (context, addr))
1313 return false;
1314 }
1315 else
1316 {
1317 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1318 return false;
1319 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001320 }
1321 return true;
1322}
1323
1324// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001325// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001326bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001327EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001328{
1329#if 0
1330 // ARM pseudo code...
1331 if (ConditionPassed())
1332 {
1333 EncodingSpecificOperations();
1334 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001335 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001336 if d == 15 then
1337 ALUWritePC(result); // setflags is always FALSE here
1338 else
1339 R[d] = result;
1340 if setflags then
1341 APSR.N = result<31>;
1342 APSR.Z = IsZeroBit(result);
1343 APSR.C = carry;
1344 APSR.V = overflow;
1345 }
1346#endif
1347
1348 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001349
Greg Clayton7bc39082011-03-24 23:53:38 +00001350 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001351 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001352 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001353 if (!success)
1354 return false;
1355 uint32_t Rm; // the second operand
1356 switch (encoding) {
1357 case eEncodingT2:
1358 Rm = Bits32(opcode, 6, 3);
1359 break;
1360 default:
1361 return false;
1362 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001363 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001364 if (!success)
1365 return false;
1366
1367 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1368
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001369 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00001370 context.type = eContextArithmetic;
1371 RegisterInfo sp_reg;
1372 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1373
1374 RegisterInfo other_reg;
1375 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001376 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001377
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001378 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001379 return false;
1380 }
1381 return true;
1382}
1383
Johnny Chen9b8d7832011-02-02 01:13:56 +00001384// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1385// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1386// from Thumb to ARM.
1387// BLX (immediate)
1388bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001389EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001390{
1391#if 0
1392 // ARM pseudo code...
1393 if (ConditionPassed())
1394 {
1395 EncodingSpecificOperations();
1396 if CurrentInstrSet() == InstrSet_ARM then
1397 LR = PC - 4;
1398 else
1399 LR = PC<31:1> : '1';
1400 if targetInstrSet == InstrSet_ARM then
1401 targetAddress = Align(PC,4) + imm32;
1402 else
1403 targetAddress = PC + imm32;
1404 SelectInstrSet(targetInstrSet);
1405 BranchWritePC(targetAddress);
1406 }
1407#endif
1408
Greg Clayton7bc39082011-03-24 23:53:38 +00001409 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001410
Greg Clayton7bc39082011-03-24 23:53:38 +00001411 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001412 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001413 EmulateInstruction::Context context;
1414 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001415 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001416 if (!success)
1417 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001418 addr_t lr; // next instruction address
1419 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001420 int32_t imm32; // PC-relative offset
1421 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001422 case eEncodingT1:
1423 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001424 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001425 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001426 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001427 uint32_t J1 = Bit32(opcode, 13);
1428 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001429 uint32_t imm11 = Bits32(opcode, 10, 0);
1430 uint32_t I1 = !(J1 ^ S);
1431 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001432 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001433 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001434 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001435 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001436 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001437 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001438 break;
1439 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001440 case eEncodingT2:
1441 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001442 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001443 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001444 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001445 uint32_t J1 = Bit32(opcode, 13);
1446 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001447 uint32_t imm10L = Bits32(opcode, 10, 1);
1448 uint32_t I1 = !(J1 ^ S);
1449 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001450 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001451 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001452 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001453 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001454 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001455 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001456 break;
1457 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001458 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001459 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001460 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001461 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001462 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001463 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001464 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001465 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001466 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001467 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001468 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001469 break;
1470 default:
1471 return false;
1472 }
1473 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1474 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001475 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001476 return false;
1477 }
1478 return true;
1479}
1480
1481// Branch with Link and Exchange (register) calls a subroutine at an address and
1482// instruction set specified by a register.
1483// BLX (register)
1484bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001485EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001486{
1487#if 0
1488 // ARM pseudo code...
1489 if (ConditionPassed())
1490 {
1491 EncodingSpecificOperations();
1492 target = R[m];
1493 if CurrentInstrSet() == InstrSet_ARM then
1494 next_instr_addr = PC - 4;
1495 LR = next_instr_addr;
1496 else
1497 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001498 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001499 BXWritePC(target);
1500 }
1501#endif
1502
1503 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001504
Greg Clayton7bc39082011-03-24 23:53:38 +00001505 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001506 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001507 EmulateInstruction::Context context;
1508 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001509 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001510 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001511 if (!success)
1512 return false;
1513 uint32_t Rm; // the register with the target address
1514 switch (encoding) {
1515 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001516 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001517 Rm = Bits32(opcode, 6, 3);
1518 // if m == 15 then UNPREDICTABLE;
1519 if (Rm == 15)
1520 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001521 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001522 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001523 break;
1524 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001525 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001526 Rm = Bits32(opcode, 3, 0);
1527 // if m == 15 then UNPREDICTABLE;
1528 if (Rm == 15)
1529 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001530 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001531 default:
1532 return false;
1533 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001534 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001535 if (!success)
1536 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001537 RegisterInfo dwarf_reg;
1538 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001539 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001540 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1541 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001542 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001543 return false;
1544 }
1545 return true;
1546}
1547
Johnny Chenab3b3512011-02-12 00:10:51 +00001548// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001549bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001550EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001551{
1552#if 0
1553 // ARM pseudo code...
1554 if (ConditionPassed())
1555 {
1556 EncodingSpecificOperations();
1557 BXWritePC(R[m]);
1558 }
1559#endif
1560
Greg Clayton7bc39082011-03-24 23:53:38 +00001561 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001562 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001563 EmulateInstruction::Context context;
1564 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001565 uint32_t Rm; // the register with the target address
1566 switch (encoding) {
1567 case eEncodingT1:
1568 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001569 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001570 return false;
1571 break;
1572 case eEncodingA1:
1573 Rm = Bits32(opcode, 3, 0);
1574 break;
1575 default:
1576 return false;
1577 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001578 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001579 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001580 if (!success)
1581 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001582
1583 RegisterInfo dwarf_reg;
1584 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen668b4512011-02-15 21:08:58 +00001585 context.SetRegister (dwarf_reg);
1586 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001587 return false;
1588 }
1589 return true;
1590}
1591
Johnny Chen59e6ab72011-02-24 21:01:20 +00001592// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1593// address and instruction set specified by a register as though it were a BX instruction.
1594//
1595// TODO: Emulate Jazelle architecture?
1596// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1597bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001598EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001599{
1600#if 0
1601 // ARM pseudo code...
1602 if (ConditionPassed())
1603 {
1604 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001605 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001606 BXWritePC(R[m]);
1607 else
1608 if JazelleAcceptsExecution() then
1609 SwitchToJazelleExecution();
1610 else
1611 SUBARCHITECTURE_DEFINED handler call;
1612 }
1613#endif
1614
Greg Clayton7bc39082011-03-24 23:53:38 +00001615 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001616 {
1617 EmulateInstruction::Context context;
1618 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1619 uint32_t Rm; // the register with the target address
1620 switch (encoding) {
1621 case eEncodingT1:
1622 Rm = Bits32(opcode, 19, 16);
1623 if (BadReg(Rm))
1624 return false;
1625 if (InITBlock() && !LastInITBlock())
1626 return false;
1627 break;
1628 case eEncodingA1:
1629 Rm = Bits32(opcode, 3, 0);
1630 if (Rm == 15)
1631 return false;
1632 break;
1633 default:
1634 return false;
1635 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001636 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001637 addr_t target = ReadCoreReg (Rm, &success);
1638 if (!success)
1639 return false;
1640
Greg Claytonc07d4512011-04-26 23:48:45 +00001641 RegisterInfo dwarf_reg;
1642 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen59e6ab72011-02-24 21:01:20 +00001643 context.SetRegister (dwarf_reg);
1644 if (!BXWritePC(context, target))
1645 return false;
1646 }
1647 return true;
1648}
1649
Johnny Chen0d0148e2011-01-28 02:26:08 +00001650// Set r7 to point to some ip offset.
1651// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001652bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001653EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001654{
1655#if 0
1656 // ARM pseudo code...
1657 if (ConditionPassed())
1658 {
1659 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001660 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001661 if d == 15 then // Can only occur for ARM encoding
1662 ALUWritePC(result); // setflags is always FALSE here
1663 else
1664 R[d] = result;
1665 if setflags then
1666 APSR.N = result<31>;
1667 APSR.Z = IsZeroBit(result);
1668 APSR.C = carry;
1669 APSR.V = overflow;
1670 }
1671#endif
1672
Greg Clayton7bc39082011-03-24 23:53:38 +00001673 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001674 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001675 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001676 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001677 if (!success)
1678 return false;
1679 uint32_t imm32;
1680 switch (encoding) {
1681 case eEncodingA1:
1682 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1683 break;
1684 default:
1685 return false;
1686 }
1687 addr_t ip_offset = imm32;
1688 addr_t addr = ip - ip_offset; // the adjusted ip value
1689
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001690 EmulateInstruction::Context context;
1691 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001692 RegisterInfo dwarf_reg;
1693 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001694 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001695
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001696 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001697 return false;
1698 }
1699 return true;
1700}
1701
1702// Set ip to point to some stack offset.
1703// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001704bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001705EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001706{
1707#if 0
1708 // ARM pseudo code...
1709 if (ConditionPassed())
1710 {
1711 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001712 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001713 if d == 15 then // Can only occur for ARM encoding
1714 ALUWritePC(result); // setflags is always FALSE here
1715 else
1716 R[d] = result;
1717 if setflags then
1718 APSR.N = result<31>;
1719 APSR.Z = IsZeroBit(result);
1720 APSR.C = carry;
1721 APSR.V = overflow;
1722 }
1723#endif
1724
Greg Clayton7bc39082011-03-24 23:53:38 +00001725 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001726 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001727 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001728 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001729 if (!success)
1730 return false;
1731 uint32_t imm32;
1732 switch (encoding) {
1733 case eEncodingA1:
1734 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1735 break;
1736 default:
1737 return false;
1738 }
1739 addr_t sp_offset = imm32;
1740 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1741
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001742 EmulateInstruction::Context context;
1743 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001744 RegisterInfo dwarf_reg;
1745 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001746 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001747
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001748 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001749 return false;
1750 }
1751 return true;
1752}
1753
Johnny Chenc9e747f2011-02-23 01:55:07 +00001754// This instruction subtracts an immediate value from the SP value, and writes
1755// the result to the destination register.
1756//
1757// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001758bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001759EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001760{
1761#if 0
1762 // ARM pseudo code...
1763 if (ConditionPassed())
1764 {
1765 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001766 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001767 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001768 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001769 else
1770 R[d] = result;
1771 if setflags then
1772 APSR.N = result<31>;
1773 APSR.Z = IsZeroBit(result);
1774 APSR.C = carry;
1775 APSR.V = overflow;
1776 }
1777#endif
1778
1779 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001780 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001781 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001782 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001783 if (!success)
1784 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001785
1786 uint32_t Rd;
1787 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001788 uint32_t imm32;
1789 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001790 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001791 Rd = 13;
1792 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001793 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001794 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001795 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001796 Rd = Bits32(opcode, 11, 8);
1797 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001798 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001799 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001800 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001801 if (Rd == 15 && !setflags)
1802 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001803 break;
1804 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001805 Rd = Bits32(opcode, 11, 8);
1806 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001807 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001808 if (Rd == 15)
1809 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001810 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001811 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001812 Rd = Bits32(opcode, 15, 12);
1813 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001814 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001815
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001816 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001817 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001818 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001819 break;
1820 default:
1821 return false;
1822 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001823 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1824
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001825 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001826 if (Rd == 13)
1827 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001828 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1829 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001830 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001831 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001832 }
1833 else
1834 {
1835 context.type = EmulateInstruction::eContextImmediate;
1836 context.SetNoArgs ();
1837 }
1838
1839 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001840 return false;
1841 }
1842 return true;
1843}
1844
Johnny Chen08c25e82011-01-31 18:02:28 +00001845// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001846bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001847EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001848{
1849#if 0
1850 // ARM pseudo code...
1851 if (ConditionPassed())
1852 {
1853 EncodingSpecificOperations();
1854 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1855 address = if index then offset_addr else R[n];
1856 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1857 if wback then R[n] = offset_addr;
1858 }
1859#endif
1860
Greg Clayton107e53d2011-07-06 04:07:21 +00001861 bool conditional = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001862 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +00001863 if (ConditionPassed(opcode, &conditional))
Johnny Chence1ca772011-01-25 01:13:00 +00001864 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001865 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001866 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001867 if (!success)
1868 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001869 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001870 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001871 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1872
1873 bool index;
1874 bool add;
1875 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001876 switch (encoding) {
1877 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001878 Rt = Bits32(opcode, 15, 12);
1879 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001880 Rn = Bits32 (opcode, 19, 16);
1881
1882 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1883 return false;
1884
1885 index = BitIsSet (opcode, 24);
1886 add = BitIsSet (opcode, 23);
1887 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1888
1889 if (wback && ((Rn == 15) || (Rn == Rt)))
1890 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001891 break;
1892 default:
1893 return false;
1894 }
Caroline Tice3e407972011-03-18 19:41:00 +00001895 addr_t offset_addr;
1896 if (add)
1897 offset_addr = sp + imm12;
1898 else
1899 offset_addr = sp - imm12;
1900
1901 addr_t addr;
1902 if (index)
1903 addr = offset_addr;
1904 else
1905 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001906
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001907 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +00001908 if (conditional)
1909 context.type = EmulateInstruction::eContextRegisterStore;
1910 else
1911 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001912 RegisterInfo sp_reg;
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001913 RegisterInfo dwarf_reg;
1914
Greg Claytonc07d4512011-04-26 23:48:45 +00001915 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001916 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1917 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001918 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001919 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001920 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001921 if (!success)
1922 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001923 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001924 return false;
1925 }
1926 else
1927 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001928 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001929 if (!success)
1930 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001931 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001932 return false;
1933 }
1934
Caroline Tice3e407972011-03-18 19:41:00 +00001935
1936 if (wback)
1937 {
1938 context.type = EmulateInstruction::eContextAdjustStackPointer;
1939 context.SetImmediateSigned (addr - sp);
1940 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1941 return false;
1942 }
Johnny Chence1ca772011-01-25 01:13:00 +00001943 }
1944 return true;
1945}
1946
Johnny Chen08c25e82011-01-31 18:02:28 +00001947// Vector Push stores multiple extension registers to the stack.
1948// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001949bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001950EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001951{
1952#if 0
1953 // ARM pseudo code...
1954 if (ConditionPassed())
1955 {
1956 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1957 address = SP - imm32;
1958 SP = SP - imm32;
1959 if single_regs then
1960 for r = 0 to regs-1
1961 MemA[address,4] = S[d+r]; address = address+4;
1962 else
1963 for r = 0 to regs-1
1964 // Store as two word-aligned words in the correct order for current endianness.
1965 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1966 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1967 address = address+8;
1968 }
1969#endif
1970
1971 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +00001972 bool conditional = false;
1973 if (ConditionPassed(opcode, &conditional))
Johnny Chen799dfd02011-01-26 23:14:33 +00001974 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001975 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001976 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001977 if (!success)
1978 return false;
1979 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001980 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001981 uint32_t imm32; // stack offset
1982 uint32_t regs; // number of registers
1983 switch (encoding) {
1984 case eEncodingT1:
1985 case eEncodingA1:
1986 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001987 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001988 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1989 // If UInt(imm8) is odd, see "FSTMX".
1990 regs = Bits32(opcode, 7, 0) / 2;
1991 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1992 if (regs == 0 || regs > 16 || (d + regs) > 32)
1993 return false;
1994 break;
1995 case eEncodingT2:
1996 case eEncodingA2:
1997 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001998 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001999 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2000 regs = Bits32(opcode, 7, 0);
2001 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2002 if (regs == 0 || regs > 16 || (d + regs) > 32)
2003 return false;
2004 break;
2005 default:
2006 return false;
2007 }
2008 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2009 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2010 addr_t sp_offset = imm32;
2011 addr_t addr = sp - sp_offset;
2012 uint32_t i;
2013
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002014 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +00002015 if (conditional)
2016 context.type = EmulateInstruction::eContextRegisterStore;
2017 else
2018 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002019 RegisterInfo dwarf_reg;
2020 RegisterInfo sp_reg;
2021 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002022 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00002023 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002024 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002025 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00002026 // uint64_t to accommodate 64-bit registers.
Greg Clayton061b79d2011-05-09 20:18:18 +00002027 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00002028 if (!success)
2029 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002030 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00002031 return false;
2032 addr += reg_byte_size;
2033 }
2034
2035 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002036 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00002037
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002038 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00002039 return false;
2040 }
2041 return true;
2042}
2043
Johnny Chen587a0a42011-02-01 18:35:28 +00002044// Vector Pop loads multiple extension registers from the stack.
2045// It also updates SP to point just above the loaded data.
2046bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002047EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00002048{
2049#if 0
2050 // ARM pseudo code...
2051 if (ConditionPassed())
2052 {
2053 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2054 address = SP;
2055 SP = SP + imm32;
2056 if single_regs then
2057 for r = 0 to regs-1
2058 S[d+r] = MemA[address,4]; address = address+4;
2059 else
2060 for r = 0 to regs-1
2061 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2062 // Combine the word-aligned words in the correct order for current endianness.
2063 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2064 }
2065#endif
2066
2067 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +00002068 bool conditional = false;
2069 if (ConditionPassed(opcode, &conditional))
Johnny Chen587a0a42011-02-01 18:35:28 +00002070 {
2071 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002072 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002073 if (!success)
2074 return false;
2075 bool single_regs;
2076 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2077 uint32_t imm32; // stack offset
2078 uint32_t regs; // number of registers
2079 switch (encoding) {
2080 case eEncodingT1:
2081 case eEncodingA1:
2082 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002083 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002084 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2085 // If UInt(imm8) is odd, see "FLDMX".
2086 regs = Bits32(opcode, 7, 0) / 2;
2087 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2088 if (regs == 0 || regs > 16 || (d + regs) > 32)
2089 return false;
2090 break;
2091 case eEncodingT2:
2092 case eEncodingA2:
2093 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002094 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002095 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2096 regs = Bits32(opcode, 7, 0);
2097 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2098 if (regs == 0 || regs > 16 || (d + regs) > 32)
2099 return false;
2100 break;
2101 default:
2102 return false;
2103 }
2104 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2105 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2106 addr_t sp_offset = imm32;
2107 addr_t addr = sp;
2108 uint32_t i;
2109 uint64_t data; // uint64_t to accomodate 64-bit registers.
2110
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002111 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +00002112 if (conditional)
2113 context.type = EmulateInstruction::eContextRegisterLoad;
2114 else
2115 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002116 RegisterInfo dwarf_reg;
2117 RegisterInfo sp_reg;
2118 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002119 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002120 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002121 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002122 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002123 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002124 if (!success)
2125 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +00002126 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002127 return false;
2128 addr += reg_byte_size;
2129 }
2130
2131 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002132 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002133
2134 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2135 return false;
2136 }
2137 return true;
2138}
2139
Johnny Chenb77be412011-02-04 00:40:18 +00002140// SVC (previously SWI)
2141bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002142EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002143{
2144#if 0
2145 // ARM pseudo code...
2146 if (ConditionPassed())
2147 {
2148 EncodingSpecificOperations();
2149 CallSupervisor();
2150 }
2151#endif
2152
2153 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002154
Greg Clayton7bc39082011-03-24 23:53:38 +00002155 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002156 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002157 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002158 addr_t lr; // next instruction address
2159 if (!success)
2160 return false;
2161 uint32_t imm32; // the immediate constant
2162 uint32_t mode; // ARM or Thumb mode
2163 switch (encoding) {
2164 case eEncodingT1:
2165 lr = (pc + 2) | 1u; // return address
2166 imm32 = Bits32(opcode, 7, 0);
2167 mode = eModeThumb;
2168 break;
2169 case eEncodingA1:
2170 lr = pc + 4; // return address
2171 imm32 = Bits32(opcode, 23, 0);
2172 mode = eModeARM;
2173 break;
2174 default:
2175 return false;
2176 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002177
2178 EmulateInstruction::Context context;
2179 context.type = EmulateInstruction::eContextSupervisorCall;
Greg Claytonc07d4512011-04-26 23:48:45 +00002180 context.SetISAAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002181 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2182 return false;
2183 }
2184 return true;
2185}
2186
Johnny Chenc315f862011-02-05 00:46:10 +00002187// If Then makes up to four following instructions (the IT block) conditional.
2188bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002189EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002190{
2191#if 0
2192 // ARM pseudo code...
2193 EncodingSpecificOperations();
2194 ITSTATE.IT<7:0> = firstcond:mask;
2195#endif
2196
Johnny Chenc315f862011-02-05 00:46:10 +00002197 m_it_session.InitIT(Bits32(opcode, 7, 0));
2198 return true;
2199}
2200
Greg Clayton04d397c2011-05-23 18:04:09 +00002201bool
2202EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding)
2203{
2204 // NOP, nothing to do...
2205 return true;
2206}
2207
Johnny Chen3b620b32011-02-07 20:11:47 +00002208// Branch causes a branch to a target address.
2209bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002210EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002211{
2212#if 0
2213 // ARM pseudo code...
2214 if (ConditionPassed())
2215 {
2216 EncodingSpecificOperations();
2217 BranchWritePC(PC + imm32);
2218 }
2219#endif
2220
2221 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002222
Greg Clayton7bc39082011-03-24 23:53:38 +00002223 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002224 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002225 EmulateInstruction::Context context;
2226 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002227 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002228 if (!success)
2229 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002230 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002231 int32_t imm32; // PC-relative offset
2232 switch (encoding) {
2233 case eEncodingT1:
2234 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2235 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002236 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002237 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002238 break;
2239 case eEncodingT2:
2240 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002241 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002242 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002243 break;
2244 case eEncodingT3:
2245 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2246 {
Johnny Chenbd599902011-02-10 21:39:01 +00002247 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002248 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002249 uint32_t J1 = Bit32(opcode, 13);
2250 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002251 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002252 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002253 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002254 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002255 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002256 break;
2257 }
2258 case eEncodingT4:
2259 {
Johnny Chenbd599902011-02-10 21:39:01 +00002260 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002261 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002262 uint32_t J1 = Bit32(opcode, 13);
2263 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002264 uint32_t imm11 = Bits32(opcode, 10, 0);
2265 uint32_t I1 = !(J1 ^ S);
2266 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002267 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002268 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002269 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002270 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002271 break;
2272 }
2273 case eEncodingA1:
2274 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002275 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002276 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002277 break;
2278 default:
2279 return false;
2280 }
2281 if (!BranchWritePC(context, target))
2282 return false;
2283 }
2284 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002285}
2286
Johnny Chen53ebab72011-02-08 23:21:57 +00002287// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2288// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2289// CBNZ, CBZ
2290bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002291EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002292{
2293#if 0
2294 // ARM pseudo code...
2295 EncodingSpecificOperations();
2296 if nonzero ^ IsZero(R[n]) then
2297 BranchWritePC(PC + imm32);
2298#endif
2299
2300 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002301
2302 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002303 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002304 if (!success)
2305 return false;
2306
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002307 EmulateInstruction::Context context;
2308 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002309 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002310 if (!success)
2311 return false;
2312
2313 addr_t target; // target address
2314 uint32_t imm32; // PC-relative offset to branch forward
2315 bool nonzero;
2316 switch (encoding) {
2317 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002318 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002319 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002320 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002321 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002322 break;
2323 default:
2324 return false;
2325 }
2326 if (nonzero ^ (reg_val == 0))
2327 if (!BranchWritePC(context, target))
2328 return false;
2329
2330 return true;
2331}
2332
Johnny Chen60299ec2011-02-17 19:34:27 +00002333// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2334// A base register provides a pointer to the table, and a second register supplies an index into the table.
2335// The branch length is twice the value of the byte returned from the table.
2336//
2337// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2338// A base register provides a pointer to the table, and a second register supplies an index into the table.
2339// The branch length is twice the value of the halfword returned from the table.
2340// TBB, TBH
2341bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002342EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002343{
2344#if 0
2345 // ARM pseudo code...
2346 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2347 if is_tbh then
2348 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2349 else
2350 halfwords = UInt(MemU[R[n]+R[m], 1]);
2351 BranchWritePC(PC + 2*halfwords);
2352#endif
2353
2354 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002355
2356 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2357 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2358 bool is_tbh; // true if table branch halfword
2359 switch (encoding) {
2360 case eEncodingT1:
2361 Rn = Bits32(opcode, 19, 16);
2362 Rm = Bits32(opcode, 3, 0);
2363 is_tbh = BitIsSet(opcode, 4);
2364 if (Rn == 13 || BadReg(Rm))
2365 return false;
2366 if (InITBlock() && !LastInITBlock())
2367 return false;
2368 break;
2369 default:
2370 return false;
2371 }
2372
2373 // Read the address of the table from the operand register Rn.
2374 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002375 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002376 if (!success)
2377 return false;
2378
2379 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002380 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002381 if (!success)
2382 return false;
2383
2384 // the offsetted table address
2385 addr_t addr = base + (is_tbh ? index*2 : index);
2386
2387 // PC-relative offset to branch forward
2388 EmulateInstruction::Context context;
2389 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002390 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002391 if (!success)
2392 return false;
2393
Johnny Chene39f22d2011-02-19 01:36:13 +00002394 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002395 if (!success)
2396 return false;
2397
2398 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002399 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002400 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Greg Claytonc07d4512011-04-26 23:48:45 +00002401 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
Johnny Chen60299ec2011-02-17 19:34:27 +00002402
2403 if (!BranchWritePC(context, target))
2404 return false;
2405
2406 return true;
2407}
2408
Caroline Ticedcc11b32011-03-02 23:57:02 +00002409// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2410// It can optionally update the condition flags based on the result.
2411bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002412EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002413{
2414#if 0
2415 if ConditionPassed() then
2416 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002417 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002418 R[d] = result;
2419 if setflags then
2420 APSR.N = result<31>;
2421 APSR.Z = IsZeroBit(result);
2422 APSR.C = carry;
2423 APSR.V = overflow;
2424#endif
2425
2426 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002427
Greg Clayton7bc39082011-03-24 23:53:38 +00002428 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002429 {
2430 uint32_t d;
2431 uint32_t n;
2432 bool setflags;
2433 uint32_t imm32;
2434 uint32_t carry_out;
2435
2436 //EncodingSpecificOperations();
2437 switch (encoding)
2438 {
2439 case eEncodingT1:
2440 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2441 d = Bits32 (opcode, 2, 0);
2442 n = Bits32 (opcode, 5, 3);
2443 setflags = !InITBlock();
2444 imm32 = Bits32 (opcode, 8,6);
2445
2446 break;
2447
2448 case eEncodingT2:
2449 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2450 d = Bits32 (opcode, 10, 8);
2451 n = Bits32 (opcode, 10, 8);
2452 setflags = !InITBlock();
2453 imm32 = Bits32 (opcode, 7, 0);
2454
2455 break;
2456
2457 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002458 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2459 // if Rn == '1101' then SEE ADD (SP plus immediate);
2460 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002461 d = Bits32 (opcode, 11, 8);
2462 n = Bits32 (opcode, 19, 16);
2463 setflags = BitIsSet (opcode, 20);
2464 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2465
2466 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2467 if (BadReg (d) || (n == 15))
2468 return false;
2469
2470 break;
2471
2472 case eEncodingT4:
2473 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002474 // if Rn == '1111' then SEE ADR;
2475 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002476 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2477 d = Bits32 (opcode, 11, 8);
2478 n = Bits32 (opcode, 19, 16);
2479 setflags = false;
2480 uint32_t i = Bit32 (opcode, 26);
2481 uint32_t imm3 = Bits32 (opcode, 14, 12);
2482 uint32_t imm8 = Bits32 (opcode, 7, 0);
2483 imm32 = (i << 11) | (imm3 << 8) | imm8;
2484
2485 // if BadReg(d) then UNPREDICTABLE;
2486 if (BadReg (d))
2487 return false;
2488
2489 break;
2490 }
2491 default:
2492 return false;
2493 }
2494
2495 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2496 if (!success)
2497 return false;
2498
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002499 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002500 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2501
Greg Claytonc07d4512011-04-26 23:48:45 +00002502 RegisterInfo reg_n;
2503 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002504
2505 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002506 context.type = eContextArithmetic;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002507 context.SetRegisterPlusOffset (reg_n, imm32);
2508
2509 //R[d] = result;
2510 //if setflags then
2511 //APSR.N = result<31>;
2512 //APSR.Z = IsZeroBit(result);
2513 //APSR.C = carry;
2514 //APSR.V = overflow;
2515 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2516 return false;
2517
2518 }
2519 return true;
2520}
2521
Johnny Chen8fa20592011-02-18 01:22:22 +00002522// This instruction adds an immediate value to a register value, and writes the result to the destination
2523// register. It can optionally update the condition flags based on the result.
2524bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002525EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002526{
2527#if 0
2528 // ARM pseudo code...
2529 if ConditionPassed() then
2530 EncodingSpecificOperations();
2531 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2532 if d == 15 then
2533 ALUWritePC(result); // setflags is always FALSE here
2534 else
2535 R[d] = result;
2536 if setflags then
2537 APSR.N = result<31>;
2538 APSR.Z = IsZeroBit(result);
2539 APSR.C = carry;
2540 APSR.V = overflow;
2541#endif
2542
2543 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002544
Greg Clayton7bc39082011-03-24 23:53:38 +00002545 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002546 {
2547 uint32_t Rd, Rn;
2548 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2549 bool setflags;
2550 switch (encoding)
2551 {
2552 case eEncodingA1:
2553 Rd = Bits32(opcode, 15, 12);
2554 Rn = Bits32(opcode, 19, 16);
2555 setflags = BitIsSet(opcode, 20);
2556 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2557 break;
2558 default:
2559 return false;
2560 }
2561
Johnny Chen8fa20592011-02-18 01:22:22 +00002562 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002563 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002564 if (!success)
2565 return false;
2566
2567 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2568
2569 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002570 context.type = eContextArithmetic;
2571 RegisterInfo dwarf_reg;
2572 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00002573 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002574
2575 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2576 return false;
2577 }
2578 return true;
2579}
2580
Johnny Chend761dcf2011-02-17 22:03:29 +00002581// This instruction adds a register value and an optionally-shifted register value, and writes the result
2582// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002583bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002584EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002585{
2586#if 0
2587 // ARM pseudo code...
2588 if ConditionPassed() then
2589 EncodingSpecificOperations();
2590 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2591 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2592 if d == 15 then
2593 ALUWritePC(result); // setflags is always FALSE here
2594 else
2595 R[d] = result;
2596 if setflags then
2597 APSR.N = result<31>;
2598 APSR.Z = IsZeroBit(result);
2599 APSR.C = carry;
2600 APSR.V = overflow;
2601#endif
2602
2603 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002604
Greg Clayton7bc39082011-03-24 23:53:38 +00002605 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002606 {
2607 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002608 ARM_ShifterType shift_t;
2609 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002610 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002611 switch (encoding)
2612 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002613 case eEncodingT1:
2614 Rd = Bits32(opcode, 2, 0);
2615 Rn = Bits32(opcode, 5, 3);
2616 Rm = Bits32(opcode, 8, 6);
2617 setflags = !InITBlock();
2618 shift_t = SRType_LSL;
2619 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002620 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002621 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002622 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002623 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002624 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002625 shift_t = SRType_LSL;
2626 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002627 if (Rn == 15 && Rm == 15)
2628 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002629 if (Rd == 15 && InITBlock() && !LastInITBlock())
2630 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002631 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002632 case eEncodingA1:
2633 Rd = Bits32(opcode, 15, 12);
2634 Rn = Bits32(opcode, 19, 16);
2635 Rm = Bits32(opcode, 3, 0);
2636 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002637 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002638 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002639 default:
2640 return false;
2641 }
2642
Johnny Chen26863dc2011-02-09 23:43:29 +00002643 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002644 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002645 if (!success)
2646 return false;
2647
2648 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002649 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002650 if (!success)
2651 return false;
2652
Johnny Chena4438a72011-06-02 22:50:51 +00002653 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2654 if (!success)
2655 return false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002656 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002657
2658 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002659 context.type = eContextArithmetic;
2660 RegisterInfo op1_reg;
2661 RegisterInfo op2_reg;
2662 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2663 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00002664 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002665
Johnny Chen10530c22011-02-17 22:37:12 +00002666 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002667 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002668 }
2669 return true;
2670}
2671
Johnny Chen34075cb2011-02-22 01:56:31 +00002672// Compare Negative (immediate) adds a register value and an immediate value.
2673// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002674bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002675EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002676{
2677#if 0
2678 // ARM pseudo code...
2679 if ConditionPassed() then
2680 EncodingSpecificOperations();
2681 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2682 APSR.N = result<31>;
2683 APSR.Z = IsZeroBit(result);
2684 APSR.C = carry;
2685 APSR.V = overflow;
2686#endif
2687
2688 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002689
2690 uint32_t Rn; // the first operand
2691 uint32_t imm32; // the immediate value to be compared with
2692 switch (encoding) {
2693 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002694 Rn = Bits32(opcode, 19, 16);
2695 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2696 if (Rn == 15)
2697 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002698 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002699 case eEncodingA1:
2700 Rn = Bits32(opcode, 19, 16);
2701 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2702 break;
2703 default:
2704 return false;
2705 }
2706 // Read the register value from the operand register Rn.
2707 uint32_t reg_val = ReadCoreReg(Rn, &success);
2708 if (!success)
2709 return false;
2710
Johnny Chen078fbc62011-02-22 19:48:22 +00002711 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002712
2713 EmulateInstruction::Context context;
2714 context.type = EmulateInstruction::eContextImmediate;
2715 context.SetNoArgs ();
2716 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2717 return false;
2718
2719 return true;
2720}
2721
2722// Compare Negative (register) adds a register value and an optionally-shifted register value.
2723// It updates the condition flags based on the result, and discards the result.
2724bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002725EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002726{
2727#if 0
2728 // ARM pseudo code...
2729 if ConditionPassed() then
2730 EncodingSpecificOperations();
2731 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2732 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2733 APSR.N = result<31>;
2734 APSR.Z = IsZeroBit(result);
2735 APSR.C = carry;
2736 APSR.V = overflow;
2737#endif
2738
2739 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002740
2741 uint32_t Rn; // the first operand
2742 uint32_t Rm; // the second operand
2743 ARM_ShifterType shift_t;
2744 uint32_t shift_n; // the shift applied to the value read from Rm
2745 switch (encoding) {
2746 case eEncodingT1:
2747 Rn = Bits32(opcode, 2, 0);
2748 Rm = Bits32(opcode, 5, 3);
2749 shift_t = SRType_LSL;
2750 shift_n = 0;
2751 break;
2752 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002753 Rn = Bits32(opcode, 19, 16);
2754 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002755 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002756 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2757 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002758 return false;
2759 break;
2760 case eEncodingA1:
2761 Rn = Bits32(opcode, 19, 16);
2762 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002763 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002764 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002765 default:
2766 return false;
2767 }
2768 // Read the register value from register Rn.
2769 uint32_t val1 = ReadCoreReg(Rn, &success);
2770 if (!success)
2771 return false;
2772
2773 // Read the register value from register Rm.
2774 uint32_t val2 = ReadCoreReg(Rm, &success);
2775 if (!success)
2776 return false;
2777
Johnny Chena4438a72011-06-02 22:50:51 +00002778 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2779 if (!success)
2780 return false;
Johnny Chen078fbc62011-02-22 19:48:22 +00002781 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002782
2783 EmulateInstruction::Context context;
2784 context.type = EmulateInstruction::eContextImmediate;
2785 context.SetNoArgs();
2786 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2787 return false;
2788
2789 return true;
2790}
2791
2792// Compare (immediate) subtracts an immediate value from a register value.
2793// It updates the condition flags based on the result, and discards the result.
2794bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002795EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002796{
2797#if 0
2798 // ARM pseudo code...
2799 if ConditionPassed() then
2800 EncodingSpecificOperations();
2801 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2802 APSR.N = result<31>;
2803 APSR.Z = IsZeroBit(result);
2804 APSR.C = carry;
2805 APSR.V = overflow;
2806#endif
2807
2808 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002809
2810 uint32_t Rn; // the first operand
2811 uint32_t imm32; // the immediate value to be compared with
2812 switch (encoding) {
2813 case eEncodingT1:
2814 Rn = Bits32(opcode, 10, 8);
2815 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002816 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002817 case eEncodingT2:
2818 Rn = Bits32(opcode, 19, 16);
2819 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2820 if (Rn == 15)
2821 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002822 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002823 case eEncodingA1:
2824 Rn = Bits32(opcode, 19, 16);
2825 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002826 break;
2827 default:
2828 return false;
2829 }
2830 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002831 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002832 if (!success)
2833 return false;
2834
Johnny Chen10530c22011-02-17 22:37:12 +00002835 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2836
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002837 EmulateInstruction::Context context;
2838 context.type = EmulateInstruction::eContextImmediate;
2839 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002840 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2841 return false;
2842
Johnny Chend4dc4442011-02-11 02:02:56 +00002843 return true;
2844}
2845
Johnny Chen34075cb2011-02-22 01:56:31 +00002846// Compare (register) subtracts an optionally-shifted register value from a register value.
2847// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002848bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002849EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002850{
2851#if 0
2852 // ARM pseudo code...
2853 if ConditionPassed() then
2854 EncodingSpecificOperations();
2855 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2856 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2857 APSR.N = result<31>;
2858 APSR.Z = IsZeroBit(result);
2859 APSR.C = carry;
2860 APSR.V = overflow;
2861#endif
2862
2863 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002864
2865 uint32_t Rn; // the first operand
2866 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002867 ARM_ShifterType shift_t;
2868 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002869 switch (encoding) {
2870 case eEncodingT1:
2871 Rn = Bits32(opcode, 2, 0);
2872 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002873 shift_t = SRType_LSL;
2874 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002875 break;
2876 case eEncodingT2:
2877 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2878 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002879 shift_t = SRType_LSL;
2880 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002881 if (Rn < 8 && Rm < 8)
2882 return false;
2883 if (Rn == 15 || Rm == 15)
2884 return false;
2885 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002886 case eEncodingA1:
2887 Rn = Bits32(opcode, 19, 16);
2888 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002889 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002890 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002891 default:
2892 return false;
2893 }
2894 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002895 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002896 if (!success)
2897 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002898
Johnny Chene4a4d302011-02-11 21:53:58 +00002899 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002900 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002901 if (!success)
2902 return false;
2903
Johnny Chena4438a72011-06-02 22:50:51 +00002904 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2905 if (!success)
2906 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002907 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002908
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002909 EmulateInstruction::Context context;
2910 context.type = EmulateInstruction::eContextImmediate;
2911 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002912 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2913 return false;
2914
Johnny Chene4a4d302011-02-11 21:53:58 +00002915 return true;
2916}
2917
Johnny Chen82f16aa2011-02-15 20:10:55 +00002918// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2919// shifting in copies of its sign bit, and writes the result to the destination register. It can
2920// optionally update the condition flags based on the result.
2921bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002922EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002923{
2924#if 0
2925 // ARM pseudo code...
2926 if ConditionPassed() then
2927 EncodingSpecificOperations();
2928 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2929 if d == 15 then // Can only occur for ARM encoding
2930 ALUWritePC(result); // setflags is always FALSE here
2931 else
2932 R[d] = result;
2933 if setflags then
2934 APSR.N = result<31>;
2935 APSR.Z = IsZeroBit(result);
2936 APSR.C = carry;
2937 // APSR.V unchanged
2938#endif
2939
Greg Clayton7bc39082011-03-24 23:53:38 +00002940 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002941}
2942
2943// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2944// shifting in copies of its sign bit, and writes the result to the destination register.
2945// The variable number of bits is read from the bottom byte of a register. It can optionally update
2946// the condition flags based on the result.
2947bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002948EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002949{
2950#if 0
2951 // ARM pseudo code...
2952 if ConditionPassed() then
2953 EncodingSpecificOperations();
2954 shift_n = UInt(R[m]<7:0>);
2955 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2956 R[d] = result;
2957 if setflags then
2958 APSR.N = result<31>;
2959 APSR.Z = IsZeroBit(result);
2960 APSR.C = carry;
2961 // APSR.V unchanged
2962#endif
2963
Greg Clayton7bc39082011-03-24 23:53:38 +00002964 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002965}
2966
2967// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2968// shifting in zeros, and writes the result to the destination register. It can optionally
2969// update the condition flags based on the result.
2970bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002971EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002972{
2973#if 0
2974 // ARM pseudo code...
2975 if ConditionPassed() then
2976 EncodingSpecificOperations();
2977 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2978 if d == 15 then // Can only occur for ARM encoding
2979 ALUWritePC(result); // setflags is always FALSE here
2980 else
2981 R[d] = result;
2982 if setflags then
2983 APSR.N = result<31>;
2984 APSR.Z = IsZeroBit(result);
2985 APSR.C = carry;
2986 // APSR.V unchanged
2987#endif
2988
Greg Clayton7bc39082011-03-24 23:53:38 +00002989 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002990}
2991
2992// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2993// shifting in zeros, and writes the result to the destination register. The variable number
2994// of bits is read from the bottom byte of a register. It can optionally update the condition
2995// flags based on the result.
2996bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002997EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002998{
2999#if 0
3000 // ARM pseudo code...
3001 if ConditionPassed() then
3002 EncodingSpecificOperations();
3003 shift_n = UInt(R[m]<7:0>);
3004 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3005 R[d] = result;
3006 if setflags then
3007 APSR.N = result<31>;
3008 APSR.Z = IsZeroBit(result);
3009 APSR.C = carry;
3010 // APSR.V unchanged
3011#endif
3012
Greg Clayton7bc39082011-03-24 23:53:38 +00003013 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00003014}
3015
3016// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
3017// shifting in zeros, and writes the result to the destination register. It can optionally
3018// update the condition flags based on the result.
3019bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003020EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003021{
3022#if 0
3023 // ARM pseudo code...
3024 if ConditionPassed() then
3025 EncodingSpecificOperations();
3026 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3027 if d == 15 then // Can only occur for ARM encoding
3028 ALUWritePC(result); // setflags is always FALSE here
3029 else
3030 R[d] = result;
3031 if setflags then
3032 APSR.N = result<31>;
3033 APSR.Z = IsZeroBit(result);
3034 APSR.C = carry;
3035 // APSR.V unchanged
3036#endif
3037
Greg Clayton7bc39082011-03-24 23:53:38 +00003038 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003039}
3040
3041// Logical Shift Right (register) shifts a register value right by a variable number of bits,
3042// shifting in zeros, and writes the result to the destination register. The variable number
3043// of bits is read from the bottom byte of a register. It can optionally update the condition
3044// flags based on the result.
3045bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003046EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003047{
3048#if 0
3049 // ARM pseudo code...
3050 if ConditionPassed() then
3051 EncodingSpecificOperations();
3052 shift_n = UInt(R[m]<7:0>);
3053 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3054 R[d] = result;
3055 if setflags then
3056 APSR.N = result<31>;
3057 APSR.Z = IsZeroBit(result);
3058 APSR.C = carry;
3059 // APSR.V unchanged
3060#endif
3061
Greg Clayton7bc39082011-03-24 23:53:38 +00003062 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003063}
3064
Johnny Cheneeab4852011-02-16 22:14:44 +00003065// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3066// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3067// It can optionally update the condition flags based on the result.
3068bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003069EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003070{
3071#if 0
3072 // ARM pseudo code...
3073 if ConditionPassed() then
3074 EncodingSpecificOperations();
3075 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3076 if d == 15 then // Can only occur for ARM encoding
3077 ALUWritePC(result); // setflags is always FALSE here
3078 else
3079 R[d] = result;
3080 if setflags then
3081 APSR.N = result<31>;
3082 APSR.Z = IsZeroBit(result);
3083 APSR.C = carry;
3084 // APSR.V unchanged
3085#endif
3086
Greg Clayton7bc39082011-03-24 23:53:38 +00003087 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003088}
3089
3090// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3091// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3092// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3093// flags based on the result.
3094bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003095EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003096{
3097#if 0
3098 // ARM pseudo code...
3099 if ConditionPassed() then
3100 EncodingSpecificOperations();
3101 shift_n = UInt(R[m]<7:0>);
3102 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3103 R[d] = result;
3104 if setflags then
3105 APSR.N = result<31>;
3106 APSR.Z = IsZeroBit(result);
3107 APSR.C = carry;
3108 // APSR.V unchanged
3109#endif
3110
Greg Clayton7bc39082011-03-24 23:53:38 +00003111 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003112}
3113
3114// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3115// with the carry flag shifted into bit [31].
3116//
3117// RRX can optionally update the condition flags based on the result.
3118// In that case, bit [0] is shifted into the carry flag.
3119bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003120EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003121{
3122#if 0
3123 // ARM pseudo code...
3124 if ConditionPassed() then
3125 EncodingSpecificOperations();
3126 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3127 if d == 15 then // Can only occur for ARM encoding
3128 ALUWritePC(result); // setflags is always FALSE here
3129 else
3130 R[d] = result;
3131 if setflags then
3132 APSR.N = result<31>;
3133 APSR.Z = IsZeroBit(result);
3134 APSR.C = carry;
3135 // APSR.V unchanged
3136#endif
3137
Greg Clayton7bc39082011-03-24 23:53:38 +00003138 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003139}
3140
Johnny Chen41a0a152011-02-16 01:27:54 +00003141bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003142EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003143{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003144// assert(shift_type == SRType_ASR
3145// || shift_type == SRType_LSL
3146// || shift_type == SRType_LSR
3147// || shift_type == SRType_ROR
3148// || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003149
Johnny Chen82f16aa2011-02-15 20:10:55 +00003150 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003151
Greg Clayton7bc39082011-03-24 23:53:38 +00003152 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003153 {
Johnny Chene7f89532011-02-15 23:22:46 +00003154 uint32_t Rd; // the destination register
3155 uint32_t Rm; // the first operand register
3156 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003157 uint32_t carry; // the carry bit after the shift operation
3158 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003159
3160 // Special case handling!
3161 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003162 ARMEncoding use_encoding = encoding;
3163 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003164 {
3165 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3166 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003167 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003168 }
3169
Greg Clayton7bc39082011-03-24 23:53:38 +00003170 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003171 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003172 // Due to the above special case handling!
Johnny Chen6cc60972011-06-02 23:07:03 +00003173 if (shift_type == SRType_ROR)
3174 return false;
Johnny Cheneeab4852011-02-16 22:14:44 +00003175
Johnny Chen82f16aa2011-02-15 20:10:55 +00003176 Rd = Bits32(opcode, 2, 0);
3177 Rm = Bits32(opcode, 5, 3);
3178 setflags = !InITBlock();
3179 imm5 = Bits32(opcode, 10, 6);
3180 break;
3181 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003182 // A8.6.141 RRX
Johnny Chen6cc60972011-06-02 23:07:03 +00003183 // There's no imm form of RRX instructions.
3184 if (shift_type == SRType_RRX)
3185 return false;
Johnny Cheneeab4852011-02-16 22:14:44 +00003186
Johnny Chen82f16aa2011-02-15 20:10:55 +00003187 Rd = Bits32(opcode, 11, 8);
3188 Rm = Bits32(opcode, 3, 0);
3189 setflags = BitIsSet(opcode, 20);
3190 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3191 if (BadReg(Rd) || BadReg(Rm))
3192 return false;
3193 break;
3194 case eEncodingA1:
3195 Rd = Bits32(opcode, 15, 12);
3196 Rm = Bits32(opcode, 3, 0);
3197 setflags = BitIsSet(opcode, 20);
3198 imm5 = Bits32(opcode, 11, 7);
3199 break;
3200 default:
3201 return false;
3202 }
3203
Johnny Cheneeab4852011-02-16 22:14:44 +00003204 // A8.6.139 ROR (immediate)
3205 if (shift_type == SRType_ROR && imm5 == 0)
3206 shift_type = SRType_RRX;
3207
Johnny Chen82f16aa2011-02-15 20:10:55 +00003208 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003209 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003210 if (!success)
3211 return false;
3212
Johnny Cheneeab4852011-02-16 22:14:44 +00003213 // Decode the shift amount if not RRX.
3214 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003215
Johnny Chena4438a72011-06-02 22:50:51 +00003216 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3217 if (!success)
3218 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003219
3220 // The context specifies that an immediate is to be moved into Rd.
3221 EmulateInstruction::Context context;
3222 context.type = EmulateInstruction::eContextImmediate;
3223 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003224
Johnny Chen10530c22011-02-17 22:37:12 +00003225 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003226 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003227 }
3228 return true;
3229}
3230
Johnny Chene7f89532011-02-15 23:22:46 +00003231bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003232EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003233{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003234 // assert(shift_type == SRType_ASR
3235 // || shift_type == SRType_LSL
3236 // || shift_type == SRType_LSR
3237 // || shift_type == SRType_ROR);
Johnny Chene7f89532011-02-15 23:22:46 +00003238
3239 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003240
Greg Clayton7bc39082011-03-24 23:53:38 +00003241 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003242 {
3243 uint32_t Rd; // the destination register
3244 uint32_t Rn; // the first operand register
3245 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3246 uint32_t carry; // the carry bit after the shift operation
3247 bool setflags;
3248 switch (encoding) {
3249 case eEncodingT1:
3250 Rd = Bits32(opcode, 2, 0);
3251 Rn = Rd;
3252 Rm = Bits32(opcode, 5, 3);
3253 setflags = !InITBlock();
3254 break;
3255 case eEncodingT2:
3256 Rd = Bits32(opcode, 11, 8);
3257 Rn = Bits32(opcode, 19, 16);
3258 Rm = Bits32(opcode, 3, 0);
3259 setflags = BitIsSet(opcode, 20);
3260 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3261 return false;
3262 break;
3263 case eEncodingA1:
3264 Rd = Bits32(opcode, 15, 12);
3265 Rn = Bits32(opcode, 3, 0);
3266 Rm = Bits32(opcode, 11, 8);
3267 setflags = BitIsSet(opcode, 20);
3268 if (Rd == 15 || Rn == 15 || Rm == 15)
3269 return false;
3270 break;
3271 default:
3272 return false;
3273 }
3274
3275 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003276 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003277 if (!success)
3278 return false;
3279 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003280 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003281 if (!success)
3282 return false;
3283
3284 // Get the shift amount.
3285 uint32_t amt = Bits32(val, 7, 0);
3286
Johnny Chena4438a72011-06-02 22:50:51 +00003287 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3288 if (!success)
3289 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003290
3291 // The context specifies that an immediate is to be moved into Rd.
3292 EmulateInstruction::Context context;
3293 context.type = EmulateInstruction::eContextImmediate;
3294 context.SetNoArgs ();
3295
Johnny Chen10530c22011-02-17 22:37:12 +00003296 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003297 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003298 }
3299 return true;
3300}
3301
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003302// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003303// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003304// can be written back to the base register.
3305bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003306EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003307{
3308#if 0
3309 // ARM pseudo code...
3310 if ConditionPassed()
3311 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3312 address = R[n];
3313
3314 for i = 0 to 14
3315 if registers<i> == '1' then
3316 R[i] = MemA[address, 4]; address = address + 4;
3317 if registers<15> == '1' then
3318 LoadWritePC (MemA[address, 4]);
3319
3320 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3321 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3322
3323#endif
3324
3325 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +00003326 bool conditional = false;
3327 if (ConditionPassed(opcode, &conditional))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003328 {
3329 uint32_t n;
3330 uint32_t registers = 0;
3331 bool wback;
3332 const uint32_t addr_byte_size = GetAddressByteSize();
3333 switch (encoding)
3334 {
3335 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003336 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003337 n = Bits32 (opcode, 10, 8);
3338 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003339 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003340 wback = BitIsClear (registers, n);
3341 // if BitCount(registers) < 1 then UNPREDICTABLE;
3342 if (BitCount(registers) < 1)
3343 return false;
3344 break;
3345 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003346 // if W == '1' && Rn == '1101' then SEE POP;
3347 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003348 n = Bits32 (opcode, 19, 16);
3349 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003350 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003351 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003352
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003353 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003354 if ((n == 15)
3355 || (BitCount (registers) < 2)
3356 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3357 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003358
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003359 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003360 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003361 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003362
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003363 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003364 if (wback
3365 && BitIsSet (registers, n))
3366 return false;
3367 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003368
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003369 case eEncodingA1:
3370 n = Bits32 (opcode, 19, 16);
3371 registers = Bits32 (opcode, 15, 0);
3372 wback = BitIsSet (opcode, 21);
3373 if ((n == 15)
3374 || (BitCount (registers) < 1))
3375 return false;
3376 break;
3377 default:
3378 return false;
3379 }
3380
3381 int32_t offset = 0;
3382 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3383 if (!success)
3384 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003385
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003386 EmulateInstruction::Context context;
3387 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003388 RegisterInfo dwarf_reg;
3389 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003390 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003391
3392 for (int i = 0; i < 14; ++i)
3393 {
3394 if (BitIsSet (registers, i))
3395 {
Caroline Tice85aab332011-02-08 23:56:10 +00003396 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003397 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003398 if (wback && (n == 13)) // Pop Instruction
Greg Clayton107e53d2011-07-06 04:07:21 +00003399 {
3400 if (conditional)
3401 context.type = EmulateInstruction::eContextRegisterLoad;
3402 else
3403 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3404 }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003405
3406 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003407 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003408 if (!success)
3409 return false;
3410
3411 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3412 return false;
3413
3414 offset += addr_byte_size;
3415 }
3416 }
3417
3418 if (BitIsSet (registers, 15))
3419 {
3420 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003421 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003422 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003423 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003424 if (!success)
3425 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003426 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003427 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003428 return false;
3429 }
3430
3431 if (wback && BitIsClear (registers, n))
3432 {
Caroline Ticefa172202011-02-11 22:49:54 +00003433 // R[n] = R[n] + 4 * BitCount (registers)
3434 int32_t offset = addr_byte_size * BitCount (registers);
3435 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003436 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003437
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003438 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3439 return false;
3440 }
3441 if (wback && BitIsSet (registers, n))
3442 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003443 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003444 }
3445 return true;
3446}
Caroline Tice713c2662011-02-11 17:59:55 +00003447
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003448// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3449// The consecutive memory locations end at this address and the address just below the lowest of those locations
3450// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003451bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003452EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003453{
3454#if 0
3455 // ARM pseudo code...
3456 if ConditionPassed() then
3457 EncodingSpecificOperations();
3458 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003459
Caroline Tice713c2662011-02-11 17:59:55 +00003460 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003461 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003462 R[i] = MemA[address,4]; address = address + 4;
3463
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003464 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003465 LoadWritePC(MemA[address,4]);
3466
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003467 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3468 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003469#endif
3470
3471 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003472
Greg Clayton7bc39082011-03-24 23:53:38 +00003473 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003474 {
3475 uint32_t n;
3476 uint32_t registers = 0;
3477 bool wback;
3478 const uint32_t addr_byte_size = GetAddressByteSize();
3479
3480 // EncodingSpecificOperations();
3481 switch (encoding)
3482 {
3483 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003484 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003485 n = Bits32 (opcode, 19, 16);
3486 registers = Bits32 (opcode, 15, 0);
3487 wback = BitIsSet (opcode, 21);
3488
3489 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3490 if ((n == 15) || (BitCount (registers) < 1))
3491 return false;
3492
3493 break;
3494
3495 default:
3496 return false;
3497 }
3498 // address = R[n] - 4*BitCount(registers) + 4;
3499
3500 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003501 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003502
3503 if (!success)
3504 return false;
3505
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003506 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003507
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003508 EmulateInstruction::Context context;
3509 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003510 RegisterInfo dwarf_reg;
3511 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003512 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003513
3514 // for i = 0 to 14
3515 for (int i = 0; i < 14; ++i)
3516 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003517 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003518 if (BitIsSet (registers, i))
3519 {
3520 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003521 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003522 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003523 if (!success)
3524 return false;
3525 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3526 return false;
3527 offset += addr_byte_size;
3528 }
3529 }
3530
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003531 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003532 // LoadWritePC(MemA[address,4]);
3533 if (BitIsSet (registers, 15))
3534 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003535 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003536 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003537 if (!success)
3538 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003539 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003540 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003541 return false;
3542 }
3543
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003544 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003545 if (wback && BitIsClear (registers, n))
3546 {
Caroline Tice713c2662011-02-11 17:59:55 +00003547 if (!success)
3548 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003549
3550 offset = (addr_byte_size * BitCount (registers)) * -1;
3551 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003552 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003553 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003554 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3555 return false;
3556 }
3557
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003558 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003559 if (wback && BitIsSet (registers, n))
3560 return WriteBits32Unknown (n);
3561 }
3562 return true;
3563}
3564
3565// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3566// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3567// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003568bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003569EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003570{
3571#if 0
3572 // ARM pseudo code...
3573 if ConditionPassed() then
3574 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3575 address = R[n] - 4*BitCount(registers);
3576
3577 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003578 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003579 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003580 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003581 LoadWritePC(MemA[address,4]);
3582
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003583 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3584 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003585#endif
3586
3587 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003588
Greg Clayton7bc39082011-03-24 23:53:38 +00003589 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003590 {
3591 uint32_t n;
3592 uint32_t registers = 0;
3593 bool wback;
3594 const uint32_t addr_byte_size = GetAddressByteSize();
3595 switch (encoding)
3596 {
3597 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003598 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003599 n = Bits32 (opcode, 19, 16);
3600 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003601 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003602 wback = BitIsSet (opcode, 21);
3603
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003604 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003605 if ((n == 15)
3606 || (BitCount (registers) < 2)
3607 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3608 return false;
3609
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003610 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003611 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003612 return false;
3613
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003614 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003615 if (wback && BitIsSet (registers, n))
3616 return false;
3617
3618 break;
3619
3620 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003621 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003622 n = Bits32 (opcode, 19, 16);
3623 registers = Bits32 (opcode, 15, 0);
3624 wback = BitIsSet (opcode, 21);
3625
3626 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3627 if ((n == 15) || (BitCount (registers) < 1))
3628 return false;
3629
3630 break;
3631
3632 default:
3633 return false;
3634 }
3635
Caroline Tice713c2662011-02-11 17:59:55 +00003636 // address = R[n] - 4*BitCount(registers);
3637
Caroline Tice0b29e242011-02-08 23:16:02 +00003638 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003639 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003640
3641 if (!success)
3642 return false;
3643
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003644 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003645 EmulateInstruction::Context context;
3646 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003647 RegisterInfo dwarf_reg;
3648 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003649 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003650
3651 for (int i = 0; i < 14; ++i)
3652 {
3653 if (BitIsSet (registers, i))
3654 {
3655 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003656 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003657 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003658 if (!success)
3659 return false;
3660
3661 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3662 return false;
3663
3664 offset += addr_byte_size;
3665 }
3666 }
3667
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003668 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003669 // LoadWritePC(MemA[address,4]);
3670 if (BitIsSet (registers, 15))
3671 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003672 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003673 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003674 if (!success)
3675 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003676 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003677 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003678 return false;
3679 }
3680
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003681 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003682 if (wback && BitIsClear (registers, n))
3683 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003684 if (!success)
3685 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003686
3687 offset = (addr_byte_size * BitCount (registers)) * -1;
3688 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003689 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003690 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003691 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3692 return false;
3693 }
3694
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003695 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003696 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003697 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003698 }
3699 return true;
3700}
Caroline Tice85aab332011-02-08 23:56:10 +00003701
Caroline Tice713c2662011-02-11 17:59:55 +00003702// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3703// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3704// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003705bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003706EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003707{
3708#if 0
3709 if ConditionPassed() then
3710 EncodingSpecificOperations();
3711 address = R[n] + 4;
3712
3713 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003714 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003715 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003716 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003717 LoadWritePC(MemA[address,4]);
3718
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003719 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3720 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003721#endif
3722
3723 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003724
Greg Clayton7bc39082011-03-24 23:53:38 +00003725 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003726 {
3727 uint32_t n;
3728 uint32_t registers = 0;
3729 bool wback;
3730 const uint32_t addr_byte_size = GetAddressByteSize();
3731 switch (encoding)
3732 {
3733 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003734 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003735 n = Bits32 (opcode, 19, 16);
3736 registers = Bits32 (opcode, 15, 0);
3737 wback = BitIsSet (opcode, 21);
3738
3739 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3740 if ((n == 15) || (BitCount (registers) < 1))
3741 return false;
3742
3743 break;
3744 default:
3745 return false;
3746 }
3747 // address = R[n] + 4;
3748
3749 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003750 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003751
3752 if (!success)
3753 return false;
3754
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003755 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003756
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003757 EmulateInstruction::Context context;
3758 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003759 RegisterInfo dwarf_reg;
3760 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003761 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003762
3763 for (int i = 0; i < 14; ++i)
3764 {
3765 if (BitIsSet (registers, i))
3766 {
3767 // R[i] = MemA[address,4]; address = address + 4;
3768
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003769 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003770 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003771 if (!success)
3772 return false;
3773
3774 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3775 return false;
3776
3777 offset += addr_byte_size;
3778 }
3779 }
3780
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003781 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003782 // LoadWritePC(MemA[address,4]);
3783 if (BitIsSet (registers, 15))
3784 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003785 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003786 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003787 if (!success)
3788 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003789 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003790 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003791 return false;
3792 }
3793
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003794 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003795 if (wback && BitIsClear (registers, n))
3796 {
Caroline Tice85aab332011-02-08 23:56:10 +00003797 if (!success)
3798 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003799
3800 offset = addr_byte_size * BitCount (registers);
3801 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003802 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003803 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003804 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3805 return false;
3806 }
3807
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003808 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003809 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003810 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003811 }
3812 return true;
3813}
Caroline Tice0b29e242011-02-08 23:16:02 +00003814
Johnny Chenef21b592011-02-10 01:52:38 +00003815// Load Register (immediate) calculates an address from a base register value and
3816// an immediate offset, loads a word from memory, and writes to a register.
3817// LDR (immediate, Thumb)
3818bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003819EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003820{
3821#if 0
3822 // ARM pseudo code...
3823 if (ConditionPassed())
3824 {
3825 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3826 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3827 address = if index then offset_addr else R[n];
3828 data = MemU[address,4];
3829 if wback then R[n] = offset_addr;
3830 if t == 15 then
3831 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3832 elsif UnalignedSupport() || address<1:0> = '00' then
3833 R[t] = data;
3834 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3835 }
3836#endif
3837
3838 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003839
Greg Clayton7bc39082011-03-24 23:53:38 +00003840 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003841 {
3842 uint32_t Rt; // the destination register
3843 uint32_t Rn; // the base register
3844 uint32_t imm32; // the immediate offset used to form the address
3845 addr_t offset_addr; // the offset address
3846 addr_t address; // the calculated address
3847 uint32_t data; // the literal data value from memory load
3848 bool add, index, wback;
3849 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003850 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003851 Rt = Bits32(opcode, 2, 0);
3852 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003853 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3854 // index = TRUE; add = TRUE; wback = FALSE
3855 add = true;
3856 index = true;
3857 wback = false;
3858
3859 break;
3860
3861 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003862 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003863 Rt = Bits32 (opcode, 10, 8);
3864 Rn = 13;
3865 imm32 = Bits32 (opcode, 7, 0) << 2;
3866
3867 // index = TRUE; add = TRUE; wback = FALSE;
3868 index = true;
3869 add = true;
3870 wback = false;
3871
3872 break;
3873
3874 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003875 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003876 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3877 Rt = Bits32 (opcode, 15, 12);
3878 Rn = Bits32 (opcode, 19, 16);
3879 imm32 = Bits32 (opcode, 11, 0);
3880
3881 // index = TRUE; add = TRUE; wback = FALSE;
3882 index = true;
3883 add = true;
3884 wback = false;
3885
3886 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3887 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3888 return false;
3889
3890 break;
3891
3892 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003893 // if Rn == '1111' then SEE LDR (literal);
3894 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3895 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3896 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003897 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3898 return false;
3899
3900 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3901 Rt = Bits32 (opcode, 15, 12);
3902 Rn = Bits32 (opcode, 19, 16);
3903 imm32 = Bits32 (opcode, 7, 0);
3904
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003905 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003906 index = BitIsSet (opcode, 10);
3907 add = BitIsSet (opcode, 9);
3908 wback = BitIsSet (opcode, 8);
3909
3910 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3911 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3912 return false;
3913
3914 break;
3915
3916 default:
3917 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003918 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003919 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003920 if (!success)
3921 return false;
3922 if (add)
3923 offset_addr = base + imm32;
3924 else
3925 offset_addr = base - imm32;
3926
3927 address = (index ? offset_addr : base);
3928
Greg Claytonc07d4512011-04-26 23:48:45 +00003929 RegisterInfo base_reg;
3930 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
Johnny Chenef21b592011-02-10 01:52:38 +00003931 if (wback)
3932 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003933 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003934 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3935 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003936
Johnny Chenef21b592011-02-10 01:52:38 +00003937 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3938 return false;
3939 }
3940
3941 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003942 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003943 context.type = EmulateInstruction::eContextRegisterLoad;
3944 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003945
3946 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003947 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003948 if (!success)
3949 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003950
3951 if (Rt == 15)
3952 {
3953 if (Bits32(address, 1, 0) == 0)
3954 {
Johnny Chen668b4512011-02-15 21:08:58 +00003955 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003956 return false;
3957 }
3958 else
3959 return false;
3960 }
3961 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3962 {
3963 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3964 return false;
3965 }
3966 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003967 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003968 }
3969 return true;
3970}
3971
Caroline Ticeaf556562011-02-15 18:42:15 +00003972// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3973// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3974// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003975bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003976EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003977{
3978#if 0
3979 if ConditionPassed() then
3980 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3981 address = R[n];
3982
3983 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003984 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003985 if i == n && wback && i != LowestSetBit(registers) then
3986 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3987 else
3988 MemA[address,4] = R[i];
3989 address = address + 4;
3990
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003991 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003992 MemA[address,4] = PCStoreValue();
3993 if wback then R[n] = R[n] + 4*BitCount(registers);
3994#endif
3995
3996 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003997
Greg Clayton7bc39082011-03-24 23:53:38 +00003998 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003999 {
4000 uint32_t n;
4001 uint32_t registers = 0;
4002 bool wback;
4003 const uint32_t addr_byte_size = GetAddressByteSize();
4004
4005 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4006 switch (encoding)
4007 {
4008 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004009 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00004010 n = Bits32 (opcode, 10, 8);
4011 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004012 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00004013 wback = true;
4014
4015 // if BitCount(registers) < 1 then UNPREDICTABLE;
4016 if (BitCount (registers) < 1)
4017 return false;
4018
4019 break;
4020
4021 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004022 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00004023 n = Bits32 (opcode, 19, 16);
4024 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004025 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00004026 wback = BitIsSet (opcode, 21);
4027
4028 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4029 if ((n == 15) || (BitCount (registers) < 2))
4030 return false;
4031
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004032 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00004033 if (wback && BitIsSet (registers, n))
4034 return false;
4035
4036 break;
4037
4038 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004039 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00004040 n = Bits32 (opcode, 19, 16);
4041 registers = Bits32 (opcode, 15, 0);
4042 wback = BitIsSet (opcode, 21);
4043
4044 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4045 if ((n == 15) || (BitCount (registers) < 1))
4046 return false;
4047
4048 break;
4049
4050 default:
4051 return false;
4052 }
4053
4054 // address = R[n];
4055 int32_t offset = 0;
4056 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4057 if (!success)
4058 return false;
4059
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004060 EmulateInstruction::Context context;
4061 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004062 RegisterInfo base_reg;
4063 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefa172202011-02-11 22:49:54 +00004064
4065 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004066 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00004067 for (int i = 0; i < 14; ++i)
4068 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004069 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00004070 if (BitIsSet (registers, i))
4071 {
4072 if (i < lowest_set_bit)
4073 lowest_set_bit = i;
4074 // if i == n && wback && i != LowestSetBit(registers) then
4075 if ((i == n) && wback && (i != lowest_set_bit))
4076 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4077 WriteBits32UnknownToMemory (address + offset);
4078 else
4079 {
4080 // MemA[address,4] = R[i];
4081 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4082 if (!success)
4083 return false;
4084
Greg Claytonc07d4512011-04-26 23:48:45 +00004085 RegisterInfo data_reg;
4086 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004087 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004088 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004089 return false;
4090 }
4091
4092 // address = address + 4;
4093 offset += addr_byte_size;
4094 }
4095 }
4096
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004097 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004098 // MemA[address,4] = PCStoreValue();
4099 if (BitIsSet (registers, 15))
4100 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004101 RegisterInfo pc_reg;
4102 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004103 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004104 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004105 if (!success)
4106 return false;
4107
Caroline Tice8d681f52011-03-17 23:50:16 +00004108 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004109 return false;
4110 }
4111
4112 // if wback then R[n] = R[n] + 4*BitCount(registers);
4113 if (wback)
4114 {
4115 offset = addr_byte_size * BitCount (registers);
4116 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004117 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004118 addr_t data = address + offset;
4119 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4120 return false;
4121 }
4122 }
4123 return true;
4124}
4125
Caroline Ticeaf556562011-02-15 18:42:15 +00004126// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4127// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4128// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004129bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004130EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004131{
4132#if 0
4133 if ConditionPassed() then
4134 EncodingSpecificOperations();
4135 address = R[n] - 4*BitCount(registers) + 4;
4136
4137 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004138 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004139 if i == n && wback && i != LowestSetBit(registers) then
4140 MemA[address,4] = bits(32) UNKNOWN;
4141 else
4142 MemA[address,4] = R[i];
4143 address = address + 4;
4144
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004145 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004146 MemA[address,4] = PCStoreValue();
4147
4148 if wback then R[n] = R[n] - 4*BitCount(registers);
4149#endif
4150
4151 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004152
Greg Clayton7bc39082011-03-24 23:53:38 +00004153 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004154 {
4155 uint32_t n;
4156 uint32_t registers = 0;
4157 bool wback;
4158 const uint32_t addr_byte_size = GetAddressByteSize();
4159
4160 // EncodingSpecificOperations();
4161 switch (encoding)
4162 {
4163 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004164 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004165 n = Bits32 (opcode, 19, 16);
4166 registers = Bits32 (opcode, 15, 0);
4167 wback = BitIsSet (opcode, 21);
4168
4169 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4170 if ((n == 15) || (BitCount (registers) < 1))
4171 return false;
4172 break;
4173 default:
4174 return false;
4175 }
4176
4177 // address = R[n] - 4*BitCount(registers) + 4;
4178 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004179 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004180 if (!success)
4181 return false;
4182
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004183 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004184
4185 EmulateInstruction::Context context;
4186 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004187 RegisterInfo base_reg;
4188 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004189
4190 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004191 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004192 for (int i = 0; i < 14; ++i)
4193 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004194 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004195 if (BitIsSet (registers, i))
4196 {
4197 if (i < lowest_bit_set)
4198 lowest_bit_set = i;
4199 //if i == n && wback && i != LowestSetBit(registers) then
4200 if ((i == n) && wback && (i != lowest_bit_set))
4201 // MemA[address,4] = bits(32) UNKNOWN;
4202 WriteBits32UnknownToMemory (address + offset);
4203 else
4204 {
4205 // MemA[address,4] = R[i];
4206 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4207 if (!success)
4208 return false;
4209
Greg Claytonc07d4512011-04-26 23:48:45 +00004210 RegisterInfo data_reg;
4211 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004212 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004213 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004214 return false;
4215 }
4216
4217 // address = address + 4;
4218 offset += addr_byte_size;
4219 }
4220 }
4221
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004222 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004223 // MemA[address,4] = PCStoreValue();
4224 if (BitIsSet (registers, 15))
4225 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004226 RegisterInfo pc_reg;
4227 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004228 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004229 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004230 if (!success)
4231 return false;
4232
Caroline Tice8d681f52011-03-17 23:50:16 +00004233 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004234 return false;
4235 }
4236
4237 // if wback then R[n] = R[n] - 4*BitCount(registers);
4238 if (wback)
4239 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004240 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004241 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4242 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004243 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004244 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4245 return false;
4246 }
4247 }
4248 return true;
4249}
4250
Caroline Ticeaf556562011-02-15 18:42:15 +00004251// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4252// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4253// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004254bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004255EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004256{
4257#if 0
4258 if ConditionPassed() then
4259 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4260 address = R[n] - 4*BitCount(registers);
4261
4262 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004263 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004264 if i == n && wback && i != LowestSetBit(registers) then
4265 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4266 else
4267 MemA[address,4] = R[i];
4268 address = address + 4;
4269
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004270 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004271 MemA[address,4] = PCStoreValue();
4272
4273 if wback then R[n] = R[n] - 4*BitCount(registers);
4274#endif
4275
4276
4277 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004278
Greg Clayton7bc39082011-03-24 23:53:38 +00004279 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004280 {
4281 uint32_t n;
4282 uint32_t registers = 0;
4283 bool wback;
4284 const uint32_t addr_byte_size = GetAddressByteSize();
4285
4286 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4287 switch (encoding)
4288 {
4289 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004290 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004291 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4292 {
4293 // See PUSH
4294 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004295 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004296 n = Bits32 (opcode, 19, 16);
4297 registers = Bits32 (opcode, 15, 0);
4298 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4299 wback = BitIsSet (opcode, 21);
4300 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4301 if ((n == 15) || BitCount (registers) < 2)
4302 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004303 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004304 if (wback && BitIsSet (registers, n))
4305 return false;
4306 break;
4307
4308 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00004309 // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004310 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4311 {
4312 // See Push
4313 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004314 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004315 n = Bits32 (opcode, 19, 16);
4316 registers = Bits32 (opcode, 15, 0);
4317 wback = BitIsSet (opcode, 21);
4318 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4319 if ((n == 15) || BitCount (registers) < 1)
4320 return false;
4321 break;
4322
4323 default:
4324 return false;
4325 }
4326
4327 // address = R[n] - 4*BitCount(registers);
4328
4329 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004330 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004331 if (!success)
4332 return false;
4333
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004334 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004335
4336 EmulateInstruction::Context context;
4337 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004338 RegisterInfo base_reg;
4339 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004340
4341 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004342 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004343 for (int i = 0; i < 14; ++i)
4344 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004345 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004346 if (BitIsSet (registers, i))
4347 {
4348 if (i < lowest_set_bit)
4349 lowest_set_bit = i;
4350 // if i == n && wback && i != LowestSetBit(registers) then
4351 if ((i == n) && wback && (i != lowest_set_bit))
4352 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4353 WriteBits32UnknownToMemory (address + offset);
4354 else
4355 {
4356 // MemA[address,4] = R[i];
4357 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4358 if (!success)
4359 return false;
4360
Greg Claytonc07d4512011-04-26 23:48:45 +00004361 RegisterInfo data_reg;
4362 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004363 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004364 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004365 return false;
4366 }
4367
4368 // address = address + 4;
4369 offset += addr_byte_size;
4370 }
4371 }
4372
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004373 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004374 // MemA[address,4] = PCStoreValue();
4375 if (BitIsSet (registers, 15))
4376 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004377 RegisterInfo pc_reg;
4378 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004379 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004380 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004381 if (!success)
4382 return false;
4383
Caroline Tice8d681f52011-03-17 23:50:16 +00004384 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004385 return false;
4386 }
4387
4388 // if wback then R[n] = R[n] - 4*BitCount(registers);
4389 if (wback)
4390 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004391 offset = (addr_byte_size * BitCount (registers)) * -1;
4392 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4393 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004394 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004395 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4396 return false;
4397 }
4398 }
4399 return true;
4400}
4401
4402// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4403// from a base register. The consecutive memory locations start just above this address, and the address of the last
4404// of those locations can optionally be written back to the base register.
4405bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004406EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004407{
4408#if 0
4409 if ConditionPassed() then
4410 EncodingSpecificOperations();
4411 address = R[n] + 4;
4412
4413 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004414 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004415 if i == n && wback && i != LowestSetBit(registers) then
4416 MemA[address,4] = bits(32) UNKNOWN;
4417 else
4418 MemA[address,4] = R[i];
4419 address = address + 4;
4420
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004421 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004422 MemA[address,4] = PCStoreValue();
4423
4424 if wback then R[n] = R[n] + 4*BitCount(registers);
4425#endif
4426
4427 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004428
Greg Clayton7bc39082011-03-24 23:53:38 +00004429 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004430 {
4431 uint32_t n;
4432 uint32_t registers = 0;
4433 bool wback;
4434 const uint32_t addr_byte_size = GetAddressByteSize();
4435
4436 // EncodingSpecificOperations();
4437 switch (encoding)
4438 {
4439 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004440 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004441 n = Bits32 (opcode, 19, 16);
4442 registers = Bits32 (opcode, 15, 0);
4443 wback = BitIsSet (opcode, 21);
4444
4445 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4446 if ((n == 15) && (BitCount (registers) < 1))
4447 return false;
4448 break;
4449 default:
4450 return false;
4451 }
4452 // address = R[n] + 4;
4453
4454 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004455 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004456 if (!success)
4457 return false;
4458
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004459 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004460
4461 EmulateInstruction::Context context;
4462 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004463 RegisterInfo base_reg;
4464 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004465
4466 uint32_t lowest_set_bit = 14;
4467 // for i = 0 to 14
4468 for (int i = 0; i < 14; ++i)
4469 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004470 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004471 if (BitIsSet (registers, i))
4472 {
4473 if (i < lowest_set_bit)
4474 lowest_set_bit = i;
4475 // if i == n && wback && i != LowestSetBit(registers) then
4476 if ((i == n) && wback && (i != lowest_set_bit))
4477 // MemA[address,4] = bits(32) UNKNOWN;
4478 WriteBits32UnknownToMemory (address + offset);
4479 // else
4480 else
4481 {
4482 // MemA[address,4] = R[i];
4483 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4484 if (!success)
4485 return false;
4486
Greg Claytonc07d4512011-04-26 23:48:45 +00004487 RegisterInfo data_reg;
4488 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004489 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004490 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004491 return false;
4492 }
4493
4494 // address = address + 4;
4495 offset += addr_byte_size;
4496 }
4497 }
4498
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004499 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004500 // MemA[address,4] = PCStoreValue();
4501 if (BitIsSet (registers, 15))
4502 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004503 RegisterInfo pc_reg;
4504 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004505 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004506 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004507 if (!success)
4508 return false;
4509
Caroline Tice8d681f52011-03-17 23:50:16 +00004510 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004511 return false;
4512 }
4513
4514 // if wback then R[n] = R[n] + 4*BitCount(registers);
4515 if (wback)
4516 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004517 offset = addr_byte_size * BitCount (registers);
4518 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4519 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004520 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004521 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4522 return false;
4523 }
4524 }
4525 return true;
4526}
Caroline Tice7fac8572011-02-15 22:53:54 +00004527
4528// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4529// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4530bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004531EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004532{
4533#if 0
4534 if ConditionPassed() then
4535 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4536 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4537 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004538 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004539 MemU[address,4] = R[t];
4540 else // Can only occur before ARMv7
4541 MemU[address,4] = bits(32) UNKNOWN;
4542 if wback then R[n] = offset_addr;
4543#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004544
Caroline Tice7fac8572011-02-15 22:53:54 +00004545 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004546
Greg Clayton7bc39082011-03-24 23:53:38 +00004547 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004548 {
4549 const uint32_t addr_byte_size = GetAddressByteSize();
4550
4551 uint32_t t;
4552 uint32_t n;
4553 uint32_t imm32;
4554 bool index;
4555 bool add;
4556 bool wback;
4557 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4558 switch (encoding)
4559 {
4560 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004561 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004562 t = Bits32 (opcode, 2, 0);
4563 n = Bits32 (opcode, 5, 3);
4564 imm32 = Bits32 (opcode, 10, 6) << 2;
4565
4566 // index = TRUE; add = TRUE; wback = FALSE;
4567 index = true;
4568 add = false;
4569 wback = false;
4570 break;
4571
4572 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004573 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004574 t = Bits32 (opcode, 10, 8);
4575 n = 13;
4576 imm32 = Bits32 (opcode, 7, 0) << 2;
4577
4578 // index = TRUE; add = TRUE; wback = FALSE;
4579 index = true;
4580 add = true;
4581 wback = false;
4582 break;
4583
4584 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004585 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004586 if (Bits32 (opcode, 19, 16) == 15)
4587 return false;
4588
4589 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4590 t = Bits32 (opcode, 15, 12);
4591 n = Bits32 (opcode, 19, 16);
4592 imm32 = Bits32 (opcode, 11, 0);
4593
4594 // index = TRUE; add = TRUE; wback = FALSE;
4595 index = true;
4596 add = true;
4597 wback = false;
4598
4599 // if t == 15 then UNPREDICTABLE;
4600 if (t == 15)
4601 return false;
4602 break;
4603
4604 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004605 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4606 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4607 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004608 if ((Bits32 (opcode, 19, 16) == 15)
4609 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4610 return false;
4611
4612 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4613 t = Bits32 (opcode, 15, 12);
4614 n = Bits32 (opcode, 19, 16);
4615 imm32 = Bits32 (opcode, 7, 0);
4616
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004617 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004618 index = BitIsSet (opcode, 10);
4619 add = BitIsSet (opcode, 9);
4620 wback = BitIsSet (opcode, 8);
4621
4622 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4623 if ((t == 15) || (wback && (n == t)))
4624 return false;
4625 break;
4626
4627 default:
4628 return false;
4629 }
4630
4631 addr_t offset_addr;
4632 addr_t address;
4633
4634 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004635 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004636 if (!success)
4637 return false;
4638
4639 if (add)
4640 offset_addr = base_address + imm32;
4641 else
4642 offset_addr = base_address - imm32;
4643
4644 // address = if index then offset_addr else R[n];
4645 if (index)
4646 address = offset_addr;
4647 else
4648 address = base_address;
4649
4650 EmulateInstruction::Context context;
4651 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004652 RegisterInfo base_reg;
4653 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004654
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004655 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004656 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4657 {
4658 // MemU[address,4] = R[t];
4659 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4660 if (!success)
4661 return false;
4662
Greg Claytonc07d4512011-04-26 23:48:45 +00004663 RegisterInfo data_reg;
4664 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004665 int32_t offset = address - base_address;
4666 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004667 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004668 return false;
4669 }
4670 else
4671 {
4672 // MemU[address,4] = bits(32) UNKNOWN;
4673 WriteBits32UnknownToMemory (address);
4674 }
4675
4676 // if wback then R[n] = offset_addr;
4677 if (wback)
4678 {
4679 context.type = eContextRegisterLoad;
4680 context.SetAddress (offset_addr);
4681 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4682 return false;
4683 }
4684 }
4685 return true;
4686}
Caroline Ticeaf556562011-02-15 18:42:15 +00004687
Caroline Tice3fd63e92011-02-16 00:33:43 +00004688// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4689// word from a register to memory. The offset register value can optionally be shifted.
4690bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004691EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004692{
4693#if 0
4694 if ConditionPassed() then
4695 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4696 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4697 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4698 address = if index then offset_addr else R[n];
4699 if t == 15 then // Only possible for encoding A1
4700 data = PCStoreValue();
4701 else
4702 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004703 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004704 MemU[address,4] = data;
4705 else // Can only occur before ARMv7
4706 MemU[address,4] = bits(32) UNKNOWN;
4707 if wback then R[n] = offset_addr;
4708#endif
4709
4710 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004711
Greg Clayton7bc39082011-03-24 23:53:38 +00004712 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004713 {
4714 const uint32_t addr_byte_size = GetAddressByteSize();
4715
4716 uint32_t t;
4717 uint32_t n;
4718 uint32_t m;
4719 ARM_ShifterType shift_t;
4720 uint32_t shift_n;
4721 bool index;
4722 bool add;
4723 bool wback;
4724
4725 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4726 switch (encoding)
4727 {
4728 case eEncodingT1:
4729 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4730 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4731 t = Bits32 (opcode, 2, 0);
4732 n = Bits32 (opcode, 5, 3);
4733 m = Bits32 (opcode, 8, 6);
4734
4735 // index = TRUE; add = TRUE; wback = FALSE;
4736 index = true;
4737 add = true;
4738 wback = false;
4739
4740 // (shift_t, shift_n) = (SRType_LSL, 0);
4741 shift_t = SRType_LSL;
4742 shift_n = 0;
4743 break;
4744
4745 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004746 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004747 if (Bits32 (opcode, 19, 16) == 15)
4748 return false;
4749
4750 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4751 t = Bits32 (opcode, 15, 12);
4752 n = Bits32 (opcode, 19, 16);
4753 m = Bits32 (opcode, 3, 0);
4754
4755 // index = TRUE; add = TRUE; wback = FALSE;
4756 index = true;
4757 add = true;
4758 wback = false;
4759
4760 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4761 shift_t = SRType_LSL;
4762 shift_n = Bits32 (opcode, 5, 4);
4763
4764 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4765 if ((t == 15) || (BadReg (m)))
4766 return false;
4767 break;
4768
4769 case eEncodingA1:
4770 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004771 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004772 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4773 t = Bits32 (opcode, 15, 12);
4774 n = Bits32 (opcode, 19, 16);
4775 m = Bits32 (opcode, 3, 0);
4776
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004777 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004778 index = BitIsSet (opcode, 24);
4779 add = BitIsSet (opcode, 23);
4780 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4781
4782 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4783 uint32_t typ = Bits32 (opcode, 6, 5);
4784 uint32_t imm5 = Bits32 (opcode, 11, 7);
4785 shift_n = DecodeImmShift(typ, imm5, shift_t);
4786
4787 // if m == 15 then UNPREDICTABLE;
4788 if (m == 15)
4789 return false;
4790
4791 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4792 if (wback && ((n == 15) || (n == t)))
4793 return false;
4794
4795 break;
4796 }
4797 default:
4798 return false;
4799 }
4800
4801 addr_t offset_addr;
4802 addr_t address;
4803 int32_t offset = 0;
4804
4805 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4806 if (!success)
4807 return false;
4808
4809 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4810 if (!success)
4811 return false;
4812
4813 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00004814 offset = Shift (Rm_data, shift_t, shift_n, APSR_C, &success);
4815 if (!success)
4816 return false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004817
4818 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4819 if (add)
4820 offset_addr = base_address + offset;
4821 else
4822 offset_addr = base_address - offset;
4823
4824 // address = if index then offset_addr else R[n];
4825 if (index)
4826 address = offset_addr;
4827 else
4828 address = base_address;
4829
4830 uint32_t data;
4831 // if t == 15 then // Only possible for encoding A1
4832 if (t == 15)
4833 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004834 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004835 else
4836 // data = R[t];
4837 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4838
4839 if (!success)
4840 return false;
4841
4842 EmulateInstruction::Context context;
4843 context.type = eContextRegisterStore;
4844
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004845 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004846 if (UnalignedSupport ()
4847 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4848 || CurrentInstrSet() == eModeARM)
4849 {
4850 // MemU[address,4] = data;
4851
Greg Claytonc07d4512011-04-26 23:48:45 +00004852 RegisterInfo base_reg;
4853 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004854
Greg Claytonc07d4512011-04-26 23:48:45 +00004855 RegisterInfo data_reg;
4856 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004857
4858 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004859 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004860 return false;
4861
4862 }
4863 else
4864 // MemU[address,4] = bits(32) UNKNOWN;
4865 WriteBits32UnknownToMemory (address);
4866
4867 // if wback then R[n] = offset_addr;
4868 if (wback)
4869 {
4870 context.type = eContextRegisterLoad;
4871 context.SetAddress (offset_addr);
4872 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4873 return false;
4874 }
4875
4876 }
4877 return true;
4878}
Caroline Tice73a29de2011-02-16 20:22:22 +00004879
4880bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004881EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004882{
4883#if 0
4884 if ConditionPassed() then
4885 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4886 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4887 address = if index then offset_addr else R[n];
4888 MemU[address,1] = R[t]<7:0>;
4889 if wback then R[n] = offset_addr;
4890#endif
4891
4892
4893 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004894
Greg Clayton7bc39082011-03-24 23:53:38 +00004895 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004896 {
4897 uint32_t t;
4898 uint32_t n;
4899 uint32_t imm32;
4900 bool index;
4901 bool add;
4902 bool wback;
4903 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4904 switch (encoding)
4905 {
4906 case eEncodingT1:
4907 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4908 t = Bits32 (opcode, 2, 0);
4909 n = Bits32 (opcode, 5, 3);
4910 imm32 = Bits32 (opcode, 10, 6);
4911
4912 // index = TRUE; add = TRUE; wback = FALSE;
4913 index = true;
4914 add = true;
4915 wback = false;
4916 break;
4917
4918 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004919 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004920 if (Bits32 (opcode, 19, 16) == 15)
4921 return false;
4922
4923 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4924 t = Bits32 (opcode, 15, 12);
4925 n = Bits32 (opcode, 19, 16);
4926 imm32 = Bits32 (opcode, 11, 0);
4927
4928 // index = TRUE; add = TRUE; wback = FALSE;
4929 index = true;
4930 add = true;
4931 wback = false;
4932
4933 // if BadReg(t) then UNPREDICTABLE;
4934 if (BadReg (t))
4935 return false;
4936 break;
4937
4938 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004939 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4940 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004941 if (Bits32 (opcode, 19, 16) == 15)
4942 return false;
4943
4944 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4945 t = Bits32 (opcode, 15, 12);
4946 n = Bits32 (opcode, 19, 16);
4947 imm32 = Bits32 (opcode, 7, 0);
4948
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004949 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004950 index = BitIsSet (opcode, 10);
4951 add = BitIsSet (opcode, 9);
4952 wback = BitIsSet (opcode, 8);
4953
4954 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4955 if ((BadReg (t)) || (wback && (n == t)))
4956 return false;
4957 break;
4958
4959 default:
4960 return false;
4961 }
4962
4963 addr_t offset_addr;
4964 addr_t address;
4965 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4966 if (!success)
4967 return false;
4968
4969 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4970 if (add)
4971 offset_addr = base_address + imm32;
4972 else
4973 offset_addr = base_address - imm32;
4974
4975 // address = if index then offset_addr else R[n];
4976 if (index)
4977 address = offset_addr;
4978 else
4979 address = base_address;
4980
Caroline Ticecc96eb52011-02-17 19:20:40 +00004981 // MemU[address,1] = R[t]<7:0>
Greg Claytonc07d4512011-04-26 23:48:45 +00004982 RegisterInfo base_reg;
4983 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004984
Greg Claytonc07d4512011-04-26 23:48:45 +00004985 RegisterInfo data_reg;
4986 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004987
4988 EmulateInstruction::Context context;
4989 context.type = eContextRegisterStore;
4990 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4991
4992 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4993 if (!success)
4994 return false;
4995
4996 data = Bits32 (data, 7, 0);
4997
Caroline Ticecc96eb52011-02-17 19:20:40 +00004998 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004999 return false;
5000
5001 // if wback then R[n] = offset_addr;
5002 if (wback)
5003 {
5004 context.type = eContextRegisterLoad;
5005 context.SetAddress (offset_addr);
5006 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5007 return false;
5008 }
5009
5010 }
5011
5012 return true;
5013}
Caroline Tice8ce836d2011-03-16 22:46:55 +00005014
5015// STRH (register) calculates an address from a base register value and an offset register value, and stores a
5016// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
5017bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005018EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00005019{
5020#if 0
5021 if ConditionPassed() then
5022 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5023 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5024 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5025 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005026 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005027 MemU[address,2] = R[t]<15:0>;
5028 else // Can only occur before ARMv7
5029 MemU[address,2] = bits(16) UNKNOWN;
5030 if wback then R[n] = offset_addr;
5031#endif
5032
5033 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005034
Greg Clayton7bc39082011-03-24 23:53:38 +00005035 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00005036 {
5037 uint32_t t;
5038 uint32_t n;
5039 uint32_t m;
5040 bool index;
5041 bool add;
5042 bool wback;
5043 ARM_ShifterType shift_t;
5044 uint32_t shift_n;
5045
5046 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5047 switch (encoding)
5048 {
5049 case eEncodingT1:
5050 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5051 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5052 t = Bits32 (opcode, 2, 0);
5053 n = Bits32 (opcode, 5, 3);
5054 m = Bits32 (opcode, 8, 6);
5055
5056 // index = TRUE; add = TRUE; wback = FALSE;
5057 index = true;
5058 add = true;
5059 wback = false;
5060
5061 // (shift_t, shift_n) = (SRType_LSL, 0);
5062 shift_t = SRType_LSL;
5063 shift_n = 0;
5064
5065 break;
5066
5067 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005068 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005069 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5070 t = Bits32 (opcode, 15, 12);
5071 n = Bits32 (opcode, 19, 16);
5072 m = Bits32 (opcode, 3, 0);
5073 if (n == 15)
5074 return false;
5075
5076 // index = TRUE; add = TRUE; wback = FALSE;
5077 index = true;
5078 add = true;
5079 wback = false;
5080
5081 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5082 shift_t = SRType_LSL;
5083 shift_n = Bits32 (opcode, 5, 4);
5084
5085 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5086 if (BadReg (t) || BadReg (m))
5087 return false;
5088
5089 break;
5090
5091 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005092 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005093 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5094 t = Bits32 (opcode, 15, 12);
5095 n = Bits32 (opcode, 19, 16);
5096 m = Bits32 (opcode, 3, 0);
5097
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005098 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005099 index = BitIsSet (opcode, 24);
5100 add = BitIsSet (opcode, 23);
5101 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5102
5103 // (shift_t, shift_n) = (SRType_LSL, 0);
5104 shift_t = SRType_LSL;
5105 shift_n = 0;
5106
5107 // if t == 15 || m == 15 then UNPREDICTABLE;
5108 if ((t == 15) || (m == 15))
5109 return false;
5110
5111 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5112 if (wback && ((n == 15) || (n == t)))
5113 return false;
5114
5115 break;
5116
5117 default:
5118 return false;
5119 }
5120
5121 uint32_t Rm = ReadCoreReg (m, &success);
5122 if (!success)
5123 return false;
5124
5125 uint32_t Rn = ReadCoreReg (n, &success);
5126 if (!success)
5127 return false;
5128
5129 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00005130 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
5131 if (!success)
5132 return false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005133
5134 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5135 addr_t offset_addr;
5136 if (add)
5137 offset_addr = Rn + offset;
5138 else
5139 offset_addr = Rn - offset;
5140
5141 // address = if index then offset_addr else R[n];
5142 addr_t address;
5143 if (index)
5144 address = offset_addr;
5145 else
5146 address = Rn;
5147
5148 EmulateInstruction::Context context;
5149 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005150 RegisterInfo base_reg;
5151 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5152 RegisterInfo offset_reg;
5153 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005154
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005155 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005156 if (UnalignedSupport() || BitIsClear (address, 0))
5157 {
5158 // MemU[address,2] = R[t]<15:0>;
5159 uint32_t Rt = ReadCoreReg (t, &success);
5160 if (!success)
5161 return false;
5162
5163 EmulateInstruction::Context context;
5164 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005165 RegisterInfo base_reg;
5166 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5167 RegisterInfo offset_reg;
5168 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5169 RegisterInfo data_reg;
5170 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005171 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5172
5173 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5174 return false;
5175 }
5176 else // Can only occur before ARMv7
5177 {
5178 // MemU[address,2] = bits(16) UNKNOWN;
5179 }
5180
5181 // if wback then R[n] = offset_addr;
5182 if (wback)
5183 {
5184 context.type = eContextAdjustBaseRegister;
5185 context.SetAddress (offset_addr);
5186 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5187 return false;
5188 }
5189 }
5190
5191 return true;
5192}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005193
Johnny Chen157b9592011-02-18 21:13:05 +00005194// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5195// and writes the result to the destination register. It can optionally update the condition flags
5196// based on the result.
5197bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005198EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005199{
5200#if 0
5201 // ARM pseudo code...
5202 if ConditionPassed() then
5203 EncodingSpecificOperations();
5204 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5205 if d == 15 then // Can only occur for ARM encoding
5206 ALUWritePC(result); // setflags is always FALSE here
5207 else
5208 R[d] = result;
5209 if setflags then
5210 APSR.N = result<31>;
5211 APSR.Z = IsZeroBit(result);
5212 APSR.C = carry;
5213 APSR.V = overflow;
5214#endif
5215
5216 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005217
Greg Clayton7bc39082011-03-24 23:53:38 +00005218 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005219 {
5220 uint32_t Rd, Rn;
5221 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5222 bool setflags;
5223 switch (encoding)
5224 {
5225 case eEncodingT1:
5226 Rd = Bits32(opcode, 11, 8);
5227 Rn = Bits32(opcode, 19, 16);
5228 setflags = BitIsSet(opcode, 20);
5229 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5230 if (BadReg(Rd) || BadReg(Rn))
5231 return false;
5232 break;
5233 case eEncodingA1:
5234 Rd = Bits32(opcode, 15, 12);
5235 Rn = Bits32(opcode, 19, 16);
5236 setflags = BitIsSet(opcode, 20);
5237 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005238
Johnny Chen157b9592011-02-18 21:13:05 +00005239 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005240 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005241 break;
5242 default:
5243 return false;
5244 }
5245
5246 // Read the first operand.
5247 int32_t val1 = ReadCoreReg(Rn, &success);
5248 if (!success)
5249 return false;
5250
5251 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5252
5253 EmulateInstruction::Context context;
5254 context.type = EmulateInstruction::eContextImmediate;
5255 context.SetNoArgs ();
5256
5257 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5258 return false;
5259 }
5260 return true;
5261}
5262
5263// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5264// register value, and writes the result to the destination register. It can optionally update the
5265// condition flags based on the result.
5266bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005267EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005268{
5269#if 0
5270 // ARM pseudo code...
5271 if ConditionPassed() then
5272 EncodingSpecificOperations();
5273 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5274 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5275 if d == 15 then // Can only occur for ARM encoding
5276 ALUWritePC(result); // setflags is always FALSE here
5277 else
5278 R[d] = result;
5279 if setflags then
5280 APSR.N = result<31>;
5281 APSR.Z = IsZeroBit(result);
5282 APSR.C = carry;
5283 APSR.V = overflow;
5284#endif
5285
5286 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005287
Greg Clayton7bc39082011-03-24 23:53:38 +00005288 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005289 {
5290 uint32_t Rd, Rn, Rm;
5291 ARM_ShifterType shift_t;
5292 uint32_t shift_n; // the shift applied to the value read from Rm
5293 bool setflags;
5294 switch (encoding)
5295 {
5296 case eEncodingT1:
5297 Rd = Rn = Bits32(opcode, 2, 0);
5298 Rm = Bits32(opcode, 5, 3);
5299 setflags = !InITBlock();
5300 shift_t = SRType_LSL;
5301 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005302 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005303 case eEncodingT2:
5304 Rd = Bits32(opcode, 11, 8);
5305 Rn = Bits32(opcode, 19, 16);
5306 Rm = Bits32(opcode, 3, 0);
5307 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005308 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005309 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5310 return false;
5311 break;
5312 case eEncodingA1:
5313 Rd = Bits32(opcode, 15, 12);
5314 Rn = Bits32(opcode, 19, 16);
5315 Rm = Bits32(opcode, 3, 0);
5316 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005317 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005318
Johnny Chen157b9592011-02-18 21:13:05 +00005319 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005320 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005321 break;
5322 default:
5323 return false;
5324 }
5325
5326 // Read the first operand.
5327 int32_t val1 = ReadCoreReg(Rn, &success);
5328 if (!success)
5329 return false;
5330
5331 // Read the second operand.
5332 int32_t val2 = ReadCoreReg(Rm, &success);
5333 if (!success)
5334 return false;
5335
Johnny Chena4438a72011-06-02 22:50:51 +00005336 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5337 if (!success)
5338 return false;
Johnny Chen157b9592011-02-18 21:13:05 +00005339 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5340
5341 EmulateInstruction::Context context;
5342 context.type = EmulateInstruction::eContextImmediate;
5343 context.SetNoArgs ();
5344
5345 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5346 return false;
5347 }
5348 return true;
5349}
5350
Johnny Chena695f952011-02-23 21:24:25 +00005351// This instruction adds an immediate value to the PC value to form a PC-relative address,
5352// and writes the result to the destination register.
5353bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005354EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005355{
5356#if 0
5357 // ARM pseudo code...
5358 if ConditionPassed() then
5359 EncodingSpecificOperations();
5360 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5361 if d == 15 then // Can only occur for ARM encodings
5362 ALUWritePC(result);
5363 else
5364 R[d] = result;
5365#endif
5366
5367 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005368
Greg Clayton7bc39082011-03-24 23:53:38 +00005369 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005370 {
5371 uint32_t Rd;
5372 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5373 bool add;
5374 switch (encoding)
5375 {
5376 case eEncodingT1:
5377 Rd = Bits32(opcode, 10, 8);
5378 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5379 break;
5380 case eEncodingT2:
5381 case eEncodingT3:
5382 Rd = Bits32(opcode, 11, 8);
5383 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5384 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5385 if (BadReg(Rd))
5386 return false;
5387 break;
5388 case eEncodingA1:
5389 case eEncodingA2:
5390 Rd = Bits32(opcode, 15, 12);
5391 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5392 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5393 break;
5394 default:
5395 return false;
5396 }
5397
5398 // Read the PC value.
5399 uint32_t pc = ReadCoreReg(PC_REG, &success);
5400 if (!success)
5401 return false;
5402
5403 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5404
5405 EmulateInstruction::Context context;
5406 context.type = EmulateInstruction::eContextImmediate;
5407 context.SetNoArgs ();
5408
5409 if (!WriteCoreReg(context, result, Rd))
5410 return false;
5411 }
5412 return true;
5413}
5414
Johnny Chene97c0d52011-02-18 19:32:20 +00005415// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5416// to the destination register. It can optionally update the condition flags based on the result.
5417bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005418EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005419{
5420#if 0
5421 // ARM pseudo code...
5422 if ConditionPassed() then
5423 EncodingSpecificOperations();
5424 result = R[n] AND imm32;
5425 if d == 15 then // Can only occur for ARM encoding
5426 ALUWritePC(result); // setflags is always FALSE here
5427 else
5428 R[d] = result;
5429 if setflags then
5430 APSR.N = result<31>;
5431 APSR.Z = IsZeroBit(result);
5432 APSR.C = carry;
5433 // APSR.V unchanged
5434#endif
5435
5436 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005437
Greg Clayton7bc39082011-03-24 23:53:38 +00005438 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005439 {
5440 uint32_t Rd, Rn;
5441 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5442 bool setflags;
5443 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5444 switch (encoding)
5445 {
5446 case eEncodingT1:
5447 Rd = Bits32(opcode, 11, 8);
5448 Rn = Bits32(opcode, 19, 16);
5449 setflags = BitIsSet(opcode, 20);
5450 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005451 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005452 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005453 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005454 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5455 return false;
5456 break;
5457 case eEncodingA1:
5458 Rd = Bits32(opcode, 15, 12);
5459 Rn = Bits32(opcode, 19, 16);
5460 setflags = BitIsSet(opcode, 20);
5461 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005462
Johnny Chene97c0d52011-02-18 19:32:20 +00005463 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005464 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005465 break;
5466 default:
5467 return false;
5468 }
5469
Johnny Chene97c0d52011-02-18 19:32:20 +00005470 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005471 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005472 if (!success)
5473 return false;
5474
5475 uint32_t result = val1 & imm32;
5476
5477 EmulateInstruction::Context context;
5478 context.type = EmulateInstruction::eContextImmediate;
5479 context.SetNoArgs ();
5480
5481 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5482 return false;
5483 }
5484 return true;
5485}
5486
5487// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5488// and writes the result to the destination register. It can optionally update the condition flags
5489// based on the result.
5490bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005491EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005492{
5493#if 0
5494 // ARM pseudo code...
5495 if ConditionPassed() then
5496 EncodingSpecificOperations();
5497 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5498 result = R[n] AND shifted;
5499 if d == 15 then // Can only occur for ARM encoding
5500 ALUWritePC(result); // setflags is always FALSE here
5501 else
5502 R[d] = result;
5503 if setflags then
5504 APSR.N = result<31>;
5505 APSR.Z = IsZeroBit(result);
5506 APSR.C = carry;
5507 // APSR.V unchanged
5508#endif
5509
5510 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005511
Greg Clayton7bc39082011-03-24 23:53:38 +00005512 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005513 {
5514 uint32_t Rd, Rn, Rm;
5515 ARM_ShifterType shift_t;
5516 uint32_t shift_n; // the shift applied to the value read from Rm
5517 bool setflags;
5518 uint32_t carry;
5519 switch (encoding)
5520 {
5521 case eEncodingT1:
5522 Rd = Rn = Bits32(opcode, 2, 0);
5523 Rm = Bits32(opcode, 5, 3);
5524 setflags = !InITBlock();
5525 shift_t = SRType_LSL;
5526 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005527 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005528 case eEncodingT2:
5529 Rd = Bits32(opcode, 11, 8);
5530 Rn = Bits32(opcode, 19, 16);
5531 Rm = Bits32(opcode, 3, 0);
5532 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005533 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005534 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005535 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005536 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005537 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5538 return false;
5539 break;
5540 case eEncodingA1:
5541 Rd = Bits32(opcode, 15, 12);
5542 Rn = Bits32(opcode, 19, 16);
5543 Rm = Bits32(opcode, 3, 0);
5544 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005545 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005546
Johnny Chene97c0d52011-02-18 19:32:20 +00005547 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005548 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005549 break;
5550 default:
5551 return false;
5552 }
5553
Johnny Chene97c0d52011-02-18 19:32:20 +00005554 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005555 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005556 if (!success)
5557 return false;
5558
5559 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005560 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005561 if (!success)
5562 return false;
5563
Johnny Chena4438a72011-06-02 22:50:51 +00005564 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5565 if (!success)
5566 return false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005567 uint32_t result = val1 & shifted;
5568
5569 EmulateInstruction::Context context;
5570 context.type = EmulateInstruction::eContextImmediate;
5571 context.SetNoArgs ();
5572
5573 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5574 return false;
5575 }
5576 return true;
5577}
5578
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005579// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5580// immediate value, and writes the result to the destination register. It can optionally update the
5581// condition flags based on the result.
5582bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005583EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005584{
5585#if 0
5586 // ARM pseudo code...
5587 if ConditionPassed() then
5588 EncodingSpecificOperations();
5589 result = R[n] AND NOT(imm32);
5590 if d == 15 then // Can only occur for ARM encoding
5591 ALUWritePC(result); // setflags is always FALSE here
5592 else
5593 R[d] = result;
5594 if setflags then
5595 APSR.N = result<31>;
5596 APSR.Z = IsZeroBit(result);
5597 APSR.C = carry;
5598 // APSR.V unchanged
5599#endif
5600
5601 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005602
Greg Clayton7bc39082011-03-24 23:53:38 +00005603 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005604 {
5605 uint32_t Rd, Rn;
5606 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5607 bool setflags;
5608 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5609 switch (encoding)
5610 {
5611 case eEncodingT1:
5612 Rd = Bits32(opcode, 11, 8);
5613 Rn = Bits32(opcode, 19, 16);
5614 setflags = BitIsSet(opcode, 20);
5615 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5616 if (BadReg(Rd) || BadReg(Rn))
5617 return false;
5618 break;
5619 case eEncodingA1:
5620 Rd = Bits32(opcode, 15, 12);
5621 Rn = Bits32(opcode, 19, 16);
5622 setflags = BitIsSet(opcode, 20);
5623 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005624
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005625 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005626 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005627 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005628 break;
5629 default:
5630 return false;
5631 }
5632
5633 // Read the first operand.
5634 uint32_t val1 = ReadCoreReg(Rn, &success);
5635 if (!success)
5636 return false;
5637
5638 uint32_t result = val1 & ~imm32;
5639
5640 EmulateInstruction::Context context;
5641 context.type = EmulateInstruction::eContextImmediate;
5642 context.SetNoArgs ();
5643
5644 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5645 return false;
5646 }
5647 return true;
5648}
5649
5650// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5651// optionally-shifted register value, and writes the result to the destination register.
5652// It can optionally update the condition flags based on the result.
5653bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005654EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005655{
5656#if 0
5657 // ARM pseudo code...
5658 if ConditionPassed() then
5659 EncodingSpecificOperations();
5660 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5661 result = R[n] AND NOT(shifted);
5662 if d == 15 then // Can only occur for ARM encoding
5663 ALUWritePC(result); // setflags is always FALSE here
5664 else
5665 R[d] = result;
5666 if setflags then
5667 APSR.N = result<31>;
5668 APSR.Z = IsZeroBit(result);
5669 APSR.C = carry;
5670 // APSR.V unchanged
5671#endif
5672
5673 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005674
Greg Clayton7bc39082011-03-24 23:53:38 +00005675 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005676 {
5677 uint32_t Rd, Rn, Rm;
5678 ARM_ShifterType shift_t;
5679 uint32_t shift_n; // the shift applied to the value read from Rm
5680 bool setflags;
5681 uint32_t carry;
5682 switch (encoding)
5683 {
5684 case eEncodingT1:
5685 Rd = Rn = Bits32(opcode, 2, 0);
5686 Rm = Bits32(opcode, 5, 3);
5687 setflags = !InITBlock();
5688 shift_t = SRType_LSL;
5689 shift_n = 0;
5690 break;
5691 case eEncodingT2:
5692 Rd = Bits32(opcode, 11, 8);
5693 Rn = Bits32(opcode, 19, 16);
5694 Rm = Bits32(opcode, 3, 0);
5695 setflags = BitIsSet(opcode, 20);
5696 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5697 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5698 return false;
5699 break;
5700 case eEncodingA1:
5701 Rd = Bits32(opcode, 15, 12);
5702 Rn = Bits32(opcode, 19, 16);
5703 Rm = Bits32(opcode, 3, 0);
5704 setflags = BitIsSet(opcode, 20);
5705 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005706
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005707 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005708 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005709 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005710 break;
5711 default:
5712 return false;
5713 }
5714
5715 // Read the first operand.
5716 uint32_t val1 = ReadCoreReg(Rn, &success);
5717 if (!success)
5718 return false;
5719
5720 // Read the second operand.
5721 uint32_t val2 = ReadCoreReg(Rm, &success);
5722 if (!success)
5723 return false;
5724
Johnny Chena4438a72011-06-02 22:50:51 +00005725 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5726 if (!success)
5727 return false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005728 uint32_t result = val1 & ~shifted;
5729
5730 EmulateInstruction::Context context;
5731 context.type = EmulateInstruction::eContextImmediate;
5732 context.SetNoArgs ();
5733
5734 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5735 return false;
5736 }
5737 return true;
5738}
5739
Caroline Tice4d729c52011-02-18 00:55:53 +00005740// 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 +00005741// 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 +00005742bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005743EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005744{
5745#if 0
5746 if ConditionPassed() then
5747 EncodingSpecificOperations();
5748 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5749 address = if index then offset_addr else R[n];
5750 data = MemU[address,4];
5751 if wback then R[n] = offset_addr;
5752 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005753 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5754 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005755 R[t] = data;
5756 else // Can only apply before ARMv7
5757 R[t] = ROR(data, 8*UInt(address<1:0>));
5758#endif
5759
5760 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005761
Greg Clayton7bc39082011-03-24 23:53:38 +00005762 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005763 {
5764 const uint32_t addr_byte_size = GetAddressByteSize();
5765
5766 uint32_t t;
5767 uint32_t n;
5768 uint32_t imm32;
5769 bool index;
5770 bool add;
5771 bool wback;
5772
5773 switch (encoding)
5774 {
5775 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005776 // if Rn == '1111' then SEE LDR (literal);
5777 // if P == '0' && W == '1' then SEE LDRT;
5778 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005779 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5780 t = Bits32 (opcode, 15, 12);
5781 n = Bits32 (opcode, 19, 16);
5782 imm32 = Bits32 (opcode, 11, 0);
5783
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005784 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5785 index = BitIsSet (opcode, 24);
5786 add = BitIsSet (opcode, 23);
5787 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005788
5789 // if wback && n == t then UNPREDICTABLE;
5790 if (wback && (n == t))
5791 return false;
5792
5793 break;
5794
5795 default:
5796 return false;
5797 }
5798
5799 addr_t address;
5800 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005801 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005802 if (!success)
5803 return false;
5804
5805 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5806 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005807 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005808 else
5809 offset_addr = base_address - imm32;
5810
5811 // address = if index then offset_addr else R[n];
5812 if (index)
5813 address = offset_addr;
5814 else
5815 address = base_address;
5816
5817 // data = MemU[address,4];
5818
Greg Claytonc07d4512011-04-26 23:48:45 +00005819 RegisterInfo base_reg;
5820 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4d729c52011-02-18 00:55:53 +00005821
5822 EmulateInstruction::Context context;
5823 context.type = eContextRegisterLoad;
5824 context.SetRegisterPlusOffset (base_reg, address - base_address);
5825
5826 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5827 if (!success)
5828 return false;
5829
5830 // if wback then R[n] = offset_addr;
5831 if (wback)
5832 {
5833 context.type = eContextAdjustBaseRegister;
5834 context.SetAddress (offset_addr);
5835 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5836 return false;
5837 }
5838
5839 // if t == 15 then
5840 if (t == 15)
5841 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005842 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005843 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5844 {
5845 // LoadWritePC (data);
5846 context.type = eContextRegisterLoad;
5847 context.SetRegisterPlusOffset (base_reg, address - base_address);
5848 LoadWritePC (context, data);
5849 }
5850 else
5851 return false;
5852 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005853 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005854 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5855 {
5856 // R[t] = data;
5857 context.type = eContextRegisterLoad;
5858 context.SetRegisterPlusOffset (base_reg, address - base_address);
5859 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5860 return false;
5861 }
5862 // else // Can only apply before ARMv7
5863 else
5864 {
5865 // R[t] = ROR(data, 8*UInt(address<1:0>));
Johnny Chena4438a72011-06-02 22:50:51 +00005866 data = ROR (data, Bits32 (address, 1, 0), &success);
5867 if (!success)
5868 return false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005869 context.type = eContextRegisterLoad;
5870 context.SetImmediate (data);
5871 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5872 return false;
5873 }
5874
5875 }
5876 return true;
5877}
5878
Caroline Ticefe479112011-02-18 18:52:37 +00005879// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5880// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5881bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005882EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005883{
5884#if 0
5885 if ConditionPassed() then
5886 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5887 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5888 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5889 address = if index then offset_addr else R[n];
5890 data = MemU[address,4];
5891 if wback then R[n] = offset_addr;
5892 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005893 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5894 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005895 R[t] = data;
5896 else // Can only apply before ARMv7
5897 if CurrentInstrSet() == InstrSet_ARM then
5898 R[t] = ROR(data, 8*UInt(address<1:0>));
5899 else
5900 R[t] = bits(32) UNKNOWN;
5901#endif
5902
5903 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005904
Greg Clayton7bc39082011-03-24 23:53:38 +00005905 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005906 {
5907 const uint32_t addr_byte_size = GetAddressByteSize();
5908
5909 uint32_t t;
5910 uint32_t n;
5911 uint32_t m;
5912 bool index;
5913 bool add;
5914 bool wback;
5915 ARM_ShifterType shift_t;
5916 uint32_t shift_n;
5917
5918 switch (encoding)
5919 {
5920 case eEncodingT1:
5921 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5922 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5923 t = Bits32 (opcode, 2, 0);
5924 n = Bits32 (opcode, 5, 3);
5925 m = Bits32 (opcode, 8, 6);
5926
5927 // index = TRUE; add = TRUE; wback = FALSE;
5928 index = true;
5929 add = true;
5930 wback = false;
5931
5932 // (shift_t, shift_n) = (SRType_LSL, 0);
5933 shift_t = SRType_LSL;
5934 shift_n = 0;
5935
5936 break;
5937
5938 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005939 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005940 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5941 t = Bits32 (opcode, 15, 12);
5942 n = Bits32 (opcode, 19, 16);
5943 m = Bits32 (opcode, 3, 0);
5944
5945 // index = TRUE; add = TRUE; wback = FALSE;
5946 index = true;
5947 add = true;
5948 wback = false;
5949
5950 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5951 shift_t = SRType_LSL;
5952 shift_n = Bits32 (opcode, 5, 4);
5953
5954 // if BadReg(m) then UNPREDICTABLE;
5955 if (BadReg (m))
5956 return false;
5957
5958 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5959 if ((t == 15) && InITBlock() && !LastInITBlock())
5960 return false;
5961
5962 break;
5963
5964 case eEncodingA1:
5965 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005966 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005967 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5968 t = Bits32 (opcode, 15, 12);
5969 n = Bits32 (opcode, 19, 16);
5970 m = Bits32 (opcode, 3, 0);
5971
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005972 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005973 index = BitIsSet (opcode, 24);
5974 add = BitIsSet (opcode, 23);
5975 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5976
5977 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5978 uint32_t type = Bits32 (opcode, 6, 5);
5979 uint32_t imm5 = Bits32 (opcode, 11, 7);
5980 shift_n = DecodeImmShift (type, imm5, shift_t);
5981
5982 // if m == 15 then UNPREDICTABLE;
5983 if (m == 15)
5984 return false;
5985
5986 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5987 if (wback && ((n == 15) || (n == t)))
5988 return false;
5989 }
5990 break;
5991
5992
5993 default:
5994 return false;
5995 }
5996
5997 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5998 if (!success)
5999 return false;
6000
6001 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6002 if (!success)
6003 return false;
6004
6005 addr_t offset_addr;
6006 addr_t address;
6007
6008 // 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 +00006009 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C), &success);
6010 if (!success)
6011 return false;
Caroline Ticefe479112011-02-18 18:52:37 +00006012
6013 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6014 if (add)
6015 offset_addr = Rn + offset;
6016 else
6017 offset_addr = Rn - offset;
6018
6019 // address = if index then offset_addr else R[n];
6020 if (index)
6021 address = offset_addr;
6022 else
6023 address = Rn;
6024
6025 // data = MemU[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +00006026 RegisterInfo base_reg;
6027 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefe479112011-02-18 18:52:37 +00006028
6029 EmulateInstruction::Context context;
6030 context.type = eContextRegisterLoad;
6031 context.SetRegisterPlusOffset (base_reg, address - Rn);
6032
6033 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
6034 if (!success)
6035 return false;
6036
6037 // if wback then R[n] = offset_addr;
6038 if (wback)
6039 {
6040 context.type = eContextAdjustBaseRegister;
6041 context.SetAddress (offset_addr);
6042 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6043 return false;
6044 }
6045
6046 // if t == 15 then
6047 if (t == 15)
6048 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006049 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00006050 if (BitIsClear (address, 1) && BitIsClear (address, 0))
6051 {
6052 context.type = eContextRegisterLoad;
6053 context.SetRegisterPlusOffset (base_reg, address - Rn);
6054 LoadWritePC (context, data);
6055 }
6056 else
6057 return false;
6058 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006059 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00006060 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
6061 {
6062 // R[t] = data;
6063 context.type = eContextRegisterLoad;
6064 context.SetRegisterPlusOffset (base_reg, address - Rn);
6065 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6066 return false;
6067 }
6068 else // Can only apply before ARMv7
6069 {
6070 // if CurrentInstrSet() == InstrSet_ARM then
6071 if (CurrentInstrSet () == eModeARM)
6072 {
6073 // R[t] = ROR(data, 8*UInt(address<1:0>));
Johnny Chena4438a72011-06-02 22:50:51 +00006074 data = ROR (data, Bits32 (address, 1, 0), &success);
6075 if (!success)
6076 return false;
Caroline Ticefe479112011-02-18 18:52:37 +00006077 context.type = eContextRegisterLoad;
6078 context.SetImmediate (data);
6079 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6080 return false;
6081 }
6082 else
6083 {
6084 // R[t] = bits(32) UNKNOWN;
6085 WriteBits32Unknown (t);
6086 }
6087 }
6088 }
6089 return true;
6090}
Caroline Tice21b604b2011-02-18 21:06:04 +00006091
6092// LDRB (immediate, Thumb)
6093bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006094EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00006095{
6096#if 0
6097 if ConditionPassed() then
6098 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6099 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6100 address = if index then offset_addr else R[n];
6101 R[t] = ZeroExtend(MemU[address,1], 32);
6102 if wback then R[n] = offset_addr;
6103#endif
6104
6105 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00006106
Greg Clayton7bc39082011-03-24 23:53:38 +00006107 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00006108 {
6109 uint32_t t;
6110 uint32_t n;
6111 uint32_t imm32;
6112 bool index;
6113 bool add;
6114 bool wback;
6115
6116 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6117 switch (encoding)
6118 {
6119 case eEncodingT1:
6120 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6121 t = Bits32 (opcode, 2, 0);
6122 n = Bits32 (opcode, 5, 3);
6123 imm32 = Bits32 (opcode, 10, 6);
6124
6125 // index = TRUE; add = TRUE; wback = FALSE;
6126 index = true;
6127 add = true;
6128 wback= false;
6129
6130 break;
6131
6132 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006133 // if Rt == '1111' then SEE PLD;
6134 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006135 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6136 t = Bits32 (opcode, 15, 12);
6137 n = Bits32 (opcode, 19, 16);
6138 imm32 = Bits32 (opcode, 11, 0);
6139
6140 // index = TRUE; add = TRUE; wback = FALSE;
6141 index = true;
6142 add = true;
6143 wback = false;
6144
6145 // if t == 13 then UNPREDICTABLE;
6146 if (t == 13)
6147 return false;
6148
6149 break;
6150
6151 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006152 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6153 // if Rn == '1111' then SEE LDRB (literal);
6154 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6155 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006156 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6157 return false;
6158
6159 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6160 t = Bits32 (opcode, 15, 12);
6161 n = Bits32 (opcode, 19, 16);
6162 imm32 = Bits32 (opcode, 7, 0);
6163
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006164 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006165 index = BitIsSet (opcode, 10);
6166 add = BitIsSet (opcode, 9);
6167 wback = BitIsSet (opcode, 8);
6168
6169 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6170 if (BadReg (t) || (wback && (n == t)))
6171 return false;
6172
6173 break;
6174
6175 default:
6176 return false;
6177 }
6178
6179 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6180 if (!success)
6181 return false;
6182
6183 addr_t address;
6184 addr_t offset_addr;
6185
6186 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6187 if (add)
6188 offset_addr = Rn + imm32;
6189 else
6190 offset_addr = Rn - imm32;
6191
6192 // address = if index then offset_addr else R[n];
6193 if (index)
6194 address = offset_addr;
6195 else
6196 address = Rn;
6197
6198 // R[t] = ZeroExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006199 RegisterInfo base_reg;
6200 RegisterInfo data_reg;
6201 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6202 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice21b604b2011-02-18 21:06:04 +00006203
6204 EmulateInstruction::Context context;
6205 context.type = eContextRegisterLoad;
6206 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6207
6208 uint64_t data = MemURead (context, address, 1, 0, &success);
6209 if (!success)
6210 return false;
6211
6212 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6213 return false;
6214
6215 // if wback then R[n] = offset_addr;
6216 if (wback)
6217 {
6218 context.type = eContextAdjustBaseRegister;
6219 context.SetAddress (offset_addr);
6220 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6221 return false;
6222 }
6223 }
6224 return true;
6225}
Caroline Ticef55261f2011-02-18 22:24:22 +00006226
6227// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6228// zero-extends it to form a 32-bit word and writes it to a register.
6229bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006230EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006231{
6232#if 0
6233 if ConditionPassed() then
6234 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6235 base = Align(PC,4);
6236 address = if add then (base + imm32) else (base - imm32);
6237 R[t] = ZeroExtend(MemU[address,1], 32);
6238#endif
6239
6240 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006241
Greg Clayton7bc39082011-03-24 23:53:38 +00006242 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006243 {
6244 uint32_t t;
6245 uint32_t imm32;
6246 bool add;
6247 switch (encoding)
6248 {
6249 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006250 // if Rt == '1111' then SEE PLD;
6251 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006252 t = Bits32 (opcode, 15, 12);
6253 imm32 = Bits32 (opcode, 11, 0);
6254 add = BitIsSet (opcode, 23);
6255
6256 // if t == 13 then UNPREDICTABLE;
6257 if (t == 13)
6258 return false;
6259
6260 break;
6261
6262 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006263 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006264 t = Bits32 (opcode, 15, 12);
6265 imm32 = Bits32 (opcode, 11, 0);
6266 add = BitIsSet (opcode, 23);
6267
6268 // if t == 15 then UNPREDICTABLE;
6269 if (t == 15)
6270 return false;
6271 break;
6272
6273 default:
6274 return false;
6275 }
6276
6277 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006278 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006279 if (!success)
6280 return false;
6281
6282 uint32_t base = AlignPC (pc_val);
6283
6284 addr_t address;
6285 // address = if add then (base + imm32) else (base - imm32);
6286 if (add)
6287 address = base + imm32;
6288 else
6289 address = base - imm32;
6290
6291 // R[t] = ZeroExtend(MemU[address,1], 32);
6292 EmulateInstruction::Context context;
6293 context.type = eContextRelativeBranchImmediate;
6294 context.SetImmediate (address - base);
6295
6296 uint64_t data = MemURead (context, address, 1, 0, &success);
6297 if (!success)
6298 return false;
6299
6300 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6301 return false;
6302 }
6303 return true;
6304}
Caroline Tice30fec122011-02-18 23:52:21 +00006305
6306// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6307// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6308// optionally be shifted.
6309bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006310EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006311{
6312#if 0
6313 if ConditionPassed() then
6314 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6315 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6316 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6317 address = if index then offset_addr else R[n];
6318 R[t] = ZeroExtend(MemU[address,1],32);
6319 if wback then R[n] = offset_addr;
6320#endif
6321
6322 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006323
Greg Clayton7bc39082011-03-24 23:53:38 +00006324 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006325 {
6326 uint32_t t;
6327 uint32_t n;
6328 uint32_t m;
6329 bool index;
6330 bool add;
6331 bool wback;
6332 ARM_ShifterType shift_t;
6333 uint32_t shift_n;
6334
6335 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6336 switch (encoding)
6337 {
6338 case eEncodingT1:
6339 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6340 t = Bits32 (opcode, 2, 0);
6341 n = Bits32 (opcode, 5, 3);
6342 m = Bits32 (opcode, 8, 6);
6343
6344 // index = TRUE; add = TRUE; wback = FALSE;
6345 index = true;
6346 add = true;
6347 wback = false;
6348
6349 // (shift_t, shift_n) = (SRType_LSL, 0);
6350 shift_t = SRType_LSL;
6351 shift_n = 0;
6352 break;
6353
6354 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006355 // if Rt == '1111' then SEE PLD;
6356 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006357 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6358 t = Bits32 (opcode, 15, 12);
6359 n = Bits32 (opcode, 19, 16);
6360 m = Bits32 (opcode, 3, 0);
6361
6362 // index = TRUE; add = TRUE; wback = FALSE;
6363 index = true;
6364 add = true;
6365 wback = false;
6366
6367 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6368 shift_t = SRType_LSL;
6369 shift_n = Bits32 (opcode, 5, 4);
6370
6371 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6372 if ((t == 13) || BadReg (m))
6373 return false;
6374 break;
6375
6376 case eEncodingA1:
6377 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006378 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006379 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6380 t = Bits32 (opcode, 15, 12);
6381 n = Bits32 (opcode, 19, 16);
6382 m = Bits32 (opcode, 3, 0);
6383
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006384 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006385 index = BitIsSet (opcode, 24);
6386 add = BitIsSet (opcode, 23);
6387 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6388
6389 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6390 uint32_t type = Bits32 (opcode, 6, 5);
6391 uint32_t imm5 = Bits32 (opcode, 11, 7);
6392 shift_n = DecodeImmShift (type, imm5, shift_t);
6393
6394 // if t == 15 || m == 15 then UNPREDICTABLE;
6395 if ((t == 15) || (m == 15))
6396 return false;
6397
6398 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6399 if (wback && ((n == 15) || (n == t)))
6400 return false;
6401 }
6402 break;
6403
6404 default:
6405 return false;
6406 }
6407
6408 addr_t offset_addr;
6409 addr_t address;
6410
6411 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6412 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6413 if (!success)
6414 return false;
6415
Johnny Chena4438a72011-06-02 22:50:51 +00006416 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6417 if (!success)
6418 return false;
Caroline Tice30fec122011-02-18 23:52:21 +00006419
6420 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6421 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6422 if (!success)
6423 return false;
6424
6425 if (add)
6426 offset_addr = Rn + offset;
6427 else
6428 offset_addr = Rn - offset;
6429
6430 // address = if index then offset_addr else R[n];
6431 if (index)
6432 address = offset_addr;
6433 else
6434 address = Rn;
6435
6436 // R[t] = ZeroExtend(MemU[address,1],32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006437 RegisterInfo base_reg;
6438 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice30fec122011-02-18 23:52:21 +00006439
6440 EmulateInstruction::Context context;
6441 context.type = eContextRegisterLoad;
6442 context.SetRegisterPlusOffset (base_reg, address - Rn);
6443
6444 uint64_t data = MemURead (context, address, 1, 0, &success);
6445 if (!success)
6446 return false;
6447
6448 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6449 return false;
6450
6451 // if wback then R[n] = offset_addr;
6452 if (wback)
6453 {
6454 context.type = eContextAdjustBaseRegister;
6455 context.SetAddress (offset_addr);
6456 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6457 return false;
6458 }
6459 }
6460 return true;
6461}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006462
6463// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6464// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6465// post-indexed, or pre-indexed addressing.
6466bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006467EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006468{
6469#if 0
6470 if ConditionPassed() then
6471 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6472 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6473 address = if index then offset_addr else R[n];
6474 data = MemU[address,2];
6475 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006476 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006477 R[t] = ZeroExtend(data, 32);
6478 else // Can only apply before ARMv7
6479 R[t] = bits(32) UNKNOWN;
6480#endif
6481
6482
6483 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006484
Greg Clayton7bc39082011-03-24 23:53:38 +00006485 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006486 {
6487 uint32_t t;
6488 uint32_t n;
6489 uint32_t imm32;
6490 bool index;
6491 bool add;
6492 bool wback;
6493
6494 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6495 switch (encoding)
6496 {
6497 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006498 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006499 t = Bits32 (opcode, 2, 0);
6500 n = Bits32 (opcode, 5, 3);
6501 imm32 = Bits32 (opcode, 10, 6) << 1;
6502
6503 // index = TRUE; add = TRUE; wback = FALSE;
6504 index = true;
6505 add = true;
6506 wback = false;
6507
6508 break;
6509
6510 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006511 // if Rt == '1111' then SEE "Unallocated memory hints";
6512 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006513 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6514 t = Bits32 (opcode, 15, 12);
6515 n = Bits32 (opcode, 19, 16);
6516 imm32 = Bits32 (opcode, 11, 0);
6517
6518 // index = TRUE; add = TRUE; wback = FALSE;
6519 index = true;
6520 add = true;
6521 wback = false;
6522
6523 // if t == 13 then UNPREDICTABLE;
6524 if (t == 13)
6525 return false;
6526 break;
6527
6528 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006529 // if Rn == '1111' then SEE LDRH (literal);
6530 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6531 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6532 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006533 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6534 return false;
6535
6536 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6537 t = Bits32 (opcode, 15, 12);
6538 n = Bits32 (opcode, 19, 16);
6539 imm32 = Bits32 (opcode, 7, 0);
6540
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006541 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006542 index = BitIsSet (opcode, 10);
6543 add = BitIsSet (opcode, 9);
6544 wback = BitIsSet (opcode, 8);
6545
6546 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6547 if (BadReg (t) || (wback && (n == t)))
6548 return false;
6549 break;
6550
6551 default:
6552 return false;
6553 }
6554
6555 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6556 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6557 if (!success)
6558 return false;
6559
6560 addr_t offset_addr;
6561 addr_t address;
6562
6563 if (add)
6564 offset_addr = Rn + imm32;
6565 else
6566 offset_addr = Rn - imm32;
6567
6568 // address = if index then offset_addr else R[n];
6569 if (index)
6570 address = offset_addr;
6571 else
6572 address = Rn;
6573
6574 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006575 RegisterInfo base_reg;
6576 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006577
6578 EmulateInstruction::Context context;
6579 context.type = eContextRegisterLoad;
6580 context.SetRegisterPlusOffset (base_reg, address - Rn);
6581
6582 uint64_t data = MemURead (context, address, 2, 0, &success);
6583 if (!success)
6584 return false;
6585
6586 // if wback then R[n] = offset_addr;
6587 if (wback)
6588 {
6589 context.type = eContextAdjustBaseRegister;
6590 context.SetAddress (offset_addr);
6591 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6592 return false;
6593 }
6594
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006595 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006596 if (UnalignedSupport () || BitIsClear (address, 0))
6597 {
6598 // R[t] = ZeroExtend(data, 32);
6599 context.type = eContextRegisterLoad;
6600 context.SetRegisterPlusOffset (base_reg, address - Rn);
6601 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6602 return false;
6603 }
6604 else // Can only apply before ARMv7
6605 {
6606 // R[t] = bits(32) UNKNOWN;
6607 WriteBits32Unknown (t);
6608 }
6609 }
6610 return true;
6611}
Caroline Ticefe479112011-02-18 18:52:37 +00006612
Caroline Tice952b5382011-02-28 23:15:24 +00006613// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6614// zero-extends it to form a 32-bit word, and writes it to a register.
6615bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006616EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006617{
6618#if 0
6619 if ConditionPassed() then
6620 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6621 base = Align(PC,4);
6622 address = if add then (base + imm32) else (base - imm32);
6623 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006624 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006625 R[t] = ZeroExtend(data, 32);
6626 else // Can only apply before ARMv7
6627 R[t] = bits(32) UNKNOWN;
6628#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006629
Caroline Tice952b5382011-02-28 23:15:24 +00006630 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006631
Greg Clayton7bc39082011-03-24 23:53:38 +00006632 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006633 {
6634 uint32_t t;
6635 uint32_t imm32;
6636 bool add;
6637
6638 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6639 switch (encoding)
6640 {
6641 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006642 // if Rt == '1111' then SEE "Unallocated memory hints";
6643 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006644 t = Bits32 (opcode, 15, 12);
6645 imm32 = Bits32 (opcode, 11, 0);
6646 add = BitIsSet (opcode, 23);
6647
6648 // if t == 13 then UNPREDICTABLE;
6649 if (t == 13)
6650 return false;
6651
6652 break;
6653
6654 case eEncodingA1:
6655 {
6656 uint32_t imm4H = Bits32 (opcode, 11, 8);
6657 uint32_t imm4L = Bits32 (opcode, 3, 0);
6658
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006659 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006660 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006661 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006662 add = BitIsSet (opcode, 23);
6663
6664 // if t == 15 then UNPREDICTABLE;
6665 if (t == 15)
6666 return false;
6667 break;
6668 }
6669
6670 default:
6671 return false;
6672 }
6673
6674 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006675 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006676 if (!success)
6677 return false;
6678
6679 addr_t base = AlignPC (pc_value);
6680 addr_t address;
6681
6682 // address = if add then (base + imm32) else (base - imm32);
6683 if (add)
6684 address = base + imm32;
6685 else
6686 address = base - imm32;
6687
6688 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006689 RegisterInfo base_reg;
6690 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice952b5382011-02-28 23:15:24 +00006691
6692 EmulateInstruction::Context context;
6693 context.type = eContextRegisterLoad;
6694 context.SetRegisterPlusOffset (base_reg, address - base);
6695
6696 uint64_t data = MemURead (context, address, 2, 0, &success);
6697 if (!success)
6698 return false;
6699
6700
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006701 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006702 if (UnalignedSupport () || BitIsClear (address, 0))
6703 {
6704 // R[t] = ZeroExtend(data, 32);
6705 context.type = eContextRegisterLoad;
6706 context.SetRegisterPlusOffset (base_reg, address - base);
6707 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6708 return false;
6709
6710 }
6711 else // Can only apply before ARMv7
6712 {
6713 // R[t] = bits(32) UNKNOWN;
6714 WriteBits32Unknown (t);
6715 }
6716 }
6717 return true;
6718}
6719
Caroline Tice0e6bc952011-03-01 18:00:42 +00006720// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6721// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6722// be shifted left by 0, 1, 2, or 3 bits.
6723bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006724EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006725{
6726#if 0
6727 if ConditionPassed() then
6728 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6729 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6730 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6731 address = if index then offset_addr else R[n];
6732 data = MemU[address,2];
6733 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006734 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006735 R[t] = ZeroExtend(data, 32);
6736 else // Can only apply before ARMv7
6737 R[t] = bits(32) UNKNOWN;
6738#endif
6739
6740 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006741
Greg Clayton7bc39082011-03-24 23:53:38 +00006742 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006743 {
6744 uint32_t t;
6745 uint32_t n;
6746 uint32_t m;
6747 bool index;
6748 bool add;
6749 bool wback;
6750 ARM_ShifterType shift_t;
6751 uint32_t shift_n;
6752
6753 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6754 switch (encoding)
6755 {
6756 case eEncodingT1:
6757 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6758 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6759 t = Bits32 (opcode, 2, 0);
6760 n = Bits32 (opcode, 5, 3);
6761 m = Bits32 (opcode, 8, 6);
6762
6763 // index = TRUE; add = TRUE; wback = FALSE;
6764 index = true;
6765 add = true;
6766 wback = false;
6767
6768 // (shift_t, shift_n) = (SRType_LSL, 0);
6769 shift_t = SRType_LSL;
6770 shift_n = 0;
6771
6772 break;
6773
6774 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006775 // if Rn == '1111' then SEE LDRH (literal);
6776 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006777 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6778 t = Bits32 (opcode, 15, 12);
6779 n = Bits32 (opcode, 19, 16);
6780 m = Bits32 (opcode, 3, 0);
6781
6782 // index = TRUE; add = TRUE; wback = FALSE;
6783 index = true;
6784 add = true;
6785 wback = false;
6786
6787 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6788 shift_t = SRType_LSL;
6789 shift_n = Bits32 (opcode, 5, 4);
6790
6791 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6792 if ((t == 13) || BadReg (m))
6793 return false;
6794 break;
6795
6796 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006797 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006798 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6799 t = Bits32 (opcode, 15, 12);
6800 n = Bits32 (opcode, 19, 16);
6801 m = Bits32 (opcode, 3, 0);
6802
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006803 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006804 index = BitIsSet (opcode, 24);
6805 add = BitIsSet (opcode, 23);
6806 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6807
6808 // (shift_t, shift_n) = (SRType_LSL, 0);
6809 shift_t = SRType_LSL;
6810 shift_n = 0;
6811
6812 // if t == 15 || m == 15 then UNPREDICTABLE;
6813 if ((t == 15) || (m == 15))
6814 return false;
6815
6816 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6817 if (wback && ((n == 15) || (n == t)))
6818 return false;
6819
6820 break;
6821
6822 default:
6823 return false;
6824 }
6825
6826 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6827
6828 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6829 if (!success)
6830 return false;
6831
Johnny Chena4438a72011-06-02 22:50:51 +00006832 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6833 if (!success)
6834 return false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006835
6836 addr_t offset_addr;
6837 addr_t address;
6838
6839 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6840 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6841 if (!success)
6842 return false;
6843
6844 if (add)
6845 offset_addr = Rn + offset;
6846 else
6847 offset_addr = Rn - offset;
6848
6849 // address = if index then offset_addr else R[n];
6850 if (index)
6851 address = offset_addr;
6852 else
6853 address = Rn;
6854
6855 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006856 RegisterInfo base_reg;
6857 RegisterInfo offset_reg;
6858 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6859 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice0e6bc952011-03-01 18:00:42 +00006860
6861 EmulateInstruction::Context context;
6862 context.type = eContextRegisterLoad;
6863 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6864 uint64_t data = MemURead (context, address, 2, 0, &success);
6865 if (!success)
6866 return false;
6867
6868 // if wback then R[n] = offset_addr;
6869 if (wback)
6870 {
6871 context.type = eContextAdjustBaseRegister;
6872 context.SetAddress (offset_addr);
6873 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6874 return false;
6875 }
6876
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006877 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006878 if (UnalignedSupport() || BitIsClear (address, 0))
6879 {
6880 // R[t] = ZeroExtend(data, 32);
6881 context.type = eContextRegisterLoad;
6882 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6883 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6884 return false;
6885 }
6886 else // Can only apply before ARMv7
6887 {
6888 // R[t] = bits(32) UNKNOWN;
6889 WriteBits32Unknown (t);
6890 }
6891 }
6892 return true;
6893}
6894
Caroline Ticea5e28af2011-03-01 21:53:03 +00006895// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6896// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6897// or pre-indexed addressing.
6898bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006899EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006900{
6901#if 0
6902 if ConditionPassed() then
6903 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6904 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6905 address = if index then offset_addr else R[n];
6906 R[t] = SignExtend(MemU[address,1], 32);
6907 if wback then R[n] = offset_addr;
6908#endif
6909
6910 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006911
Greg Clayton7bc39082011-03-24 23:53:38 +00006912 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006913 {
6914 uint32_t t;
6915 uint32_t n;
6916 uint32_t imm32;
6917 bool index;
6918 bool add;
6919 bool wback;
6920
6921 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6922 switch (encoding)
6923 {
6924 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006925 // if Rt == '1111' then SEE PLI;
6926 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006927 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6928 t = Bits32 (opcode, 15, 12);
6929 n = Bits32 (opcode, 19, 16);
6930 imm32 = Bits32 (opcode, 11, 0);
6931
6932 // index = TRUE; add = TRUE; wback = FALSE;
6933 index = true;
6934 add = true;
6935 wback = false;
6936
6937 // if t == 13 then UNPREDICTABLE;
6938 if (t == 13)
6939 return false;
6940
6941 break;
6942
6943 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006944 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6945 // if Rn == '1111' then SEE LDRSB (literal);
6946 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6947 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006948 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6949 return false;
6950
6951 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6952 t = Bits32 (opcode, 15, 12);
6953 n = Bits32 (opcode, 19, 16);
6954 imm32 = Bits32 (opcode, 7, 0);
6955
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006956 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006957 index = BitIsSet (opcode, 10);
6958 add = BitIsSet (opcode, 9);
6959 wback = BitIsSet (opcode, 8);
6960
6961 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006962 if (((t == 13) || ((t == 15)
6963 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6964 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006965 return false;
6966
6967 break;
6968
6969 case eEncodingA1:
6970 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006971 // if Rn == '1111' then SEE LDRSB (literal);
6972 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006973 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6974 t = Bits32 (opcode, 15, 12);
6975 n = Bits32 (opcode, 19, 16);
6976
6977 uint32_t imm4H = Bits32 (opcode, 11, 8);
6978 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006979 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006980
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006981 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006982 index = BitIsSet (opcode, 24);
6983 add = BitIsSet (opcode, 23);
6984 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6985
6986 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6987 if ((t == 15) || (wback && (n == t)))
6988 return false;
6989
6990 break;
6991 }
6992
6993 default:
6994 return false;
6995 }
6996
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006997 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006998 if (!success)
6999 return false;
7000
7001 addr_t offset_addr;
7002 addr_t address;
7003
7004 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7005 if (add)
7006 offset_addr = Rn + imm32;
7007 else
7008 offset_addr = Rn - imm32;
7009
7010 // address = if index then offset_addr else R[n];
7011 if (index)
7012 address = offset_addr;
7013 else
7014 address = Rn;
7015
7016 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007017 RegisterInfo base_reg;
7018 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticea5e28af2011-03-01 21:53:03 +00007019
7020 EmulateInstruction::Context context;
7021 context.type = eContextRegisterLoad;
7022 context.SetRegisterPlusOffset (base_reg, address - Rn);
7023
7024 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7025 if (!success)
7026 return false;
7027
7028 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7029 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7030 return false;
7031
7032 // if wback then R[n] = offset_addr;
7033 if (wback)
7034 {
7035 context.type = eContextAdjustBaseRegister;
7036 context.SetAddress (offset_addr);
7037 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7038 return false;
7039 }
7040 }
7041
7042 return true;
7043}
Caroline Tice0e6bc952011-03-01 18:00:42 +00007044
Caroline Tice5f593912011-03-01 22:25:17 +00007045// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
7046// sign-extends it to form a 32-bit word, and writes tit to a register.
7047bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007048EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00007049{
7050#if 0
7051 if ConditionPassed() then
7052 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7053 base = Align(PC,4);
7054 address = if add then (base + imm32) else (base - imm32);
7055 R[t] = SignExtend(MemU[address,1], 32);
7056#endif
7057
7058 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00007059
Greg Clayton7bc39082011-03-24 23:53:38 +00007060 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00007061 {
7062 uint32_t t;
7063 uint32_t imm32;
7064 bool add;
7065
7066 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7067 switch (encoding)
7068 {
7069 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007070 // if Rt == '1111' then SEE PLI;
7071 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007072 t = Bits32 (opcode, 15, 12);
7073 imm32 = Bits32 (opcode, 11, 0);
7074 add = BitIsSet (opcode, 23);
7075
7076 // if t == 13 then UNPREDICTABLE;
7077 if (t == 13)
7078 return false;
7079
7080 break;
7081
7082 case eEncodingA1:
7083 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007084 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007085 t = Bits32 (opcode, 15, 12);
7086 uint32_t imm4H = Bits32 (opcode, 11, 8);
7087 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007088 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00007089 add = BitIsSet (opcode, 23);
7090
7091 // if t == 15 then UNPREDICTABLE;
7092 if (t == 15)
7093 return false;
7094
7095 break;
7096 }
7097
7098 default:
7099 return false;
7100 }
7101
7102 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007103 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007104 if (!success)
7105 return false;
7106 uint64_t base = AlignPC (pc_value);
7107
7108 // address = if add then (base + imm32) else (base - imm32);
7109 addr_t address;
7110 if (add)
7111 address = base + imm32;
7112 else
7113 address = base - imm32;
7114
7115 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007116 RegisterInfo base_reg;
7117 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice5f593912011-03-01 22:25:17 +00007118
7119 EmulateInstruction::Context context;
7120 context.type = eContextRegisterLoad;
7121 context.SetRegisterPlusOffset (base_reg, address - base);
7122
7123 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7124 if (!success)
7125 return false;
7126
7127 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7128 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7129 return false;
7130 }
7131 return true;
7132}
7133
Caroline Tice672f3112011-03-01 23:55:59 +00007134// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7135// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7136// shifted left by 0, 1, 2, or 3 bits.
7137bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007138EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007139{
7140#if 0
7141 if ConditionPassed() then
7142 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7143 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7144 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7145 address = if index then offset_addr else R[n];
7146 R[t] = SignExtend(MemU[address,1], 32);
7147 if wback then R[n] = offset_addr;
7148#endif
7149
7150 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007151
Greg Clayton7bc39082011-03-24 23:53:38 +00007152 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007153 {
7154 uint32_t t;
7155 uint32_t n;
7156 uint32_t m;
7157 bool index;
7158 bool add;
7159 bool wback;
7160 ARM_ShifterType shift_t;
7161 uint32_t shift_n;
7162
7163 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7164 switch (encoding)
7165 {
7166 case eEncodingT1:
7167 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7168 t = Bits32 (opcode, 2, 0);
7169 n = Bits32 (opcode, 5, 3);
7170 m = Bits32 (opcode, 8, 6);
7171
7172 // index = TRUE; add = TRUE; wback = FALSE;
7173 index = true;
7174 add = true;
7175 wback = false;
7176
7177 // (shift_t, shift_n) = (SRType_LSL, 0);
7178 shift_t = SRType_LSL;
7179 shift_n = 0;
7180
7181 break;
7182
7183 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007184 // if Rt == '1111' then SEE PLI;
7185 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007186 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7187 t = Bits32 (opcode, 15, 12);
7188 n = Bits32 (opcode, 19, 16);
7189 m = Bits32 (opcode, 3, 0);
7190
7191 // index = TRUE; add = TRUE; wback = FALSE;
7192 index = true;
7193 add = true;
7194 wback = false;
7195
7196 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7197 shift_t = SRType_LSL;
7198 shift_n = Bits32 (opcode, 5, 4);
7199
7200 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7201 if ((t == 13) || BadReg (m))
7202 return false;
7203 break;
7204
7205 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007206 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007207 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7208 t = Bits32 (opcode, 15, 12);
7209 n = Bits32 (opcode, 19, 16);
7210 m = Bits32 (opcode, 3, 0);
7211
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007212 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007213 index = BitIsSet (opcode, 24);
7214 add = BitIsSet (opcode, 23);
7215 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7216
7217 // (shift_t, shift_n) = (SRType_LSL, 0);
7218 shift_t = SRType_LSL;
7219 shift_n = 0;
7220
7221 // if t == 15 || m == 15 then UNPREDICTABLE;
7222 if ((t == 15) || (m == 15))
7223 return false;
7224
7225 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7226 if (wback && ((n == 15) || (n == t)))
7227 return false;
7228 break;
7229
7230 default:
7231 return false;
7232 }
7233
7234 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7235 if (!success)
7236 return false;
7237
7238 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00007239 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7240 if (!success)
7241 return false;
Caroline Tice672f3112011-03-01 23:55:59 +00007242
7243 addr_t offset_addr;
7244 addr_t address;
7245
7246 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7247 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7248 if (!success)
7249 return false;
7250
7251 if (add)
7252 offset_addr = Rn + offset;
7253 else
7254 offset_addr = Rn - offset;
7255
7256 // address = if index then offset_addr else R[n];
7257 if (index)
7258 address = offset_addr;
7259 else
7260 address = Rn;
7261
7262 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007263 RegisterInfo base_reg;
7264 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7265 RegisterInfo offset_reg;
7266 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice672f3112011-03-01 23:55:59 +00007267
7268 EmulateInstruction::Context context;
7269 context.type = eContextRegisterLoad;
7270 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7271
7272 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7273 if (!success)
7274 return false;
7275
7276 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7277 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7278 return false;
7279
7280 // if wback then R[n] = offset_addr;
7281 if (wback)
7282 {
7283 context.type = eContextAdjustBaseRegister;
7284 context.SetAddress (offset_addr);
7285 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7286 return false;
7287 }
7288 }
7289 return true;
7290}
7291
Caroline Tice78fb5632011-03-02 00:39:42 +00007292// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7293// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7294// pre-indexed addressing.
7295bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007296EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007297{
7298#if 0
7299 if ConditionPassed() then
7300 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7301 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7302 address = if index then offset_addr else R[n];
7303 data = MemU[address,2];
7304 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007305 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007306 R[t] = SignExtend(data, 32);
7307 else // Can only apply before ARMv7
7308 R[t] = bits(32) UNKNOWN;
7309#endif
7310
7311 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007312
Greg Clayton7bc39082011-03-24 23:53:38 +00007313 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007314 {
7315 uint32_t t;
7316 uint32_t n;
7317 uint32_t imm32;
7318 bool index;
7319 bool add;
7320 bool wback;
7321
7322 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7323 switch (encoding)
7324 {
7325 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007326 // if Rn == '1111' then SEE LDRSH (literal);
7327 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007328 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7329 t = Bits32 (opcode, 15, 12);
7330 n = Bits32 (opcode, 19, 16);
7331 imm32 = Bits32 (opcode, 11, 0);
7332
7333 // index = TRUE; add = TRUE; wback = FALSE;
7334 index = true;
7335 add = true;
7336 wback = false;
7337
7338 // if t == 13 then UNPREDICTABLE;
7339 if (t == 13)
7340 return false;
7341
7342 break;
7343
7344 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007345 // if Rn == '1111' then SEE LDRSH (literal);
7346 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7347 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7348 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007349 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7350 return false;
7351
7352 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7353 t = Bits32 (opcode, 15, 12);
7354 n = Bits32 (opcode, 19, 16);
7355 imm32 = Bits32 (opcode, 7, 0);
7356
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007357 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007358 index = BitIsSet (opcode, 10);
7359 add = BitIsSet (opcode, 9);
7360 wback = BitIsSet (opcode, 8);
7361
7362 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7363 if (BadReg (t) || (wback && (n == t)))
7364 return false;
7365
7366 break;
7367
7368 case eEncodingA1:
7369 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007370 // if Rn == '1111' then SEE LDRSH (literal);
7371 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007372 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7373 t = Bits32 (opcode, 15, 12);
7374 n = Bits32 (opcode, 19, 16);
7375 uint32_t imm4H = Bits32 (opcode, 11,8);
7376 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007377 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007378
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007379 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007380 index = BitIsSet (opcode, 24);
7381 add = BitIsSet (opcode, 23);
7382 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7383
7384 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7385 if ((t == 15) || (wback && (n == t)))
7386 return false;
7387
7388 break;
7389 }
7390
7391 default:
7392 return false;
7393 }
7394
7395 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7396 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7397 if (!success)
7398 return false;
7399
7400 addr_t offset_addr;
7401 if (add)
7402 offset_addr = Rn + imm32;
7403 else
7404 offset_addr = Rn - imm32;
7405
7406 // address = if index then offset_addr else R[n];
7407 addr_t address;
7408 if (index)
7409 address = offset_addr;
7410 else
7411 address = Rn;
7412
7413 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007414 RegisterInfo base_reg;
7415 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice78fb5632011-03-02 00:39:42 +00007416
7417 EmulateInstruction::Context context;
7418 context.type = eContextRegisterLoad;
7419 context.SetRegisterPlusOffset (base_reg, address - Rn);
7420
7421 uint64_t data = MemURead (context, address, 2, 0, &success);
7422 if (!success)
7423 return false;
7424
7425 // if wback then R[n] = offset_addr;
7426 if (wback)
7427 {
7428 context.type = eContextAdjustBaseRegister;
7429 context.SetAddress (offset_addr);
7430 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7431 return false;
7432 }
7433
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007434 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007435 if (UnalignedSupport() || BitIsClear (address, 0))
7436 {
7437 // R[t] = SignExtend(data, 32);
7438 int64_t signed_data = llvm::SignExtend64<16>(data);
7439 context.type = eContextRegisterLoad;
7440 context.SetRegisterPlusOffset (base_reg, address - Rn);
7441 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7442 return false;
7443 }
7444 else // Can only apply before ARMv7
7445 {
7446 // R[t] = bits(32) UNKNOWN;
7447 WriteBits32Unknown (t);
7448 }
7449 }
7450 return true;
7451}
7452
Caroline Ticed2fac092011-03-02 19:45:34 +00007453// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7454// sign-extends it to from a 32-bit word, and writes it to a register.
7455bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007456EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007457{
7458#if 0
7459 if ConditionPassed() then
7460 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7461 base = Align(PC,4);
7462 address = if add then (base + imm32) else (base - imm32);
7463 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007464 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007465 R[t] = SignExtend(data, 32);
7466 else // Can only apply before ARMv7
7467 R[t] = bits(32) UNKNOWN;
7468#endif
7469
7470 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007471
Greg Clayton7bc39082011-03-24 23:53:38 +00007472 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007473 {
7474 uint32_t t;
7475 uint32_t imm32;
7476 bool add;
7477
7478 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7479 switch (encoding)
7480 {
7481 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007482 // if Rt == '1111' then SEE "Unallocated memory hints";
7483 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007484 t = Bits32 (opcode, 15, 12);
7485 imm32 = Bits32 (opcode, 11, 0);
7486 add = BitIsSet (opcode, 23);
7487
7488 // if t == 13 then UNPREDICTABLE;
7489 if (t == 13)
7490 return false;
7491
7492 break;
7493
7494 case eEncodingA1:
7495 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007496 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007497 t = Bits32 (opcode, 15, 12);
7498 uint32_t imm4H = Bits32 (opcode, 11, 8);
7499 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007500 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007501 add = BitIsSet (opcode, 23);
7502
7503 // if t == 15 then UNPREDICTABLE;
7504 if (t == 15)
7505 return false;
7506
7507 break;
7508 }
7509 default:
7510 return false;
7511 }
7512
7513 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007514 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007515 if (!success)
7516 return false;
7517
7518 uint64_t base = AlignPC (pc_value);
7519
7520 addr_t address;
7521 // address = if add then (base + imm32) else (base - imm32);
7522 if (add)
7523 address = base + imm32;
7524 else
7525 address = base - imm32;
7526
7527 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007528 RegisterInfo base_reg;
7529 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Ticed2fac092011-03-02 19:45:34 +00007530
7531 EmulateInstruction::Context context;
7532 context.type = eContextRegisterLoad;
7533 context.SetRegisterPlusOffset (base_reg, imm32);
7534
7535 uint64_t data = MemURead (context, address, 2, 0, &success);
7536 if (!success)
7537 return false;
7538
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007539 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007540 if (UnalignedSupport() || BitIsClear (address, 0))
7541 {
7542 // R[t] = SignExtend(data, 32);
7543 int64_t signed_data = llvm::SignExtend64<16>(data);
7544 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7545 return false;
7546 }
7547 else // Can only apply before ARMv7
7548 {
7549 // R[t] = bits(32) UNKNOWN;
7550 WriteBits32Unknown (t);
7551 }
7552 }
7553 return true;
7554}
7555
Caroline Tice291a3e92011-03-02 21:13:44 +00007556// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7557// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7558// shifted left by 0, 1, 2, or 3 bits.
7559bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007560EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007561{
7562#if 0
7563 if ConditionPassed() then
7564 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7565 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7566 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7567 address = if index then offset_addr else R[n];
7568 data = MemU[address,2];
7569 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007570 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007571 R[t] = SignExtend(data, 32);
7572 else // Can only apply before ARMv7
7573 R[t] = bits(32) UNKNOWN;
7574#endif
7575
7576 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007577
Greg Clayton7bc39082011-03-24 23:53:38 +00007578 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007579 {
7580 uint32_t t;
7581 uint32_t n;
7582 uint32_t m;
7583 bool index;
7584 bool add;
7585 bool wback;
7586 ARM_ShifterType shift_t;
7587 uint32_t shift_n;
7588
7589 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7590 switch (encoding)
7591 {
7592 case eEncodingT1:
7593 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7594 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7595 t = Bits32 (opcode, 2, 0);
7596 n = Bits32 (opcode, 5, 3);
7597 m = Bits32 (opcode, 8, 6);
7598
7599 // index = TRUE; add = TRUE; wback = FALSE;
7600 index = true;
7601 add = true;
7602 wback = false;
7603
7604 // (shift_t, shift_n) = (SRType_LSL, 0);
7605 shift_t = SRType_LSL;
7606 shift_n = 0;
7607
7608 break;
7609
7610 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007611 // if Rn == '1111' then SEE LDRSH (literal);
7612 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007613 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7614 t = Bits32 (opcode, 15, 12);
7615 n = Bits32 (opcode, 19, 16);
7616 m = Bits32 (opcode, 3, 0);
7617
7618 // index = TRUE; add = TRUE; wback = FALSE;
7619 index = true;
7620 add = true;
7621 wback = false;
7622
7623 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7624 shift_t = SRType_LSL;
7625 shift_n = Bits32 (opcode, 5, 4);
7626
7627 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7628 if ((t == 13) || BadReg (m))
7629 return false;
7630
7631 break;
7632
7633 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007634 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007635 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7636 t = Bits32 (opcode, 15, 12);
7637 n = Bits32 (opcode, 19, 16);
7638 m = Bits32 (opcode, 3, 0);
7639
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007640 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007641 index = BitIsSet (opcode, 24);
7642 add = BitIsSet (opcode, 23);
7643 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7644
7645 // (shift_t, shift_n) = (SRType_LSL, 0);
7646 shift_t = SRType_LSL;
7647 shift_n = 0;
7648
7649 // if t == 15 || m == 15 then UNPREDICTABLE;
7650 if ((t == 15) || (m == 15))
7651 return false;
7652
7653 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7654 if (wback && ((n == 15) || (n == t)))
7655 return false;
7656
7657 break;
7658
7659 default:
Johnny Chen6ac9e542011-08-16 01:16:02 +00007660 return false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007661 }
7662
7663 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7664 if (!success)
7665 return false;
7666
7667 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7668 if (!success)
7669 return false;
7670
7671 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00007672 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7673 if (!success)
7674 return false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007675
7676 addr_t offset_addr;
7677 addr_t address;
7678
7679 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7680 if (add)
7681 offset_addr = Rn + offset;
7682 else
7683 offset_addr = Rn - offset;
7684
7685 // address = if index then offset_addr else R[n];
7686 if (index)
7687 address = offset_addr;
7688 else
7689 address = Rn;
7690
7691 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007692 RegisterInfo base_reg;
7693 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007694
Greg Claytonc07d4512011-04-26 23:48:45 +00007695 RegisterInfo offset_reg;
7696 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007697
7698 EmulateInstruction::Context context;
7699 context.type = eContextRegisterLoad;
7700 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7701
7702 uint64_t data = MemURead (context, address, 2, 0, &success);
7703 if (!success)
7704 return false;
7705
7706 // if wback then R[n] = offset_addr;
7707 if (wback)
7708 {
7709 context.type = eContextAdjustBaseRegister;
7710 context.SetAddress (offset_addr);
7711 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7712 return false;
7713 }
7714
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007715 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007716 if (UnalignedSupport() || BitIsClear (address, 0))
7717 {
7718 // R[t] = SignExtend(data, 32);
7719 context.type = eContextRegisterLoad;
7720 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7721
7722 int64_t signed_data = llvm::SignExtend64<16>(data);
7723 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7724 return false;
7725 }
7726 else // Can only apply before ARMv7
7727 {
7728 // R[t] = bits(32) UNKNOWN;
7729 WriteBits32Unknown (t);
7730 }
7731 }
7732 return true;
7733}
Caroline Tice6bf65162011-03-03 17:42:58 +00007734
7735// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7736// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7737bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007738EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007739{
7740#if 0
7741 if ConditionPassed() then
7742 EncodingSpecificOperations();
7743 rotated = ROR(R[m], rotation);
7744 R[d] = SignExtend(rotated<7:0>, 32);
7745#endif
7746
7747 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007748
Greg Clayton7bc39082011-03-24 23:53:38 +00007749 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007750 {
7751 uint32_t d;
7752 uint32_t m;
7753 uint32_t rotation;
7754
7755 // EncodingSpecificOperations();
7756 switch (encoding)
7757 {
7758 case eEncodingT1:
7759 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7760 d = Bits32 (opcode, 2, 0);
7761 m = Bits32 (opcode, 5, 3);
7762 rotation = 0;
7763
7764 break;
7765
7766 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007767 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007768 d = Bits32 (opcode, 11, 8);
7769 m = Bits32 (opcode, 3, 0);
7770 rotation = Bits32 (opcode, 5, 4) << 3;
7771
7772 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7773 if (BadReg (d) || BadReg (m))
7774 return false;
7775
7776 break;
7777
7778 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007779 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007780 d = Bits32 (opcode, 15, 12);
7781 m = Bits32 (opcode, 3, 0);
7782 rotation = Bits32 (opcode, 11, 10) << 3;
7783
7784 // if d == 15 || m == 15 then UNPREDICTABLE;
7785 if ((d == 15) || (m == 15))
7786 return false;
7787
7788 break;
7789
7790 default:
7791 return false;
7792 }
7793
Caroline Tice868198b2011-03-03 18:04:49 +00007794 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7795 if (!success)
7796 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007797
7798 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007799 uint64_t rotated = ROR (Rm, rotation, &success);
7800 if (!success)
7801 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007802
7803 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007804 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007805
Greg Claytonc07d4512011-04-26 23:48:45 +00007806 RegisterInfo source_reg;
7807 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice6bf65162011-03-03 17:42:58 +00007808
7809 EmulateInstruction::Context context;
7810 context.type = eContextRegisterLoad;
7811 context.SetRegister (source_reg);
7812
Caroline Tice8ce96d92011-03-03 18:27:17 +00007813 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007814 return false;
7815 }
7816 return true;
7817}
Caroline Tice291a3e92011-03-02 21:13:44 +00007818
Caroline Tice868198b2011-03-03 18:04:49 +00007819// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7820// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7821bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007822EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007823{
7824#if 0
7825 if ConditionPassed() then
7826 EncodingSpecificOperations();
7827 rotated = ROR(R[m], rotation);
7828 R[d] = SignExtend(rotated<15:0>, 32);
7829#endif
7830
7831 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007832
Greg Clayton7bc39082011-03-24 23:53:38 +00007833 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007834 {
7835 uint32_t d;
7836 uint32_t m;
7837 uint32_t rotation;
7838
7839 // EncodingSpecificOperations();
7840 switch (encoding)
7841 {
7842 case eEncodingT1:
7843 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7844 d = Bits32 (opcode, 2, 0);
7845 m = Bits32 (opcode, 5, 3);
7846 rotation = 0;
7847
7848 break;
7849
7850 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007851 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007852 d = Bits32 (opcode, 11, 8);
7853 m = Bits32 (opcode, 3, 0);
7854 rotation = Bits32 (opcode, 5, 4) << 3;
7855
7856 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7857 if (BadReg (d) || BadReg (m))
7858 return false;
7859
7860 break;
7861
7862 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007863 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007864 d = Bits32 (opcode, 15, 12);
7865 m = Bits32 (opcode, 3, 0);
7866 rotation = Bits32 (opcode, 11, 10) << 3;
7867
7868 // if d == 15 || m == 15 then UNPREDICTABLE;
7869 if ((d == 15) || (m == 15))
7870 return false;
7871
7872 break;
7873
7874 default:
7875 return false;
7876 }
7877
7878 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7879 if (!success)
7880 return false;
7881
7882 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007883 uint64_t rotated = ROR (Rm, rotation, &success);
7884 if (!success)
7885 return false;
Caroline Tice868198b2011-03-03 18:04:49 +00007886
7887 // R[d] = SignExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007888 RegisterInfo source_reg;
7889 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice868198b2011-03-03 18:04:49 +00007890
7891 EmulateInstruction::Context context;
7892 context.type = eContextRegisterLoad;
7893 context.SetRegister (source_reg);
7894
Caroline Tice8ce96d92011-03-03 18:27:17 +00007895 int64_t data = llvm::SignExtend64<16> (rotated);
7896 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007897 return false;
7898 }
7899
7900 return true;
7901}
7902
Caroline Tice8ce96d92011-03-03 18:27:17 +00007903// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7904// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7905bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007906EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007907{
7908#if 0
7909 if ConditionPassed() then
7910 EncodingSpecificOperations();
7911 rotated = ROR(R[m], rotation);
7912 R[d] = ZeroExtend(rotated<7:0>, 32);
7913#endif
7914
7915 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007916
Greg Clayton7bc39082011-03-24 23:53:38 +00007917 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007918 {
7919 uint32_t d;
7920 uint32_t m;
7921 uint32_t rotation;
7922
7923 // EncodingSpecificOperations();
7924 switch (encoding)
7925 {
7926 case eEncodingT1:
7927 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7928 d = Bits32 (opcode, 2, 0);
7929 m = Bits32 (opcode, 5, 3);
7930 rotation = 0;
7931
7932 break;
7933
7934 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007935 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007936 d = Bits32 (opcode, 11, 8);
7937 m = Bits32 (opcode, 3, 0);
7938 rotation = Bits32 (opcode, 5, 4) << 3;
7939
7940 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7941 if (BadReg (d) || BadReg (m))
7942 return false;
7943
7944 break;
7945
7946 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007947 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007948 d = Bits32 (opcode, 15, 12);
7949 m = Bits32 (opcode, 3, 0);
7950 rotation = Bits32 (opcode, 11, 10) << 3;
7951
7952 // if d == 15 || m == 15 then UNPREDICTABLE;
7953 if ((d == 15) || (m == 15))
7954 return false;
7955
7956 break;
7957
7958 default:
7959 return false;
7960 }
7961
7962 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7963 if (!success)
7964 return false;
7965
7966 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007967 uint64_t rotated = ROR (Rm, rotation, &success);
7968 if (!success)
7969 return false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007970
7971 // R[d] = ZeroExtend(rotated<7:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007972 RegisterInfo source_reg;
7973 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007974
7975 EmulateInstruction::Context context;
7976 context.type = eContextRegisterLoad;
7977 context.SetRegister (source_reg);
7978
7979 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7980 return false;
7981 }
7982 return true;
7983}
7984
Caroline Tice11555f22011-03-03 18:48:58 +00007985// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7986// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7987bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007988EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007989{
7990#if 0
7991 if ConditionPassed() then
7992 EncodingSpecificOperations();
7993 rotated = ROR(R[m], rotation);
7994 R[d] = ZeroExtend(rotated<15:0>, 32);
7995#endif
7996
7997 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007998
Greg Clayton7bc39082011-03-24 23:53:38 +00007999 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00008000 {
8001 uint32_t d;
8002 uint32_t m;
8003 uint32_t rotation;
8004
8005 switch (encoding)
8006 {
8007 case eEncodingT1:
8008 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8009 d = Bits32 (opcode, 2, 0);
8010 m = Bits32 (opcode, 5, 3);
8011 rotation = 0;
8012
8013 break;
8014
8015 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008016 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00008017 d = Bits32 (opcode, 11, 8);
8018 m = Bits32 (opcode, 3, 0);
8019 rotation = Bits32 (opcode, 5, 4) << 3;
8020
8021 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8022 if (BadReg (d) || BadReg (m))
8023 return false;
8024
8025 break;
8026
8027 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008028 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00008029 d = Bits32 (opcode, 15, 12);
8030 m = Bits32 (opcode, 3, 0);
8031 rotation = Bits32 (opcode, 11, 10) << 3;
8032
8033 // if d == 15 || m == 15 then UNPREDICTABLE;
8034 if ((d == 15) || (m == 15))
8035 return false;
8036
8037 break;
8038
8039 default:
8040 return false;
8041 }
8042
8043 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8044 if (!success)
8045 return false;
8046
8047 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00008048 uint64_t rotated = ROR (Rm, rotation, &success);
8049 if (!success)
8050 return false;
Caroline Tice11555f22011-03-03 18:48:58 +00008051
8052 // R[d] = ZeroExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00008053 RegisterInfo source_reg;
8054 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice11555f22011-03-03 18:48:58 +00008055
8056 EmulateInstruction::Context context;
8057 context.type = eContextRegisterLoad;
8058 context.SetRegister (source_reg);
8059
8060 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
8061 return false;
8062 }
8063 return true;
8064}
Caroline Ticeb27771d2011-03-03 22:37:46 +00008065
8066// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
8067// word respectively.
8068bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008069EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00008070{
8071#if 0
8072 if ConditionPassed() then
8073 EncodingSpecificOperations();
8074 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8075 UNPREDICTABLE;
8076 else
8077 address = if increment then R[n] else R[n]-8;
8078 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008079 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008080 BranchWritePC(MemA[address,4]);
8081 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8082#endif
8083
8084 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008085
Greg Clayton7bc39082011-03-24 23:53:38 +00008086 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00008087 {
8088 uint32_t n;
8089 bool wback;
8090 bool increment;
8091 bool wordhigher;
8092
8093 // EncodingSpecificOperations();
8094 switch (encoding)
8095 {
8096 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008097 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008098 n = Bits32 (opcode, 19, 16);
8099 wback = BitIsSet (opcode, 21);
8100 increment = false;
8101 wordhigher = false;
8102
8103 // if n == 15 then UNPREDICTABLE;
8104 if (n == 15)
8105 return false;
8106
8107 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8108 if (InITBlock() && !LastInITBlock())
8109 return false;
8110
8111 break;
8112
8113 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008114 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008115 n = Bits32 (opcode, 19, 16);
8116 wback = BitIsSet (opcode, 21);
8117 increment = true;
8118 wordhigher = false;
8119
8120 // if n == 15 then UNPREDICTABLE;
8121 if (n == 15)
8122 return false;
8123
8124 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8125 if (InITBlock() && !LastInITBlock())
8126 return false;
8127
8128 break;
8129
8130 case eEncodingA1:
8131 // n = UInt(Rn);
8132 n = Bits32 (opcode, 19, 16);
8133
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008134 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008135 wback = BitIsSet (opcode, 21);
8136 increment = BitIsSet (opcode, 23);
8137 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8138
8139 // if n == 15 then UNPREDICTABLE;
8140 if (n == 15)
8141 return false;
8142
8143 break;
8144
8145 default:
8146 return false;
8147 }
8148
8149 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8150 if (!CurrentModeIsPrivileged ())
8151 // UNPREDICTABLE;
8152 return false;
8153 else
8154 {
8155 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8156 if (!success)
8157 return false;
8158
8159 addr_t address;
8160 // address = if increment then R[n] else R[n]-8;
8161 if (increment)
8162 address = Rn;
8163 else
8164 address = Rn - 8;
8165
8166 // if wordhigher then address = address+4;
8167 if (wordhigher)
8168 address = address + 4;
8169
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008170 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Greg Claytonc07d4512011-04-26 23:48:45 +00008171 RegisterInfo base_reg;
8172 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008173
8174 EmulateInstruction::Context context;
8175 context.type = eContextReturnFromException;
8176 context.SetRegisterPlusOffset (base_reg, address - Rn);
8177
8178 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8179 if (!success)
8180 return false;
8181
8182 CPSRWriteByInstr (data, 15, true);
8183
8184 // BranchWritePC(MemA[address,4]);
8185 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8186 if (!success)
8187 return false;
8188
8189 BranchWritePC (context, data2);
8190
8191 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8192 if (wback)
8193 {
8194 context.type = eContextAdjustBaseRegister;
8195 if (increment)
8196 {
8197 context.SetOffset (8);
8198 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8199 return false;
8200 }
8201 else
8202 {
8203 context.SetOffset (-8);
8204 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8205 return false;
8206 }
8207 } // if wback
8208 }
8209 } // if ConditionPassed()
8210 return true;
8211}
Caroline Tice11555f22011-03-03 18:48:58 +00008212
Johnny Chen2115b412011-02-21 23:42:44 +00008213// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8214// and writes the result to the destination register. It can optionally update the condition flags based on
8215// the result.
8216bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008217EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008218{
8219#if 0
8220 // ARM pseudo code...
8221 if ConditionPassed() then
8222 EncodingSpecificOperations();
8223 result = R[n] EOR imm32;
8224 if d == 15 then // Can only occur for ARM encoding
8225 ALUWritePC(result); // setflags is always FALSE here
8226 else
8227 R[d] = result;
8228 if setflags then
8229 APSR.N = result<31>;
8230 APSR.Z = IsZeroBit(result);
8231 APSR.C = carry;
8232 // APSR.V unchanged
8233#endif
8234
8235 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008236
Greg Clayton7bc39082011-03-24 23:53:38 +00008237 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008238 {
8239 uint32_t Rd, Rn;
8240 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8241 bool setflags;
8242 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8243 switch (encoding)
8244 {
8245 case eEncodingT1:
8246 Rd = Bits32(opcode, 11, 8);
8247 Rn = Bits32(opcode, 19, 16);
8248 setflags = BitIsSet(opcode, 20);
8249 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8250 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8251 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008252 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008253 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8254 return false;
8255 break;
8256 case eEncodingA1:
8257 Rd = Bits32(opcode, 15, 12);
8258 Rn = Bits32(opcode, 19, 16);
8259 setflags = BitIsSet(opcode, 20);
8260 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008261
Johnny Chen2115b412011-02-21 23:42:44 +00008262 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008263 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008264 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008265 break;
8266 default:
8267 return false;
8268 }
8269
8270 // Read the first operand.
8271 uint32_t val1 = ReadCoreReg(Rn, &success);
8272 if (!success)
8273 return false;
8274
8275 uint32_t result = val1 ^ imm32;
8276
8277 EmulateInstruction::Context context;
8278 context.type = EmulateInstruction::eContextImmediate;
8279 context.SetNoArgs ();
8280
8281 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8282 return false;
8283 }
8284 return true;
8285}
8286
8287// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8288// optionally-shifted register value, and writes the result to the destination register.
8289// It can optionally update the condition flags based on the result.
8290bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008291EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008292{
8293#if 0
8294 // ARM pseudo code...
8295 if ConditionPassed() then
8296 EncodingSpecificOperations();
8297 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8298 result = R[n] EOR shifted;
8299 if d == 15 then // Can only occur for ARM encoding
8300 ALUWritePC(result); // setflags is always FALSE here
8301 else
8302 R[d] = result;
8303 if setflags then
8304 APSR.N = result<31>;
8305 APSR.Z = IsZeroBit(result);
8306 APSR.C = carry;
8307 // APSR.V unchanged
8308#endif
8309
8310 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008311
Greg Clayton7bc39082011-03-24 23:53:38 +00008312 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008313 {
8314 uint32_t Rd, Rn, Rm;
8315 ARM_ShifterType shift_t;
8316 uint32_t shift_n; // the shift applied to the value read from Rm
8317 bool setflags;
8318 uint32_t carry;
8319 switch (encoding)
8320 {
8321 case eEncodingT1:
8322 Rd = Rn = Bits32(opcode, 2, 0);
8323 Rm = Bits32(opcode, 5, 3);
8324 setflags = !InITBlock();
8325 shift_t = SRType_LSL;
8326 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008327 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008328 case eEncodingT2:
8329 Rd = Bits32(opcode, 11, 8);
8330 Rn = Bits32(opcode, 19, 16);
8331 Rm = Bits32(opcode, 3, 0);
8332 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008333 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8334 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008335 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008336 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008337 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8338 return false;
8339 break;
8340 case eEncodingA1:
8341 Rd = Bits32(opcode, 15, 12);
8342 Rn = Bits32(opcode, 19, 16);
8343 Rm = Bits32(opcode, 3, 0);
8344 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008345 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008346
Johnny Chen2115b412011-02-21 23:42:44 +00008347 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008348 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008349 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008350 break;
8351 default:
8352 return false;
8353 }
8354
8355 // Read the first operand.
8356 uint32_t val1 = ReadCoreReg(Rn, &success);
8357 if (!success)
8358 return false;
8359
8360 // Read the second operand.
8361 uint32_t val2 = ReadCoreReg(Rm, &success);
8362 if (!success)
8363 return false;
8364
Johnny Chena4438a72011-06-02 22:50:51 +00008365 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8366 if (!success)
8367 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00008368 uint32_t result = val1 ^ shifted;
8369
8370 EmulateInstruction::Context context;
8371 context.type = EmulateInstruction::eContextImmediate;
8372 context.SetNoArgs ();
8373
8374 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8375 return false;
8376 }
8377 return true;
8378}
8379
Johnny Chen7c5234d2011-02-18 23:41:11 +00008380// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8381// writes the result to the destination register. It can optionally update the condition flags based
8382// on the result.
8383bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008384EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008385{
8386#if 0
8387 // ARM pseudo code...
8388 if ConditionPassed() then
8389 EncodingSpecificOperations();
8390 result = R[n] OR imm32;
8391 if d == 15 then // Can only occur for ARM encoding
8392 ALUWritePC(result); // setflags is always FALSE here
8393 else
8394 R[d] = result;
8395 if setflags then
8396 APSR.N = result<31>;
8397 APSR.Z = IsZeroBit(result);
8398 APSR.C = carry;
8399 // APSR.V unchanged
8400#endif
8401
8402 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008403
Greg Clayton7bc39082011-03-24 23:53:38 +00008404 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008405 {
8406 uint32_t Rd, Rn;
8407 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8408 bool setflags;
8409 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8410 switch (encoding)
8411 {
8412 case eEncodingT1:
8413 Rd = Bits32(opcode, 11, 8);
8414 Rn = Bits32(opcode, 19, 16);
8415 setflags = BitIsSet(opcode, 20);
8416 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008417 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008418 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008419 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008420 if (BadReg(Rd) || Rn == 13)
8421 return false;
8422 break;
8423 case eEncodingA1:
8424 Rd = Bits32(opcode, 15, 12);
8425 Rn = Bits32(opcode, 19, 16);
8426 setflags = BitIsSet(opcode, 20);
8427 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008428
Johnny Chen7c5234d2011-02-18 23:41:11 +00008429 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008430 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008431 break;
8432 default:
8433 return false;
8434 }
8435
8436 // Read the first operand.
8437 uint32_t val1 = ReadCoreReg(Rn, &success);
8438 if (!success)
8439 return false;
8440
8441 uint32_t result = val1 | imm32;
8442
8443 EmulateInstruction::Context context;
8444 context.type = EmulateInstruction::eContextImmediate;
8445 context.SetNoArgs ();
8446
8447 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8448 return false;
8449 }
8450 return true;
8451}
8452
8453// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8454// value, and writes the result to the destination register. It can optionally update the condition flags based
8455// on the result.
8456bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008457EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008458{
8459#if 0
8460 // ARM pseudo code...
8461 if ConditionPassed() then
8462 EncodingSpecificOperations();
8463 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8464 result = R[n] OR shifted;
8465 if d == 15 then // Can only occur for ARM encoding
8466 ALUWritePC(result); // setflags is always FALSE here
8467 else
8468 R[d] = result;
8469 if setflags then
8470 APSR.N = result<31>;
8471 APSR.Z = IsZeroBit(result);
8472 APSR.C = carry;
8473 // APSR.V unchanged
8474#endif
8475
8476 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008477
Greg Clayton7bc39082011-03-24 23:53:38 +00008478 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008479 {
8480 uint32_t Rd, Rn, Rm;
8481 ARM_ShifterType shift_t;
8482 uint32_t shift_n; // the shift applied to the value read from Rm
8483 bool setflags;
8484 uint32_t carry;
8485 switch (encoding)
8486 {
8487 case eEncodingT1:
8488 Rd = Rn = Bits32(opcode, 2, 0);
8489 Rm = Bits32(opcode, 5, 3);
8490 setflags = !InITBlock();
8491 shift_t = SRType_LSL;
8492 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008493 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008494 case eEncodingT2:
8495 Rd = Bits32(opcode, 11, 8);
8496 Rn = Bits32(opcode, 19, 16);
8497 Rm = Bits32(opcode, 3, 0);
8498 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008499 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8500 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008501 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008502 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008503 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8504 return false;
8505 break;
8506 case eEncodingA1:
8507 Rd = Bits32(opcode, 15, 12);
8508 Rn = Bits32(opcode, 19, 16);
8509 Rm = Bits32(opcode, 3, 0);
8510 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008511 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008512
Johnny Chen7c5234d2011-02-18 23:41:11 +00008513 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008514 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008515 break;
8516 default:
8517 return false;
8518 }
8519
8520 // Read the first operand.
8521 uint32_t val1 = ReadCoreReg(Rn, &success);
8522 if (!success)
8523 return false;
8524
8525 // Read the second operand.
8526 uint32_t val2 = ReadCoreReg(Rm, &success);
8527 if (!success)
8528 return false;
8529
Johnny Chena4438a72011-06-02 22:50:51 +00008530 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8531 if (!success)
8532 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00008533 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008534
8535 EmulateInstruction::Context context;
8536 context.type = EmulateInstruction::eContextImmediate;
8537 context.SetNoArgs ();
8538
8539 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8540 return false;
8541 }
8542 return true;
8543}
8544
Johnny Chened32e7c2011-02-22 23:42:58 +00008545// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8546// the destination register. It can optionally update the condition flags based on the result.
8547bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008548EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008549{
8550#if 0
8551 // ARM pseudo code...
8552 if ConditionPassed() then
8553 EncodingSpecificOperations();
8554 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8555 if d == 15 then // Can only occur for ARM encoding
8556 ALUWritePC(result); // setflags is always FALSE here
8557 else
8558 R[d] = result;
8559 if setflags then
8560 APSR.N = result<31>;
8561 APSR.Z = IsZeroBit(result);
8562 APSR.C = carry;
8563 APSR.V = overflow;
8564#endif
8565
8566 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008567
8568 uint32_t Rd; // the destination register
8569 uint32_t Rn; // the first operand
8570 bool setflags;
8571 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8572 switch (encoding) {
8573 case eEncodingT1:
8574 Rd = Bits32(opcode, 2, 0);
8575 Rn = Bits32(opcode, 5, 3);
8576 setflags = !InITBlock();
8577 imm32 = 0;
8578 break;
8579 case eEncodingT2:
8580 Rd = Bits32(opcode, 11, 8);
8581 Rn = Bits32(opcode, 19, 16);
8582 setflags = BitIsSet(opcode, 20);
8583 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8584 if (BadReg(Rd) || BadReg(Rn))
8585 return false;
8586 break;
8587 case eEncodingA1:
8588 Rd = Bits32(opcode, 15, 12);
8589 Rn = Bits32(opcode, 19, 16);
8590 setflags = BitIsSet(opcode, 20);
8591 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008592
Johnny Chened32e7c2011-02-22 23:42:58 +00008593 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008594 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008595 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008596 break;
8597 default:
8598 return false;
8599 }
8600 // Read the register value from the operand register Rn.
8601 uint32_t reg_val = ReadCoreReg(Rn, &success);
8602 if (!success)
8603 return false;
8604
8605 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8606
8607 EmulateInstruction::Context context;
8608 context.type = EmulateInstruction::eContextImmediate;
8609 context.SetNoArgs ();
8610
8611 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8612 return false;
8613
8614 return true;
8615}
8616
8617// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8618// result to the destination register. It can optionally update the condition flags based on the result.
8619bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008620EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008621{
8622#if 0
8623 // ARM pseudo code...
8624 if ConditionPassed() then
8625 EncodingSpecificOperations();
8626 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8627 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8628 if d == 15 then // Can only occur for ARM encoding
8629 ALUWritePC(result); // setflags is always FALSE here
8630 else
8631 R[d] = result;
8632 if setflags then
8633 APSR.N = result<31>;
8634 APSR.Z = IsZeroBit(result);
8635 APSR.C = carry;
8636 APSR.V = overflow;
8637#endif
8638
8639 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008640
8641 uint32_t Rd; // the destination register
8642 uint32_t Rn; // the first operand
8643 uint32_t Rm; // the second operand
8644 bool setflags;
8645 ARM_ShifterType shift_t;
8646 uint32_t shift_n; // the shift applied to the value read from Rm
8647 switch (encoding) {
8648 case eEncodingT1:
8649 Rd = Bits32(opcode, 11, 8);
8650 Rn = Bits32(opcode, 19, 16);
8651 Rm = Bits32(opcode, 3, 0);
8652 setflags = BitIsSet(opcode, 20);
8653 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8654 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8655 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8656 return false;
8657 break;
8658 case eEncodingA1:
8659 Rd = Bits32(opcode, 15, 12);
8660 Rn = Bits32(opcode, 19, 16);
8661 Rm = Bits32(opcode, 3, 0);
8662 setflags = BitIsSet(opcode, 20);
8663 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008664
Johnny Chened32e7c2011-02-22 23:42:58 +00008665 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008666 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008667 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008668 break;
8669 default:
8670 return false;
8671 }
8672 // Read the register value from register Rn.
8673 uint32_t val1 = ReadCoreReg(Rn, &success);
8674 if (!success)
8675 return false;
8676
8677 // Read the register value from register Rm.
8678 uint32_t val2 = ReadCoreReg(Rm, &success);
8679 if (!success)
8680 return false;
8681
Johnny Chena4438a72011-06-02 22:50:51 +00008682 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8683 if (!success)
8684 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008685 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8686
8687 EmulateInstruction::Context context;
8688 context.type = EmulateInstruction::eContextImmediate;
8689 context.SetNoArgs();
8690 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8691 return false;
8692
8693 return true;
8694}
8695
Johnny Chen90e607b2011-02-23 00:07:09 +00008696// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8697// an immediate value, and writes the result to the destination register. It can optionally update the condition
8698// flags based on the result.
8699bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008700EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008701{
8702#if 0
8703 // ARM pseudo code...
8704 if ConditionPassed() then
8705 EncodingSpecificOperations();
8706 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8707 if d == 15 then
8708 ALUWritePC(result); // setflags is always FALSE here
8709 else
8710 R[d] = result;
8711 if setflags then
8712 APSR.N = result<31>;
8713 APSR.Z = IsZeroBit(result);
8714 APSR.C = carry;
8715 APSR.V = overflow;
8716#endif
8717
8718 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008719
8720 uint32_t Rd; // the destination register
8721 uint32_t Rn; // the first operand
8722 bool setflags;
8723 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8724 switch (encoding) {
8725 case eEncodingA1:
8726 Rd = Bits32(opcode, 15, 12);
8727 Rn = Bits32(opcode, 19, 16);
8728 setflags = BitIsSet(opcode, 20);
8729 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008730
Johnny Chen90e607b2011-02-23 00:07:09 +00008731 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008732 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008733 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008734 break;
8735 default:
8736 return false;
8737 }
8738 // Read the register value from the operand register Rn.
8739 uint32_t reg_val = ReadCoreReg(Rn, &success);
8740 if (!success)
8741 return false;
8742
8743 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8744
8745 EmulateInstruction::Context context;
8746 context.type = EmulateInstruction::eContextImmediate;
8747 context.SetNoArgs ();
8748
8749 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8750 return false;
8751
8752 return true;
8753}
8754
8755// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8756// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8757// condition flags based on the result.
8758bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008759EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008760{
8761#if 0
8762 // ARM pseudo code...
8763 if ConditionPassed() then
8764 EncodingSpecificOperations();
8765 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8766 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8767 if d == 15 then
8768 ALUWritePC(result); // setflags is always FALSE here
8769 else
8770 R[d] = result;
8771 if setflags then
8772 APSR.N = result<31>;
8773 APSR.Z = IsZeroBit(result);
8774 APSR.C = carry;
8775 APSR.V = overflow;
8776#endif
8777
8778 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008779
8780 uint32_t Rd; // the destination register
8781 uint32_t Rn; // the first operand
8782 uint32_t Rm; // the second operand
8783 bool setflags;
8784 ARM_ShifterType shift_t;
8785 uint32_t shift_n; // the shift applied to the value read from Rm
8786 switch (encoding) {
8787 case eEncodingA1:
8788 Rd = Bits32(opcode, 15, 12);
8789 Rn = Bits32(opcode, 19, 16);
8790 Rm = Bits32(opcode, 3, 0);
8791 setflags = BitIsSet(opcode, 20);
8792 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008793
Johnny Chen90e607b2011-02-23 00:07:09 +00008794 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008795 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008796 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008797 break;
8798 default:
8799 return false;
8800 }
8801 // Read the register value from register Rn.
8802 uint32_t val1 = ReadCoreReg(Rn, &success);
8803 if (!success)
8804 return false;
8805
8806 // Read the register value from register Rm.
8807 uint32_t val2 = ReadCoreReg(Rm, &success);
8808 if (!success)
8809 return false;
8810
Johnny Chena4438a72011-06-02 22:50:51 +00008811 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8812 if (!success)
8813 return false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008814 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8815
8816 EmulateInstruction::Context context;
8817 context.type = EmulateInstruction::eContextImmediate;
8818 context.SetNoArgs();
8819 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8820 return false;
8821
8822 return true;
8823}
8824
Johnny Chen9b381772011-02-23 01:01:21 +00008825// Subtract with Carry (immediate) subtracts an immediate value and the value of
8826// NOT (Carry flag) from a register value, and writes the result to the destination register.
8827// It can optionally update the condition flags based on the result.
8828bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008829EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008830{
8831#if 0
8832 // ARM pseudo code...
8833 if ConditionPassed() then
8834 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008835 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008836 if d == 15 then // Can only occur for ARM encoding
8837 ALUWritePC(result); // setflags is always FALSE here
8838 else
8839 R[d] = result;
8840 if setflags then
8841 APSR.N = result<31>;
8842 APSR.Z = IsZeroBit(result);
8843 APSR.C = carry;
8844 APSR.V = overflow;
8845#endif
8846
8847 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008848
8849 uint32_t Rd; // the destination register
8850 uint32_t Rn; // the first operand
8851 bool setflags;
8852 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8853 switch (encoding) {
8854 case eEncodingT1:
8855 Rd = Bits32(opcode, 11, 8);
8856 Rn = Bits32(opcode, 19, 16);
8857 setflags = BitIsSet(opcode, 20);
8858 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8859 if (BadReg(Rd) || BadReg(Rn))
8860 return false;
8861 break;
8862 case eEncodingA1:
8863 Rd = Bits32(opcode, 15, 12);
8864 Rn = Bits32(opcode, 19, 16);
8865 setflags = BitIsSet(opcode, 20);
8866 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008867
Johnny Chen9b381772011-02-23 01:01:21 +00008868 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008869 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008870 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008871 break;
8872 default:
8873 return false;
8874 }
8875 // Read the register value from the operand register Rn.
8876 uint32_t reg_val = ReadCoreReg(Rn, &success);
8877 if (!success)
8878 return false;
8879
8880 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8881
8882 EmulateInstruction::Context context;
8883 context.type = EmulateInstruction::eContextImmediate;
8884 context.SetNoArgs ();
8885
8886 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8887 return false;
8888
8889 return true;
8890}
8891
8892// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8893// NOT (Carry flag) from a register value, and writes the result to the destination register.
8894// It can optionally update the condition flags based on the result.
8895bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008896EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008897{
8898#if 0
8899 // ARM pseudo code...
8900 if ConditionPassed() then
8901 EncodingSpecificOperations();
8902 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8903 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8904 if d == 15 then // Can only occur for ARM encoding
8905 ALUWritePC(result); // setflags is always FALSE here
8906 else
8907 R[d] = result;
8908 if setflags then
8909 APSR.N = result<31>;
8910 APSR.Z = IsZeroBit(result);
8911 APSR.C = carry;
8912 APSR.V = overflow;
8913#endif
8914
8915 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008916
8917 uint32_t Rd; // the destination register
8918 uint32_t Rn; // the first operand
8919 uint32_t Rm; // the second operand
8920 bool setflags;
8921 ARM_ShifterType shift_t;
8922 uint32_t shift_n; // the shift applied to the value read from Rm
8923 switch (encoding) {
8924 case eEncodingT1:
8925 Rd = Rn = Bits32(opcode, 2, 0);
8926 Rm = Bits32(opcode, 5, 3);
8927 setflags = !InITBlock();
8928 shift_t = SRType_LSL;
8929 shift_n = 0;
8930 break;
8931 case eEncodingT2:
8932 Rd = Bits32(opcode, 11, 8);
8933 Rn = Bits32(opcode, 19, 16);
8934 Rm = Bits32(opcode, 3, 0);
8935 setflags = BitIsSet(opcode, 20);
8936 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8937 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8938 return false;
8939 break;
8940 case eEncodingA1:
8941 Rd = Bits32(opcode, 15, 12);
8942 Rn = Bits32(opcode, 19, 16);
8943 Rm = Bits32(opcode, 3, 0);
8944 setflags = BitIsSet(opcode, 20);
8945 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008946
Johnny Chen9b381772011-02-23 01:01:21 +00008947 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008948 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008949 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008950 break;
8951 default:
8952 return false;
8953 }
8954 // Read the register value from register Rn.
8955 uint32_t val1 = ReadCoreReg(Rn, &success);
8956 if (!success)
8957 return false;
8958
8959 // Read the register value from register Rm.
8960 uint32_t val2 = ReadCoreReg(Rm, &success);
8961 if (!success)
8962 return false;
8963
Johnny Chena4438a72011-06-02 22:50:51 +00008964 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8965 if (!success)
8966 return false;
Johnny Chen9b381772011-02-23 01:01:21 +00008967 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8968
8969 EmulateInstruction::Context context;
8970 context.type = EmulateInstruction::eContextImmediate;
8971 context.SetNoArgs();
8972 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8973 return false;
8974
8975 return true;
8976}
8977
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008978// This instruction subtracts an immediate value from a register value, and writes the result
8979// to the destination register. It can optionally update the condition flags based on the result.
8980bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008981EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008982{
8983#if 0
8984 // ARM pseudo code...
8985 if ConditionPassed() then
8986 EncodingSpecificOperations();
8987 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8988 R[d] = result;
8989 if setflags then
8990 APSR.N = result<31>;
8991 APSR.Z = IsZeroBit(result);
8992 APSR.C = carry;
8993 APSR.V = overflow;
8994#endif
8995
8996 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008997
8998 uint32_t Rd; // the destination register
8999 uint32_t Rn; // the first operand
9000 bool setflags;
9001 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9002 switch (encoding) {
9003 case eEncodingT1:
9004 Rd = Bits32(opcode, 2, 0);
9005 Rn = Bits32(opcode, 5, 3);
9006 setflags = !InITBlock();
9007 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9008 break;
9009 case eEncodingT2:
9010 Rd = Rn = Bits32(opcode, 10, 8);
9011 setflags = !InITBlock();
9012 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9013 break;
9014 case eEncodingT3:
9015 Rd = Bits32(opcode, 11, 8);
9016 Rn = Bits32(opcode, 19, 16);
9017 setflags = BitIsSet(opcode, 20);
9018 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9019
9020 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9021 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00009022 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009023
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009024 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009025 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009026 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009027
9028 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9029 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9030 return false;
9031 break;
9032 case eEncodingT4:
9033 Rd = Bits32(opcode, 11, 8);
9034 Rn = Bits32(opcode, 19, 16);
9035 setflags = BitIsSet(opcode, 20);
9036 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9037
9038 // if Rn == '1111' then SEE ADR;
9039 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00009040 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009041
9042 // if Rn == '1101' then SEE SUB (SP minus immediate);
9043 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009044 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009045
9046 if (BadReg(Rd))
9047 return false;
9048 break;
9049 default:
9050 return false;
9051 }
9052 // Read the register value from the operand register Rn.
9053 uint32_t reg_val = ReadCoreReg(Rn, &success);
9054 if (!success)
9055 return false;
9056
9057 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9058
9059 EmulateInstruction::Context context;
9060 context.type = EmulateInstruction::eContextImmediate;
9061 context.SetNoArgs ();
9062
9063 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9064 return false;
9065
9066 return true;
9067}
9068
9069// This instruction subtracts an immediate value from a register value, and writes the result
9070// to the destination register. It can optionally update the condition flags based on the result.
9071bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009072EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009073{
9074#if 0
9075 // ARM pseudo code...
9076 if ConditionPassed() then
9077 EncodingSpecificOperations();
9078 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9079 if d == 15 then
9080 ALUWritePC(result); // setflags is always FALSE here
9081 else
9082 R[d] = result;
9083 if setflags then
9084 APSR.N = result<31>;
9085 APSR.Z = IsZeroBit(result);
9086 APSR.C = carry;
9087 APSR.V = overflow;
9088#endif
9089
9090 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009091
9092 uint32_t Rd; // the destination register
9093 uint32_t Rn; // the first operand
9094 bool setflags;
9095 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9096 switch (encoding) {
9097 case eEncodingA1:
9098 Rd = Bits32(opcode, 15, 12);
9099 Rn = Bits32(opcode, 19, 16);
9100 setflags = BitIsSet(opcode, 20);
9101 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9102
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009103 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009104 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00009105 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009106
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009107 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009108 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009109 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009110
9111 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009112 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00009113 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009114 break;
9115 default:
9116 return false;
9117 }
9118 // Read the register value from the operand register Rn.
9119 uint32_t reg_val = ReadCoreReg(Rn, &success);
9120 if (!success)
9121 return false;
9122
9123 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9124
9125 EmulateInstruction::Context context;
9126 context.type = EmulateInstruction::eContextImmediate;
9127 context.SetNoArgs ();
9128
9129 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9130 return false;
9131
9132 return true;
9133}
9134
Johnny Chen2115b412011-02-21 23:42:44 +00009135// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9136// immediate value. It updates the condition flags based on the result, and discards the result.
9137bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009138EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009139{
9140#if 0
9141 // ARM pseudo code...
9142 if ConditionPassed() then
9143 EncodingSpecificOperations();
9144 result = R[n] EOR imm32;
9145 APSR.N = result<31>;
9146 APSR.Z = IsZeroBit(result);
9147 APSR.C = carry;
9148 // APSR.V unchanged
9149#endif
9150
9151 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009152
Greg Clayton7bc39082011-03-24 23:53:38 +00009153 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009154 {
9155 uint32_t Rn;
9156 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9157 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9158 switch (encoding)
9159 {
9160 case eEncodingT1:
9161 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009162 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009163 if (BadReg(Rn))
9164 return false;
9165 break;
9166 case eEncodingA1:
9167 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009168 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009169 break;
9170 default:
9171 return false;
9172 }
9173
9174 // Read the first operand.
9175 uint32_t val1 = ReadCoreReg(Rn, &success);
9176 if (!success)
9177 return false;
9178
9179 uint32_t result = val1 ^ imm32;
9180
9181 EmulateInstruction::Context context;
9182 context.type = EmulateInstruction::eContextImmediate;
9183 context.SetNoArgs ();
9184
9185 if (!WriteFlags(context, result, carry))
9186 return false;
9187 }
9188 return true;
9189}
9190
9191// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9192// optionally-shifted register value. It updates the condition flags based on the result, and discards
9193// the result.
9194bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009195EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009196{
9197#if 0
9198 // ARM pseudo code...
9199 if ConditionPassed() then
9200 EncodingSpecificOperations();
9201 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9202 result = R[n] EOR shifted;
9203 APSR.N = result<31>;
9204 APSR.Z = IsZeroBit(result);
9205 APSR.C = carry;
9206 // APSR.V unchanged
9207#endif
9208
9209 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009210
Greg Clayton7bc39082011-03-24 23:53:38 +00009211 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009212 {
9213 uint32_t Rn, Rm;
9214 ARM_ShifterType shift_t;
9215 uint32_t shift_n; // the shift applied to the value read from Rm
9216 uint32_t carry;
9217 switch (encoding)
9218 {
9219 case eEncodingT1:
9220 Rn = Bits32(opcode, 19, 16);
9221 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009222 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009223 if (BadReg(Rn) || BadReg(Rm))
9224 return false;
9225 break;
9226 case eEncodingA1:
9227 Rn = Bits32(opcode, 19, 16);
9228 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009229 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009230 break;
9231 default:
9232 return false;
9233 }
9234
9235 // Read the first operand.
9236 uint32_t val1 = ReadCoreReg(Rn, &success);
9237 if (!success)
9238 return false;
9239
9240 // Read the second operand.
9241 uint32_t val2 = ReadCoreReg(Rm, &success);
9242 if (!success)
9243 return false;
9244
Johnny Chena4438a72011-06-02 22:50:51 +00009245 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9246 if (!success)
9247 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00009248 uint32_t result = val1 ^ shifted;
9249
9250 EmulateInstruction::Context context;
9251 context.type = EmulateInstruction::eContextImmediate;
9252 context.SetNoArgs ();
9253
9254 if (!WriteFlags(context, result, carry))
9255 return false;
9256 }
9257 return true;
9258}
9259
Johnny Chende3cce32011-02-21 21:24:49 +00009260// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9261// It updates the condition flags based on the result, and discards the result.
9262bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009263EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009264{
9265#if 0
9266 // ARM pseudo code...
9267 if ConditionPassed() then
9268 EncodingSpecificOperations();
9269 result = R[n] AND imm32;
9270 APSR.N = result<31>;
9271 APSR.Z = IsZeroBit(result);
9272 APSR.C = carry;
9273 // APSR.V unchanged
9274#endif
9275
9276 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009277
Greg Clayton7bc39082011-03-24 23:53:38 +00009278 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009279 {
9280 uint32_t Rn;
9281 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9282 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9283 switch (encoding)
9284 {
9285 case eEncodingT1:
9286 Rn = Bits32(opcode, 19, 16);
9287 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9288 if (BadReg(Rn))
9289 return false;
9290 break;
9291 case eEncodingA1:
9292 Rn = Bits32(opcode, 19, 16);
9293 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9294 break;
9295 default:
9296 return false;
9297 }
9298
9299 // Read the first operand.
9300 uint32_t val1 = ReadCoreReg(Rn, &success);
9301 if (!success)
9302 return false;
9303
9304 uint32_t result = val1 & imm32;
9305
9306 EmulateInstruction::Context context;
9307 context.type = EmulateInstruction::eContextImmediate;
9308 context.SetNoArgs ();
9309
9310 if (!WriteFlags(context, result, carry))
9311 return false;
9312 }
9313 return true;
9314}
9315
9316// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9317// It updates the condition flags based on the result, and discards the result.
9318bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009319EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009320{
9321#if 0
9322 // ARM pseudo code...
9323 if ConditionPassed() then
9324 EncodingSpecificOperations();
9325 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9326 result = R[n] AND shifted;
9327 APSR.N = result<31>;
9328 APSR.Z = IsZeroBit(result);
9329 APSR.C = carry;
9330 // APSR.V unchanged
9331#endif
9332
9333 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009334
Greg Clayton7bc39082011-03-24 23:53:38 +00009335 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009336 {
9337 uint32_t Rn, Rm;
9338 ARM_ShifterType shift_t;
9339 uint32_t shift_n; // the shift applied to the value read from Rm
9340 uint32_t carry;
9341 switch (encoding)
9342 {
9343 case eEncodingT1:
9344 Rn = Bits32(opcode, 2, 0);
9345 Rm = Bits32(opcode, 5, 3);
9346 shift_t = SRType_LSL;
9347 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009348 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009349 case eEncodingT2:
9350 Rn = Bits32(opcode, 19, 16);
9351 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009352 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009353 if (BadReg(Rn) || BadReg(Rm))
9354 return false;
9355 break;
9356 case eEncodingA1:
9357 Rn = Bits32(opcode, 19, 16);
9358 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009359 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009360 break;
9361 default:
9362 return false;
9363 }
9364
9365 // Read the first operand.
9366 uint32_t val1 = ReadCoreReg(Rn, &success);
9367 if (!success)
9368 return false;
9369
9370 // Read the second operand.
9371 uint32_t val2 = ReadCoreReg(Rm, &success);
9372 if (!success)
9373 return false;
9374
Johnny Chena4438a72011-06-02 22:50:51 +00009375 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9376 if (!success)
9377 return false;
Johnny Chende3cce32011-02-21 21:24:49 +00009378 uint32_t result = val1 & shifted;
9379
9380 EmulateInstruction::Context context;
9381 context.type = EmulateInstruction::eContextImmediate;
9382 context.SetNoArgs ();
9383
9384 if (!WriteFlags(context, result, carry))
9385 return false;
9386 }
9387 return true;
9388}
Caroline Ticed05b4902011-03-29 21:24:06 +00009389
9390// A8.6.216 SUB (SP minus register)
9391bool
9392EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9393{
9394#if 0
9395 if ConditionPassed() then
9396 EncodingSpecificOperations();
9397 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009398 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009399 if d == 15 then // Can only occur for ARM encoding
9400 ALUWritePC(result); // setflags is always FALSE here
9401 else
9402 R[d] = result;
9403 if setflags then
9404 APSR.N = result<31>;
9405 APSR.Z = IsZeroBit(result);
9406 APSR.C = carry;
9407 APSR.V = overflow;
9408#endif
9409
9410 bool success = false;
9411
9412 if (ConditionPassed(opcode))
9413 {
9414 uint32_t d;
9415 uint32_t m;
9416 bool setflags;
9417 ARM_ShifterType shift_t;
9418 uint32_t shift_n;
9419
9420 switch (encoding)
9421 {
9422 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009423 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009424 d = Bits32 (opcode, 11, 8);
9425 m = Bits32 (opcode, 3, 0);
9426 setflags = BitIsSet (opcode, 20);
9427
9428 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9429 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9430
9431 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9432 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9433 return false;
9434
9435 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9436 if ((d == 15) || BadReg (m))
9437 return false;
9438 break;
9439
9440 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009441 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009442 d = Bits32 (opcode, 15, 12);
9443 m = Bits32 (opcode, 3, 0);
9444 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009445
Greg Clayton061b79d2011-05-09 20:18:18 +00009446 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009447 if (d == 15 && setflags)
9448 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009449
9450 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9451 shift_n = DecodeImmShiftARM (opcode, shift_t);
9452 break;
9453
9454 default:
9455 return false;
9456 }
9457
9458 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9459 uint32_t Rm = ReadCoreReg (m, &success);
9460 if (!success)
9461 return false;
9462
Johnny Chena4438a72011-06-02 22:50:51 +00009463 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9464 if (!success)
9465 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009466
Greg Clayton061b79d2011-05-09 20:18:18 +00009467 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009468 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9469 if (!success)
9470 return false;
9471
9472 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9473
9474 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009475 context.type = eContextArithmetic;
9476 RegisterInfo sp_reg;
9477 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9478 RegisterInfo dwarf_reg;
9479 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +00009480 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9481
Caroline Ticeef440002011-03-30 05:40:56 +00009482 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009483 return false;
9484 }
9485 return true;
9486}
9487
9488
9489// A8.6.7 ADD (register-shifted register)
9490bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009491EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009492{
9493#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009494 if ConditionPassed() then
9495 EncodingSpecificOperations();
9496 shift_n = UInt(R[s]<7:0>);
9497 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009498 (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009499 R[d] = result;
9500 if setflags then
9501 APSR.N = result<31>;
9502 APSR.Z = IsZeroBit(result);
9503 APSR.C = carry;
9504 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009505#endif
9506
Caroline Ticec08ed382011-03-29 23:03:16 +00009507 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009508
9509 if (ConditionPassed(opcode))
9510 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009511 uint32_t d;
9512 uint32_t n;
9513 uint32_t m;
9514 uint32_t s;
9515 bool setflags;
9516 ARM_ShifterType shift_t;
9517
Caroline Ticed05b4902011-03-29 21:24:06 +00009518 switch (encoding)
9519 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009520 case eEncodingA1:
9521 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9522 d = Bits32 (opcode, 15, 12);
9523 n = Bits32 (opcode, 19, 16);
9524 m = Bits32 (opcode, 3, 0);
9525 s = Bits32 (opcode, 11, 8);
9526
Greg Clayton061b79d2011-05-09 20:18:18 +00009527 // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
Caroline Ticec08ed382011-03-29 23:03:16 +00009528 setflags = BitIsSet (opcode, 20);
9529 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9530
9531 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9532 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9533 return false;
9534 break;
9535
9536 default:
9537 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009538 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009539
9540 // shift_n = UInt(R[s]<7:0>);
9541 uint32_t Rs = ReadCoreReg (s, &success);
9542 if (!success)
9543 return false;
9544
9545 uint32_t shift_n = Bits32 (Rs, 7, 0);
9546
9547 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9548 uint32_t Rm = ReadCoreReg (m, &success);
9549 if (!success)
9550 return false;
9551
Johnny Chena4438a72011-06-02 22:50:51 +00009552 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9553 if (!success)
9554 return false;
9555
Greg Clayton061b79d2011-05-09 20:18:18 +00009556 // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009557 uint32_t Rn = ReadCoreReg (n, &success);
9558 if (!success)
9559 return false;
9560
9561 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9562
9563 // R[d] = result;
9564 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009565 context.type = eContextArithmetic;
9566 RegisterInfo reg_n;
9567 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9568 RegisterInfo reg_m;
9569 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009570
9571 context.SetRegisterRegisterOperands (reg_n, reg_m);
9572
9573 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9574 return false;
9575
9576 // if setflags then
9577 // APSR.N = result<31>;
9578 // APSR.Z = IsZeroBit(result);
9579 // APSR.C = carry;
9580 // APSR.V = overflow;
9581 if (setflags)
9582 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009583 }
9584 return true;
9585}
9586
9587// A8.6.213 SUB (register)
9588bool
9589EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9590{
9591#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009592 if ConditionPassed() then
9593 EncodingSpecificOperations();
9594 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009595 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009596 if d == 15 then // Can only occur for ARM encoding
9597 ALUWritePC(result); // setflags is always FALSE here
9598 else
9599 R[d] = result;
9600 if setflags then
9601 APSR.N = result<31>;
9602 APSR.Z = IsZeroBit(result);
9603 APSR.C = carry;
9604 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009605#endif
9606
Caroline Tice4cccd532011-03-29 23:44:20 +00009607 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009608
9609 if (ConditionPassed(opcode))
9610 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009611 uint32_t d;
9612 uint32_t n;
9613 uint32_t m;
9614 bool setflags;
9615 ARM_ShifterType shift_t;
9616 uint32_t shift_n;
9617
Caroline Ticed05b4902011-03-29 21:24:06 +00009618 switch (encoding)
9619 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009620 case eEncodingT1:
9621 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9622 d = Bits32 (opcode, 2, 0);
9623 n = Bits32 (opcode, 5, 3);
9624 m = Bits32 (opcode, 8, 6);
9625 setflags = !InITBlock();
9626
9627 // (shift_t, shift_n) = (SRType_LSL, 0);
9628 shift_t = SRType_LSL;
9629 shift_n = 0;
9630
9631 break;
9632
9633 case eEncodingT2:
Greg Clayton061b79d2011-05-09 20:18:18 +00009634 // if Rd == Ô1111Õ && S == Ô1Õ then SEE CMP (register);
9635 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9636 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009637 d = Bits32 (opcode, 11, 8);
9638 n = Bits32 (opcode, 19, 16);
9639 m = Bits32 (opcode, 3, 0);
9640 setflags = BitIsSet (opcode, 20);
9641
9642 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9643 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9644
9645 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9646 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9647 return false;
9648
9649 break;
9650
9651 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009652 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9653 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009654 d = Bits32 (opcode, 15, 12);
9655 n = Bits32 (opcode, 19, 16);
9656 m = Bits32 (opcode, 3, 0);
9657 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009658
Greg Clayton061b79d2011-05-09 20:18:18 +00009659 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009660 if ((d == 15) && setflags)
9661 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009662
9663 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9664 shift_n = DecodeImmShiftARM (opcode, shift_t);
9665
9666 break;
9667
9668 default:
9669 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009670 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009671
9672 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9673 uint32_t Rm = ReadCoreReg (m, &success);
9674 if (!success)
9675 return false;
9676
Johnny Chena4438a72011-06-02 22:50:51 +00009677 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9678 if (!success)
9679 return false;
Caroline Tice4cccd532011-03-29 23:44:20 +00009680
Greg Clayton061b79d2011-05-09 20:18:18 +00009681 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009682 uint32_t Rn = ReadCoreReg (n, &success);
9683 if (!success)
9684 return false;
9685
9686 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9687
9688 // if d == 15 then // Can only occur for ARM encoding
9689 // ALUWritePC(result); // setflags is always FALSE here
9690 // else
9691 // R[d] = result;
9692 // if setflags then
9693 // APSR.N = result<31>;
9694 // APSR.Z = IsZeroBit(result);
9695 // APSR.C = carry;
9696 // APSR.V = overflow;
9697
9698 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009699 context.type = eContextArithmetic;
9700 RegisterInfo reg_n;
9701 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9702 RegisterInfo reg_m;
9703 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009704 context.SetRegisterRegisterOperands (reg_n, reg_m);
9705
Caroline Ticeef440002011-03-30 05:40:56 +00009706 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009707 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009708 }
9709 return true;
9710}
Caroline Tice4cccd532011-03-29 23:44:20 +00009711
Caroline Ticed05b4902011-03-29 21:24:06 +00009712// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009713// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9714// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009715bool
9716EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9717{
9718#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009719 if ConditionPassed() then
9720 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9721 address = R[n] + imm32;
9722 if ExclusiveMonitorsPass(address,4) then
9723 MemA[address,4] = R[t];
9724 R[d] = 0;
9725 else
9726 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009727#endif
9728
Caroline Tice5168b6c2011-03-30 05:15:46 +00009729 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009730
9731 if (ConditionPassed(opcode))
9732 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009733 uint32_t d;
9734 uint32_t t;
9735 uint32_t n;
9736 uint32_t imm32;
9737 const uint32_t addr_byte_size = GetAddressByteSize();
9738
Caroline Ticed05b4902011-03-29 21:24:06 +00009739 switch (encoding)
9740 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009741 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009742 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009743 d = Bits32 (opcode, 11, 8);
9744 t = Bits32 (opcode, 15, 12);
9745 n = Bits32 (opcode, 19, 16);
9746 imm32 = Bits32 (opcode, 7, 0) << 2;
9747
9748 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9749 if (BadReg (d) || BadReg (t) || (n == 15))
9750 return false;
9751
9752 // if d == n || d == t then UNPREDICTABLE;
9753 if ((d == n) || (d == t))
9754 return false;
9755
9756 break;
9757
9758 case eEncodingA1:
9759 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9760 d = Bits32 (opcode, 15, 12);
9761 t = Bits32 (opcode, 3, 0);
9762 n = Bits32 (opcode, 19, 16);
9763 imm32 = 0;
9764
9765 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9766 if ((d == 15) || (t == 15) || (n == 15))
9767 return false;
9768
9769 // if d == n || d == t then UNPREDICTABLE;
9770 if ((d == n) || (d == t))
9771 return false;
9772
9773 break;
9774
9775 default:
9776 return false;
9777 }
9778
9779 // address = R[n] + imm32;
9780 uint32_t Rn = ReadCoreReg (n, &success);
9781 if (!success)
9782 return false;
9783
9784 addr_t address = Rn + imm32;
9785
Greg Claytonc07d4512011-04-26 23:48:45 +00009786 RegisterInfo base_reg;
9787 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9788 RegisterInfo data_reg;
9789 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009790 EmulateInstruction::Context context;
9791 context.type = eContextRegisterStore;
9792 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9793
9794 // if ExclusiveMonitorsPass(address,4) then
9795 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9796 // always return true.
9797 if (true)
9798 {
9799 // MemA[address,4] = R[t];
9800 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9801 if (!success)
9802 return false;
9803
9804 if (!MemAWrite (context, address, Rt, addr_byte_size))
9805 return false;
9806
9807 // R[d] = 0;
9808 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9809 return false;
9810 }
9811 else
9812 {
9813 // R[d] = 1;
9814 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9815 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009816 }
9817 }
9818 return true;
9819}
9820
9821// A8.6.197 STRB (immediate, ARM)
9822bool
9823EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9824{
9825#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009826 if ConditionPassed() then
9827 EncodingSpecificOperations();
9828 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9829 address = if index then offset_addr else R[n];
9830 MemU[address,1] = R[t]<7:0>;
9831 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009832#endif
9833
Caroline Ticeef440002011-03-30 05:40:56 +00009834 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009835
9836 if (ConditionPassed(opcode))
9837 {
Caroline Ticeef440002011-03-30 05:40:56 +00009838 uint32_t t;
9839 uint32_t n;
9840 uint32_t imm32;
9841 bool index;
9842 bool add;
9843 bool wback;
9844
Caroline Ticed05b4902011-03-29 21:24:06 +00009845 switch (encoding)
9846 {
Caroline Ticeef440002011-03-30 05:40:56 +00009847 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009848 // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
Caroline Ticeef440002011-03-30 05:40:56 +00009849 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9850 t = Bits32 (opcode, 15, 12);
9851 n = Bits32 (opcode, 19, 16);
9852 imm32 = Bits32 (opcode, 11, 0);
9853
Greg Clayton061b79d2011-05-09 20:18:18 +00009854 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeef440002011-03-30 05:40:56 +00009855 index = BitIsSet (opcode, 24);
9856 add = BitIsSet (opcode, 23);
9857 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9858
9859 // if t == 15 then UNPREDICTABLE;
9860 if (t == 15)
9861 return false;
9862
9863 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9864 if (wback && ((n == 15) || (n == t)))
9865 return false;
9866
9867 break;
9868
9869 default:
9870 return false;
9871 }
9872
9873 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9874 uint32_t Rn = ReadCoreReg (n, &success);
9875 if (!success)
9876 return false;
9877
9878 addr_t offset_addr;
9879 if (add)
9880 offset_addr = Rn + imm32;
9881 else
9882 offset_addr = Rn - imm32;
9883
9884 // address = if index then offset_addr else R[n];
9885 addr_t address;
9886 if (index)
9887 address = offset_addr;
9888 else
9889 address = Rn;
9890
9891 // MemU[address,1] = R[t]<7:0>;
9892 uint32_t Rt = ReadCoreReg (t, &success);
9893 if (!success)
9894 return false;
9895
Greg Claytonc07d4512011-04-26 23:48:45 +00009896 RegisterInfo base_reg;
9897 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9898 RegisterInfo data_reg;
9899 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticeef440002011-03-30 05:40:56 +00009900 EmulateInstruction::Context context;
9901 context.type = eContextRegisterStore;
9902 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9903
9904 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9905 return false;
9906
9907 // if wback then R[n] = offset_addr;
9908 if (wback)
9909 {
Caroline Tice523c5542011-04-13 00:42:12 +00009910 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009911 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009912 }
9913 }
9914 return true;
9915}
9916
9917// A8.6.194 STR (immediate, ARM)
9918bool
9919EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9920{
9921#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009922 if ConditionPassed() then
9923 EncodingSpecificOperations();
9924 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9925 address = if index then offset_addr else R[n];
9926 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9927 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009928#endif
9929
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009930 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009931
9932 if (ConditionPassed(opcode))
9933 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009934 uint32_t t;
9935 uint32_t n;
9936 uint32_t imm32;
9937 bool index;
9938 bool add;
9939 bool wback;
9940
9941 const uint32_t addr_byte_size = GetAddressByteSize();
9942
Caroline Ticed05b4902011-03-29 21:24:06 +00009943 switch (encoding)
9944 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009945 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009946 // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
9947 // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009948 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9949 t = Bits32 (opcode, 15, 12);
9950 n = Bits32 (opcode, 19, 16);
9951 imm32 = Bits32 (opcode, 11, 0);
9952
Greg Clayton061b79d2011-05-09 20:18:18 +00009953 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009954 index = BitIsSet (opcode, 24);
9955 add = BitIsSet (opcode, 23);
9956 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9957
9958 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9959 if (wback && ((n == 15) || (n == t)))
9960 return false;
9961
9962 break;
9963
9964 default:
9965 return false;
9966 }
9967
9968 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9969 uint32_t Rn = ReadCoreReg (n, &success);
9970 if (!success)
9971 return false;
9972
9973 addr_t offset_addr;
9974 if (add)
9975 offset_addr = Rn + imm32;
9976 else
9977 offset_addr = Rn - imm32;
9978
9979 // address = if index then offset_addr else R[n];
9980 addr_t address;
9981 if (index)
9982 address = offset_addr;
9983 else
9984 address = Rn;
9985
Greg Claytonc07d4512011-04-26 23:48:45 +00009986 RegisterInfo base_reg;
9987 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9988 RegisterInfo data_reg;
9989 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009990 EmulateInstruction::Context context;
9991 context.type = eContextRegisterStore;
9992 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9993
9994 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9995 uint32_t Rt = ReadCoreReg (t, &success);
9996 if (!success)
9997 return false;
9998
9999 if (t == 15)
10000 {
Caroline Ticee98b9582011-03-30 16:05:23 +000010001 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +000010002 if (!success)
10003 return false;
10004
10005 if (!MemUWrite (context, address, pc_value, addr_byte_size))
10006 return false;
10007 }
10008 else
10009 {
10010 if (!MemUWrite (context, address, Rt, addr_byte_size))
10011 return false;
10012 }
10013
10014 // if wback then R[n] = offset_addr;
10015 if (wback)
10016 {
10017 context.type = eContextAdjustBaseRegister;
10018 context.SetImmediate (offset_addr);
10019
10020 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10021 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010022 }
10023 }
10024 return true;
10025}
10026
Caroline Ticed05b4902011-03-29 21:24:06 +000010027// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +000010028// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
10029// words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing.
Caroline Ticed05b4902011-03-29 21:24:06 +000010030bool
10031EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
10032{
10033#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +000010034 if ConditionPassed() then
10035 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10036 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10037 address = if index then offset_addr else R[n];
10038 R[t] = MemA[address,4];
10039 R[t2] = MemA[address+4,4];
10040 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010041#endif
10042
Caroline Tice1697dd72011-03-30 17:11:45 +000010043 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010044
10045 if (ConditionPassed(opcode))
10046 {
Caroline Tice1697dd72011-03-30 17:11:45 +000010047 uint32_t t;
10048 uint32_t t2;
10049 uint32_t n;
10050 uint32_t imm32;
10051 bool index;
10052 bool add;
10053 bool wback;
10054
Caroline Ticed05b4902011-03-29 21:24:06 +000010055 switch (encoding)
10056 {
Caroline Tice1697dd72011-03-30 17:11:45 +000010057 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010058 //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10059 //if Rn == Ô1111Õ then SEE LDRD (literal);
10060 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice1697dd72011-03-30 17:11:45 +000010061 t = Bits32 (opcode, 15, 12);
10062 t2 = Bits32 (opcode, 11, 8);
10063 n = Bits32 (opcode, 19, 16);
10064 imm32 = Bits32 (opcode, 7, 0) << 2;
10065
Greg Clayton061b79d2011-05-09 20:18:18 +000010066 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +000010067 index = BitIsSet (opcode, 24);
10068 add = BitIsSet (opcode, 23);
10069 wback = BitIsSet (opcode, 21);
10070
10071 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10072 if (wback && ((n == t) || (n == t2)))
10073 return false;
10074
10075 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10076 if (BadReg (t) || BadReg (t2) || (t == t2))
10077 return false;
10078
10079 break;
10080
10081 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010082 //if Rn == Ô1111Õ then SEE LDRD (literal);
10083 //if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010084 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10085 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010086 if (BitIsSet (t, 0))
10087 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +000010088 t2 = t + 1;
10089 n = Bits32 (opcode, 19, 16);
10090 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10091
Greg Clayton061b79d2011-05-09 20:18:18 +000010092 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +000010093 index = BitIsSet (opcode, 24);
10094 add = BitIsSet (opcode, 23);
10095 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10096
Greg Clayton061b79d2011-05-09 20:18:18 +000010097 //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010098 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10099 return false;
10100
10101 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10102 if (wback && ((n == t) || (n == t2)))
10103 return false;
10104
10105 //if t2 == 15 then UNPREDICTABLE;
10106 if (t2 == 15)
10107 return false;
10108
10109 break;
10110
10111 default:
10112 return false;
10113 }
10114
10115 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10116 uint32_t Rn = ReadCoreReg (n, &success);
10117 if (!success)
10118 return false;
10119
10120 addr_t offset_addr;
10121 if (add)
10122 offset_addr = Rn + imm32;
10123 else
10124 offset_addr = Rn - imm32;
10125
10126 //address = if index then offset_addr else R[n];
10127 addr_t address;
10128 if (index)
10129 address = offset_addr;
10130 else
10131 address = Rn;
10132
10133 //R[t] = MemA[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +000010134 RegisterInfo base_reg;
10135 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1697dd72011-03-30 17:11:45 +000010136
10137 EmulateInstruction::Context context;
10138 context.type = eContextRegisterLoad;
10139 context.SetRegisterPlusOffset (base_reg, address - Rn);
10140
10141 const uint32_t addr_byte_size = GetAddressByteSize();
10142 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10143 if (!success)
10144 return false;
10145
10146 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10147 return false;
10148
10149 //R[t2] = MemA[address+4,4];
10150
10151 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10152 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10153 if (!success)
10154 return false;
10155
10156 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10157 return false;
10158
10159 //if wback then R[n] = offset_addr;
10160 if (wback)
10161 {
10162 context.type = eContextAdjustBaseRegister;
10163 context.SetAddress (offset_addr);
10164
10165 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10166 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010167 }
10168 }
10169 return true;
10170}
10171
Caroline Ticed05b4902011-03-29 21:24:06 +000010172// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010173// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10174// 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 +000010175bool
10176EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10177{
10178#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010179 if ConditionPassed() then
10180 EncodingSpecificOperations();
10181 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10182 address = if index then offset_addr else R[n];
10183 R[t] = MemA[address,4];
10184 R[t2] = MemA[address+4,4];
10185 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010186#endif
10187
Caroline Ticeeab301f2011-03-30 17:54:52 +000010188 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010189
10190 if (ConditionPassed(opcode))
10191 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010192 uint32_t t;
10193 uint32_t t2;
10194 uint32_t n;
10195 uint32_t m;
10196 bool index;
10197 bool add;
10198 bool wback;
10199
Caroline Ticed05b4902011-03-29 21:24:06 +000010200 switch (encoding)
10201 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010202 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010203 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010204 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10205 t = Bits32 (opcode, 15, 12);
10206 if (BitIsSet (t, 0))
10207 return false;
10208 t2 = t + 1;
10209 n = Bits32 (opcode, 19, 16);
10210 m = Bits32 (opcode, 3, 0);
10211
Greg Clayton061b79d2011-05-09 20:18:18 +000010212 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010213 index = BitIsSet (opcode, 24);
10214 add = BitIsSet (opcode, 23);
10215 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10216
Greg Clayton061b79d2011-05-09 20:18:18 +000010217 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010218 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10219 return false;
10220
10221 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10222 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10223 return false;
10224
10225 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10226 if (wback && ((n == 15) || (n == t) || (n == t2)))
10227 return false;
10228
10229 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10230 if ((ArchVersion() < 6) && wback && (m == n))
10231 return false;
10232 break;
10233
10234 default:
10235 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010236 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010237
Caroline Ticeeab301f2011-03-30 17:54:52 +000010238 uint32_t Rn = ReadCoreReg (n, &success);
10239 if (!success)
10240 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010241 RegisterInfo base_reg;
10242 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010243
Caroline Ticeeab301f2011-03-30 17:54:52 +000010244 uint32_t Rm = ReadCoreReg (m, &success);
10245 if (!success)
10246 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010247 RegisterInfo offset_reg;
10248 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010249
Caroline Ticeeab301f2011-03-30 17:54:52 +000010250 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10251 addr_t offset_addr;
10252 if (add)
10253 offset_addr = Rn + Rm;
10254 else
10255 offset_addr = Rn - Rm;
10256
10257 // address = if index then offset_addr else R[n];
10258 addr_t address;
10259 if (index)
10260 address = offset_addr;
10261 else
10262 address = Rn;
10263
10264 EmulateInstruction::Context context;
10265 context.type = eContextRegisterLoad;
10266 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10267
10268 // R[t] = MemA[address,4];
10269 const uint32_t addr_byte_size = GetAddressByteSize();
10270 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10271 if (!success)
10272 return false;
10273
10274 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10275 return false;
10276
10277 // R[t2] = MemA[address+4,4];
10278
10279 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10280 if (!success)
10281 return false;
10282
10283 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10284 return false;
10285
10286 // if wback then R[n] = offset_addr;
10287 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010288 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010289 context.type = eContextAdjustBaseRegister;
10290 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010291
Caroline Ticeeab301f2011-03-30 17:54:52 +000010292 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10293 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010294 }
10295 }
10296 return true;
10297}
Caroline Ticed05b4902011-03-29 21:24:06 +000010298
10299// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010300// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10301// 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 +000010302bool
10303EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10304{
10305#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010306 if ConditionPassed() then
10307 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10308 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10309 address = if index then offset_addr else R[n];
10310 MemA[address,4] = R[t];
10311 MemA[address+4,4] = R[t2];
10312 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010313#endif
10314
Caroline Tice74467fe2011-03-30 19:02:56 +000010315 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010316
Caroline Tice74467fe2011-03-30 19:02:56 +000010317 if (ConditionPassed(opcode))
10318 {
10319 uint32_t t;
10320 uint32_t t2;
10321 uint32_t n;
10322 uint32_t imm32;
10323 bool index;
10324 bool add;
10325 bool wback;
10326
10327 switch (encoding)
10328 {
10329 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010330 // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10331 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice74467fe2011-03-30 19:02:56 +000010332 t = Bits32 (opcode, 15, 12);
10333 t2 = Bits32 (opcode, 11, 8);
10334 n = Bits32 (opcode, 19, 16);
10335 imm32 = Bits32 (opcode, 7, 0) << 2;
10336
Greg Clayton061b79d2011-05-09 20:18:18 +000010337 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010338 index = BitIsSet (opcode, 24);
10339 add = BitIsSet (opcode, 23);
10340 wback = BitIsSet (opcode, 21);
10341
10342 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10343 if (wback && ((n == t) || (n == t2)))
10344 return false;
10345
10346 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10347 if ((n == 15) || BadReg (t) || BadReg (t2))
10348 return false;
10349
10350 break;
10351
10352 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010353 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010354 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10355 t = Bits32 (opcode, 15, 12);
10356 if (BitIsSet (t, 0))
10357 return false;
10358
10359 t2 = t + 1;
10360 n = Bits32 (opcode, 19, 16);
10361 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10362
Greg Clayton061b79d2011-05-09 20:18:18 +000010363 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010364 index = BitIsSet (opcode, 24);
10365 add = BitIsSet (opcode, 23);
10366 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10367
Greg Clayton061b79d2011-05-09 20:18:18 +000010368 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010369 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10370 return false;
10371
10372 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10373 if (wback && ((n == 15) || (n == t) || (n == t2)))
10374 return false;
10375
10376 // if t2 == 15 then UNPREDICTABLE;
10377 if (t2 == 15)
10378 return false;
10379
10380 break;
10381
10382 default:
10383 return false;
10384 }
10385
Greg Claytonc07d4512011-04-26 23:48:45 +000010386 RegisterInfo base_reg;
10387 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010388
10389 uint32_t Rn = ReadCoreReg (n, &success);
10390 if (!success)
10391 return false;
10392
10393 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10394 addr_t offset_addr;
10395 if (add)
10396 offset_addr = Rn + imm32;
10397 else
10398 offset_addr = Rn - imm32;
10399
10400 //address = if index then offset_addr else R[n];
10401 addr_t address;
10402 if (index)
10403 address = offset_addr;
10404 else
10405 address = Rn;
10406
10407 //MemA[address,4] = R[t];
Greg Claytonc07d4512011-04-26 23:48:45 +000010408 RegisterInfo data_reg;
10409 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010410
10411 uint32_t data = ReadCoreReg (t, &success);
10412 if (!success)
10413 return false;
10414
10415 EmulateInstruction::Context context;
10416 context.type = eContextRegisterStore;
10417 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10418
10419 const uint32_t addr_byte_size = GetAddressByteSize();
10420
10421 if (!MemAWrite (context, address, data, addr_byte_size))
10422 return false;
10423
10424 //MemA[address+4,4] = R[t2];
Greg Claytonc07d4512011-04-26 23:48:45 +000010425 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010426 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10427
10428 data = ReadCoreReg (t2, &success);
10429 if (!success)
10430 return false;
10431
10432 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10433 return false;
10434
10435 //if wback then R[n] = offset_addr;
10436 if (wback)
10437 {
10438 context.type = eContextAdjustBaseRegister;
10439 context.SetAddress (offset_addr);
10440
10441 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10442 return false;
10443 }
10444 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010445 return true;
10446}
10447
10448
10449// A8.6.201 STRD (register)
10450bool
10451EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10452{
10453#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010454 if ConditionPassed() then
10455 EncodingSpecificOperations();
10456 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10457 address = if index then offset_addr else R[n];
10458 MemA[address,4] = R[t];
10459 MemA[address+4,4] = R[t2];
10460 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010461#endif
10462
Caroline Tice74467fe2011-03-30 19:02:56 +000010463 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010464
Caroline Tice74467fe2011-03-30 19:02:56 +000010465 if (ConditionPassed(opcode))
10466 {
10467 uint32_t t;
10468 uint32_t t2;
10469 uint32_t n;
10470 uint32_t m;
10471 bool index;
10472 bool add;
10473 bool wback;
10474
10475 switch (encoding)
10476 {
10477 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010478 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010479 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10480 t = Bits32 (opcode, 15, 12);
10481 if (BitIsSet (t, 0))
10482 return false;
10483
10484 t2 = t+1;
10485 n = Bits32 (opcode, 19, 16);
10486 m = Bits32 (opcode, 3, 0);
10487
Greg Clayton061b79d2011-05-09 20:18:18 +000010488 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010489 index = BitIsSet (opcode, 24);
10490 add = BitIsSet (opcode, 23);
10491 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10492
Greg Clayton061b79d2011-05-09 20:18:18 +000010493 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010494 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10495 return false;
10496
10497 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10498 if ((t2 == 15) || (m == 15))
10499 return false;
10500
10501 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10502 if (wback && ((n == 15) || (n == t) || (n == t2)))
10503 return false;
10504
10505 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010506 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010507 return false;
10508
10509 break;
10510
10511 default:
10512 return false;
10513 }
10514
Greg Claytonc07d4512011-04-26 23:48:45 +000010515 RegisterInfo base_reg;
10516 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10517 RegisterInfo offset_reg;
10518 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10519 RegisterInfo data_reg;
Caroline Tice74467fe2011-03-30 19:02:56 +000010520
10521 uint32_t Rn = ReadCoreReg (n, &success);
10522 if (!success)
10523 return false;
10524
10525 uint32_t Rm = ReadCoreReg (m, &success);
10526 if (!success)
10527 return false;
10528
10529 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10530 addr_t offset_addr;
10531 if (add)
10532 offset_addr = Rn + Rm;
10533 else
10534 offset_addr = Rn - Rm;
10535
10536 // address = if index then offset_addr else R[n];
10537 addr_t address;
10538 if (index)
10539 address = offset_addr;
10540 else
10541 address = Rn;
10542 // MemA[address,4] = R[t];
10543 uint32_t Rt = ReadCoreReg (t, &success);
10544 if (!success)
10545 return false;
10546
10547 EmulateInstruction::Context context;
10548 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +000010549 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010550 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10551
10552 const uint32_t addr_byte_size = GetAddressByteSize();
10553
10554 if (!MemAWrite (context, address, Rt, addr_byte_size))
10555 return false;
10556
10557 // MemA[address+4,4] = R[t2];
10558 uint32_t Rt2 = ReadCoreReg (t2, &success);
10559 if (!success)
10560 return false;
10561
Greg Claytonc07d4512011-04-26 23:48:45 +000010562 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010563
10564 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10565
10566 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10567 return false;
10568
10569 // if wback then R[n] = offset_addr;
10570 if (wback)
10571 {
10572 context.type = eContextAdjustBaseRegister;
10573 context.SetAddress (offset_addr);
10574
10575 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10576 return false;
10577
10578 }
10579 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010580 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010581}
10582
Caroline Tice4f605582011-03-31 00:02:51 +000010583// A8.6.319 VLDM
10584// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10585// an ARM core register.
10586bool
10587EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10588{
10589#if 0
10590 if ConditionPassed() then
10591 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10592 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010593 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010594 for r = 0 to regs-1
10595 if single_regs then
10596 S[d+r] = MemA[address,4]; address = address+4;
10597 else
10598 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10599 // Combine the word-aligned words in the correct order for current endianness.
10600 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10601#endif
10602
10603 bool success = false;
10604
10605 if (ConditionPassed(opcode))
10606 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010607 bool single_regs;
10608 bool add;
10609 bool wback;
10610 uint32_t d;
10611 uint32_t n;
10612 uint32_t imm32;
10613 uint32_t regs;
10614
Caroline Tice4f605582011-03-31 00:02:51 +000010615 switch (encoding)
10616 {
10617 case eEncodingT1:
10618 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010619 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10620 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10621 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10622 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010623 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10624 return false;
10625
10626 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010627 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice4f605582011-03-31 00:02:51 +000010628 single_regs = false;
10629 add = BitIsSet (opcode, 23);
10630 wback = BitIsSet (opcode, 21);
10631
Greg Clayton061b79d2011-05-09 20:18:18 +000010632 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice4f605582011-03-31 00:02:51 +000010633 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10634 n = Bits32 (opcode, 19, 16);
10635 imm32 = Bits32 (opcode, 7, 0) << 2;
10636
Greg Clayton061b79d2011-05-09 20:18:18 +000010637 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
Caroline Tice4f605582011-03-31 00:02:51 +000010638 regs = Bits32 (opcode, 7, 0) / 2;
10639
10640 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10641 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10642 return false;
10643
10644 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10645 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10646 return false;
10647
10648 break;
10649
10650 case eEncodingT2:
10651 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010652 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10653 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10654 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10655 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010656 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10657 return false;
10658
10659 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010660 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Tice4f605582011-03-31 00:02:51 +000010661 single_regs = true;
10662 add = BitIsSet (opcode, 23);
10663 wback = BitIsSet (opcode, 21);
10664 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10665 n = Bits32 (opcode, 19, 16);
10666
Greg Clayton061b79d2011-05-09 20:18:18 +000010667 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Tice4f605582011-03-31 00:02:51 +000010668 imm32 = Bits32 (opcode, 7, 0) << 2;
10669 regs = Bits32 (opcode, 7, 0);
10670
10671 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10672 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10673 return false;
10674
10675 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10676 if ((regs == 0) || ((d + regs) > 32))
10677 return false;
10678 break;
10679
10680 default:
10681 return false;
10682 }
10683
Greg Claytonc07d4512011-04-26 23:48:45 +000010684 RegisterInfo base_reg;
10685 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4f605582011-03-31 00:02:51 +000010686
10687 uint32_t Rn = ReadCoreReg (n, &success);
10688 if (!success)
10689 return false;
10690
10691 // address = if add then R[n] else R[n]-imm32;
10692 addr_t address;
10693 if (add)
10694 address = Rn;
10695 else
10696 address = Rn - imm32;
10697
Greg Claytonc07d4512011-04-26 23:48:45 +000010698 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010699 EmulateInstruction::Context context;
10700
10701 if (wback)
10702 {
10703 uint32_t value;
10704 if (add)
10705 value = Rn + imm32;
10706 else
10707 value = Rn - imm32;
10708
10709 context.type = eContextAdjustBaseRegister;
10710 context.SetImmediateSigned (value - Rn);
10711 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10712 return false;
10713
10714 }
10715
10716 const uint32_t addr_byte_size = GetAddressByteSize();
10717 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10718
10719 context.type = eContextRegisterLoad;
10720
10721 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010722 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010723 {
10724 if (single_regs)
10725 {
10726 // S[d+r] = MemA[address,4]; address = address+4;
10727 context.SetRegisterPlusOffset (base_reg, address - Rn);
10728
10729 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10730 if (!success)
10731 return false;
10732
10733 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10734 return false;
10735
10736 address = address + 4;
10737 }
10738 else
10739 {
10740 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10741 context.SetRegisterPlusOffset (base_reg, address - Rn);
10742 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10743 if (!success)
10744 return false;
10745
10746 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10747 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10748 if (!success)
10749 return false;
10750
10751 address = address + 8;
10752 // // Combine the word-aligned words in the correct order for current endianness.
10753 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10754 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010755 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010756 {
10757 data = word1;
10758 data = (data << 32) | word2;
10759 }
10760 else
10761 {
10762 data = word2;
10763 data = (data << 32) | word1;
10764 }
10765
10766 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10767 return false;
10768 }
10769 }
10770 }
10771 return true;
10772}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010773
10774// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010775// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10776// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010777bool
10778EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10779{
10780#if 0
10781 if ConditionPassed() then
10782 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10783 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010784 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010785 for r = 0 to regs-1
10786 if single_regs then
10787 MemA[address,4] = S[d+r]; address = address+4;
10788 else
10789 // Store as two word-aligned words in the correct order for current endianness.
10790 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10791 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10792 address = address+8;
10793#endif
10794
10795 bool success = false;
10796
10797 if (ConditionPassed (opcode))
10798 {
10799 bool single_regs;
10800 bool add;
10801 bool wback;
10802 uint32_t d;
10803 uint32_t n;
10804 uint32_t imm32;
10805 uint32_t regs;
10806
10807 switch (encoding)
10808 {
10809 case eEncodingT1:
10810 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010811 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10812 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10813 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10814 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010815 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10816 return false;
10817
10818 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010819 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010820 single_regs = false;
10821 add = BitIsSet (opcode, 23);
10822 wback = BitIsSet (opcode, 21);
10823
Greg Clayton061b79d2011-05-09 20:18:18 +000010824 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010825 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10826 n = Bits32 (opcode, 19, 16);
10827 imm32 = Bits32 (opcode, 7, 0) << 2;
10828
Greg Clayton061b79d2011-05-09 20:18:18 +000010829 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010830 regs = Bits32 (opcode, 7, 0) / 2;
10831
10832 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10833 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10834 return false;
10835
10836 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10837 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10838 return false;
10839
10840 break;
10841
10842 case eEncodingT2:
10843 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010844 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10845 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10846 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10847 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010848 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10849 return false;
10850
10851 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010852 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010853 single_regs = true;
10854 add = BitIsSet (opcode, 23);
10855 wback = BitIsSet (opcode, 21);
10856 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10857 n = Bits32 (opcode, 19, 16);
10858
Greg Clayton061b79d2011-05-09 20:18:18 +000010859 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010860 imm32 = Bits32 (opcode, 7, 0) << 2;
10861 regs = Bits32 (opcode, 7, 0);
10862
10863 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10864 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10865 return false;
10866
10867 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10868 if ((regs == 0) || ((d + regs) > 32))
10869 return false;
10870
10871 break;
10872
10873 default:
10874 return false;
10875 }
10876
Greg Claytonc07d4512011-04-26 23:48:45 +000010877 RegisterInfo base_reg;
10878 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010879
10880 uint32_t Rn = ReadCoreReg (n, &success);
10881 if (!success)
10882 return false;
10883
10884 // address = if add then R[n] else R[n]-imm32;
10885 addr_t address;
10886 if (add)
10887 address = Rn;
10888 else
10889 address = Rn - imm32;
10890
10891 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +000010892 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010893 if (wback)
10894 {
10895 uint32_t value;
10896 if (add)
10897 value = Rn + imm32;
10898 else
10899 value = Rn - imm32;
10900
10901 context.type = eContextAdjustBaseRegister;
10902 context.SetRegisterPlusOffset (base_reg, value - Rn);
10903
10904 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10905 return false;
10906 }
10907
10908 const uint32_t addr_byte_size = GetAddressByteSize();
10909 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10910
10911 context.type = eContextRegisterStore;
10912 // for r = 0 to regs-1
10913 for (int r = 0; r < regs; ++r)
10914 {
Greg Claytonc07d4512011-04-26 23:48:45 +000010915
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010916 if (single_regs)
10917 {
10918 // MemA[address,4] = S[d+r]; address = address+4;
10919 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10920 if (!success)
10921 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010922
10923 RegisterInfo data_reg;
10924 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010925 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10926 if (!MemAWrite (context, address, data, addr_byte_size))
10927 return false;
10928
10929 address = address + 4;
10930 }
10931 else
10932 {
10933 // // Store as two word-aligned words in the correct order for current endianness.
10934 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10935 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10936 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10937 if (!success)
10938 return false;
10939
Greg Claytonc07d4512011-04-26 23:48:45 +000010940 RegisterInfo data_reg;
10941 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010942
Greg Clayton888a7332011-04-26 04:39:08 +000010943 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010944 {
10945 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10946 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10947 return false;
10948
10949 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10950 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10951 return false;
10952 }
10953 else
10954 {
10955 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10956 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10957 return false;
10958
10959 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10960 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10961 return false;
10962 }
10963 // address = address+8;
10964 address = address + 8;
10965 }
10966 }
10967 }
10968 return true;
10969}
10970
Caroline Tice917ad352011-03-31 05:05:30 +000010971// A8.6.320
10972// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10973// an optional offset.
10974bool
10975EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10976{
10977#if 0
10978 if ConditionPassed() then
10979 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10980 base = if n == 15 then Align(PC,4) else R[n];
10981 address = if add then (base + imm32) else (base - imm32);
10982 if single_reg then
10983 S[d] = MemA[address,4];
10984 else
10985 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10986 // Combine the word-aligned words in the correct order for current endianness.
10987 D[d] = if BigEndian() then word1:word2 else word2:word1;
10988#endif
10989
10990 bool success = false;
10991
10992 if (ConditionPassed (opcode))
10993 {
10994 bool single_reg;
10995 bool add;
10996 uint32_t imm32;
10997 uint32_t d;
10998 uint32_t n;
10999
11000 switch (encoding)
11001 {
11002 case eEncodingT1:
11003 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011004 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000011005 single_reg = false;
11006 add = BitIsSet (opcode, 23);
11007 imm32 = Bits32 (opcode, 7, 0) << 2;
11008
11009 // d = UInt(D:Vd); n = UInt(Rn);
11010 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11011 n = Bits32 (opcode, 19, 16);
11012
11013 break;
11014
11015 case eEncodingT2:
11016 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011017 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000011018 single_reg = true;
11019 add = BitIsSet (opcode, 23);
11020 imm32 = Bits32 (opcode, 7, 0) << 2;
11021
11022 // d = UInt(Vd:D); n = UInt(Rn);
11023 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11024 n = Bits32 (opcode, 19, 16);
11025
11026 break;
11027
11028 default:
11029 return false;
11030 }
Greg Claytonc07d4512011-04-26 23:48:45 +000011031 RegisterInfo base_reg;
11032 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice917ad352011-03-31 05:05:30 +000011033
11034 uint32_t Rn = ReadCoreReg (n, &success);
11035 if (!success)
11036 return false;
11037
11038 // base = if n == 15 then Align(PC,4) else R[n];
11039 uint32_t base;
11040 if (n == 15)
11041 base = AlignPC (Rn);
11042 else
11043 base = Rn;
11044
11045 // address = if add then (base + imm32) else (base - imm32);
11046 addr_t address;
11047 if (add)
11048 address = base + imm32;
11049 else
11050 address = base - imm32;
11051
11052 const uint32_t addr_byte_size = GetAddressByteSize();
11053 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11054
11055 EmulateInstruction::Context context;
11056 context.type = eContextRegisterLoad;
11057 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000011058
Caroline Tice917ad352011-03-31 05:05:30 +000011059 if (single_reg)
11060 {
11061 // S[d] = MemA[address,4];
11062 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
11063 if (!success)
11064 return false;
11065
11066 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
11067 return false;
11068 }
11069 else
11070 {
11071 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11072 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
11073 if (!success)
11074 return false;
11075
11076 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
11077 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
11078 if (!success)
11079 return false;
11080 // // Combine the word-aligned words in the correct order for current endianness.
11081 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11082 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000011083 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000011084 {
11085 data64 = word1;
11086 data64 = (data64 << 32) | word2;
11087 }
11088 else
11089 {
11090 data64 = word2;
11091 data64 = (data64 << 32) | word1;
11092 }
11093
11094 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
11095 return false;
11096 }
11097 }
11098 return true;
11099}
Caroline Tice424652f2011-03-31 05:38:36 +000011100
11101// A8.6.400 VSTR
11102// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
11103// optional offset.
11104bool
11105EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
11106{
11107#if 0
11108 if ConditionPassed() then
11109 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11110 address = if add then (R[n] + imm32) else (R[n] - imm32);
11111 if single_reg then
11112 MemA[address,4] = S[d];
11113 else
11114 // Store as two word-aligned words in the correct order for current endianness.
11115 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11116 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11117#endif
11118
11119 bool success = false;
11120
11121 if (ConditionPassed (opcode))
11122 {
11123 bool single_reg;
11124 bool add;
11125 uint32_t imm32;
11126 uint32_t d;
11127 uint32_t n;
11128
11129 switch (encoding)
11130 {
11131 case eEncodingT1:
11132 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011133 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011134 single_reg = false;
11135 add = BitIsSet (opcode, 23);
11136 imm32 = Bits32 (opcode, 7, 0) << 2;
11137
11138 // d = UInt(D:Vd); n = UInt(Rn);
11139 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11140 n = Bits32 (opcode, 19, 16);
11141
11142 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11143 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11144 return false;
11145
11146 break;
11147
11148 case eEncodingT2:
11149 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011150 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011151 single_reg = true;
11152 add = BitIsSet (opcode, 23);
11153 imm32 = Bits32 (opcode, 7, 0) << 2;
11154
11155 // d = UInt(Vd:D); n = UInt(Rn);
11156 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11157 n = Bits32 (opcode, 19, 16);
11158
11159 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11160 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11161 return false;
11162
11163 break;
11164
11165 default:
11166 return false;
11167 }
11168
Greg Claytonc07d4512011-04-26 23:48:45 +000011169 RegisterInfo base_reg;
11170 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011171
11172 uint32_t Rn = ReadCoreReg (n, &success);
11173 if (!success)
11174 return false;
11175
11176 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11177 addr_t address;
11178 if (add)
11179 address = Rn + imm32;
11180 else
11181 address = Rn - imm32;
11182
11183 const uint32_t addr_byte_size = GetAddressByteSize();
11184 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11185
Greg Claytonc07d4512011-04-26 23:48:45 +000011186 RegisterInfo data_reg;
11187 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011188 EmulateInstruction::Context context;
11189 context.type = eContextRegisterStore;
11190 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11191
11192 if (single_reg)
11193 {
11194 // MemA[address,4] = S[d];
11195 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11196 if (!success)
11197 return false;
11198
11199 if (!MemAWrite (context, address, data, addr_byte_size))
11200 return false;
11201 }
11202 else
11203 {
11204 // // Store as two word-aligned words in the correct order for current endianness.
11205 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11206 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11207 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11208 if (!success)
11209 return false;
11210
Greg Clayton888a7332011-04-26 04:39:08 +000011211 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011212 {
11213 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11214 return false;
11215
11216 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11217 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11218 return false;
11219 }
11220 else
11221 {
11222 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11223 return false;
11224
11225 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11226 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11227 return false;
11228 }
11229 }
11230 }
11231 return true;
11232}
Caroline Tice9121b352011-03-31 16:41:19 +000011233
11234// A8.6.307 VLDI1 (multiple single elements)
11235// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11236// element of each register is loaded.
11237bool
11238EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11239{
11240#if 0
11241 if ConditionPassed() then
11242 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11243 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11244 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11245 for r = 0 to regs-1
11246 for e = 0 to elements-1
11247 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11248 address = address + ebytes;
11249#endif
11250
11251 bool success = false;
11252
11253 if (ConditionPassed (opcode))
11254 {
11255 uint32_t regs;
11256 uint32_t alignment;
11257 uint32_t ebytes;
11258 uint32_t esize;
11259 uint32_t elements;
11260 uint32_t d;
11261 uint32_t n;
11262 uint32_t m;
11263 bool wback;
11264 bool register_index;
11265
11266 switch (encoding)
11267 {
11268 case eEncodingT1:
11269 case eEncodingA1:
11270 {
11271 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011272 // when Ô0111Õ
11273 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
11274 // when Ô1010Õ
11275 // regs = 2; if align == Ô11Õ then UNDEFINED;
11276 // when Ô0110Õ
11277 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
11278 // when Ô0010Õ
Caroline Tice9121b352011-03-31 16:41:19 +000011279 // regs = 4;
11280 // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011281 // SEE ÒRelated encodingsÓ;
Caroline Tice9121b352011-03-31 16:41:19 +000011282 uint32_t type = Bits32 (opcode, 11, 8);
11283 uint32_t align = Bits32 (opcode, 5, 4);
11284 if (type == 7) // '0111'
11285 {
11286 regs = 1;
11287 if (BitIsSet (align, 1))
11288 return false;
11289 }
11290 else if (type == 10) // '1010'
11291 {
11292 regs = 2;
11293 if (align == 3)
11294 return false;
11295
11296 }
11297 else if (type == 6) // '0110'
11298 {
11299 regs = 3;
11300 if (BitIsSet (align, 1))
11301 return false;
11302 }
11303 else if (type == 2) // '0010'
11304 {
11305 regs = 4;
11306 }
11307 else
11308 return false;
11309
Greg Clayton061b79d2011-05-09 20:18:18 +000011310 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice9121b352011-03-31 16:41:19 +000011311 if (align == 0)
11312 alignment = 1;
11313 else
11314 alignment = 4 << align;
11315
11316 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11317 ebytes = 1 << Bits32 (opcode, 7, 6);
11318 esize = 8 * ebytes;
11319 elements = 8 / ebytes;
11320
11321 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11322 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11323 n = Bits32 (opcode, 19, 15);
11324 m = Bits32 (opcode, 3, 0);
11325
11326 // wback = (m != 15); register_index = (m != 15 && m != 13);
11327 wback = (m != 15);
11328 register_index = ((m != 15) && (m != 13));
11329
11330 // if d+regs > 32 then UNPREDICTABLE;
11331 if ((d + regs) > 32)
11332 return false;
11333 }
11334 break;
11335
11336 default:
11337 return false;
11338 }
11339
Greg Claytonc07d4512011-04-26 23:48:45 +000011340 RegisterInfo base_reg;
11341 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice9121b352011-03-31 16:41:19 +000011342
11343 uint32_t Rn = ReadCoreReg (n, &success);
11344 if (!success)
11345 return false;
11346
11347 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11348 addr_t address = Rn;
11349 if ((address % alignment) != 0)
11350 return false;
11351
11352 EmulateInstruction::Context context;
11353 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11354 if (wback)
11355 {
11356 uint32_t Rm = ReadCoreReg (m, &success);
11357 if (!success)
11358 return false;
11359
11360 uint32_t offset;
11361 if (register_index)
11362 offset = Rm;
11363 else
11364 offset = 8 * regs;
11365
11366 uint32_t value = Rn + offset;
11367 context.type = eContextAdjustBaseRegister;
11368 context.SetRegisterPlusOffset (base_reg, offset);
11369
11370 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11371 return false;
11372
11373 }
11374
11375 // for r = 0 to regs-1
11376 for (int r = 0; r < regs; ++r)
11377 {
11378 // for e = 0 to elements-1
11379 uint64_t assembled_data = 0;
11380 for (int e = 0; e < elements; ++e)
11381 {
11382 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11383 context.type = eContextRegisterLoad;
11384 context.SetRegisterPlusOffset (base_reg, address - Rn);
11385 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11386 if (!success)
11387 return false;
11388
11389 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11390
11391 // address = address + ebytes;
11392 address = address + ebytes;
11393 }
11394 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11395 return false;
11396 }
11397 }
11398 return true;
11399}
11400
Caroline Ticeb6281b12011-03-31 17:58:23 +000011401// A8.6.308 VLD1 (single element to one lane)
11402//
11403bool
11404EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11405{
11406#if 0
11407 if ConditionPassed() then
11408 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11409 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11410 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11411 Elem[D[d],index,esize] = MemU[address,ebytes];
11412#endif
11413
11414 bool success = false;
11415
11416 if (ConditionPassed (opcode))
11417 {
11418 uint32_t ebytes;
11419 uint32_t esize;
11420 uint32_t index;
11421 uint32_t alignment;
11422 uint32_t d;
11423 uint32_t n;
11424 uint32_t m;
11425 bool wback;
11426 bool register_index;
11427
11428 switch (encoding)
11429 {
11430 case eEncodingT1:
11431 case eEncodingA1:
11432 {
11433 uint32_t size = Bits32 (opcode, 11, 10);
11434 uint32_t index_align = Bits32 (opcode, 7, 4);
Greg Clayton061b79d2011-05-09 20:18:18 +000011435 // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011436 if (size == 3)
11437 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011438 // case size of
11439 if (size == 0) // when '00'
11440 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011441 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011442 if (BitIsClear (index_align, 0))
11443 return false;
11444
11445 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11446 ebytes = 1;
11447 esize = 8;
11448 index = Bits32 (index_align, 3, 1);
11449 alignment = 1;
11450 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011451 else if (size == 1) // when Ô01Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011452 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011453 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011454 if (BitIsClear (index_align, 1))
11455 return false;
11456
11457 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11458 ebytes = 2;
11459 esize = 16;
11460 index = Bits32 (index_align, 3, 2);
11461
Greg Clayton061b79d2011-05-09 20:18:18 +000011462 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011463 if (BitIsClear (index_align, 0))
11464 alignment = 1;
11465 else
11466 alignment = 2;
11467 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011468 else if (size == 2) // when Ô10Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011469 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011470 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011471 if (BitIsClear (index_align, 2))
11472 return false;
11473
Greg Clayton061b79d2011-05-09 20:18:18 +000011474 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011475 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11476 return false;
11477
11478 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11479 ebytes = 4;
11480 esize = 32;
11481 index = Bit32 (index_align, 3);
11482
Greg Clayton061b79d2011-05-09 20:18:18 +000011483 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011484 if (Bits32 (index_align, 1, 0) == 0)
11485 alignment = 1;
11486 else
11487 alignment = 4;
11488 }
11489 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11490 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11491 n = Bits32 (opcode, 19, 16);
11492 m = Bits32 (opcode, 3, 0);
11493
11494 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11495 wback = (m != 15);
11496 register_index = ((m != 15) && (m != 13));
11497
11498 if (n == 15)
11499 return false;
11500
11501 }
11502 break;
11503
11504 default:
11505 return false;
11506 }
11507
Greg Claytonc07d4512011-04-26 23:48:45 +000011508 RegisterInfo base_reg;
11509 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011510
11511 uint32_t Rn = ReadCoreReg (n, &success);
11512 if (!success)
11513 return false;
11514
11515 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11516 addr_t address = Rn;
11517 if ((address % alignment) != 0)
11518 return false;
11519
11520 EmulateInstruction::Context context;
11521 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11522 if (wback)
11523 {
11524 uint32_t Rm = ReadCoreReg (m, &success);
11525 if (!success)
11526 return false;
11527
11528 uint32_t offset;
11529 if (register_index)
11530 offset = Rm;
11531 else
11532 offset = ebytes;
11533
11534 uint32_t value = Rn + offset;
11535
11536 context.type = eContextAdjustBaseRegister;
11537 context.SetRegisterPlusOffset (base_reg, offset);
11538
11539 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11540 return false;
11541 }
11542
11543 // Elem[D[d],index,esize] = MemU[address,ebytes];
11544 uint32_t element = MemURead (context, address, esize, 0, &success);
11545 if (!success)
11546 return false;
11547
11548 element = element << (index * esize);
11549
11550 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11551 if (!success)
11552 return false;
11553
11554 uint64_t all_ones = -1;
11555 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11556 // at element & to the right of element.
11557 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011558 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 +000011559 // now mask should be 0's where element goes & 1's
11560 // everywhere else.
11561
11562 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11563 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11564
11565 context.type = eContextRegisterLoad;
11566 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11567 return false;
11568 }
11569 return true;
11570}
11571
Caroline Tice1e542e32011-03-31 18:44:04 +000011572// A8.6.391 VST1 (multiple single elements)
11573// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11574// interleaving. Every element of each register is stored.
11575bool
11576EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11577{
11578#if 0
11579 if ConditionPassed() then
11580 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11581 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11582 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11583 for r = 0 to regs-1
11584 for e = 0 to elements-1
11585 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11586 address = address + ebytes;
11587#endif
11588
11589 bool success = false;
11590
11591 if (ConditionPassed (opcode))
11592 {
11593 uint32_t regs;
11594 uint32_t alignment;
11595 uint32_t ebytes;
11596 uint32_t esize;
11597 uint32_t elements;
11598 uint32_t d;
11599 uint32_t n;
11600 uint32_t m;
11601 bool wback;
11602 bool register_index;
11603
11604 switch (encoding)
11605 {
11606 case eEncodingT1:
11607 case eEncodingA1:
11608 {
11609 uint32_t type = Bits32 (opcode, 11, 8);
11610 uint32_t align = Bits32 (opcode, 5, 4);
11611
11612 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011613 if (type == 7) // when Ô0111Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011614 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011615 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011616 regs = 1;
11617 if (BitIsSet (align, 1))
11618 return false;
11619 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011620 else if (type == 10) // when Ô1010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011621 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011622 // regs = 2; if align == Ô11Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011623 regs = 2;
11624 if (align == 3)
11625 return false;
11626 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011627 else if (type == 6) // when Ô0110Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011628 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011629 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011630 regs = 3;
11631 if (BitIsSet (align, 1))
11632 return false;
11633 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011634 else if (type == 2) // when Ô0010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011635 // regs = 4;
11636 regs = 4;
11637 else // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011638 // SEE ÒRelated encodingsÓ;
Caroline Tice1e542e32011-03-31 18:44:04 +000011639 return false;
11640
Greg Clayton061b79d2011-05-09 20:18:18 +000011641 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice1e542e32011-03-31 18:44:04 +000011642 if (align == 0)
Johnny Chena1c7e462011-08-12 17:59:58 +000011643 alignment = 1;
Caroline Tice1e542e32011-03-31 18:44:04 +000011644 else
11645 alignment = 4 << align;
11646
11647 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11648 ebytes = 1 << Bits32 (opcode,7, 6);
11649 esize = 8 * ebytes;
11650 elements = 8 / ebytes;
11651
11652 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11653 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11654 n = Bits32 (opcode, 19, 16);
11655 m = Bits32 (opcode, 3, 0);
11656
11657 // wback = (m != 15); register_index = (m != 15 && m != 13);
11658 wback = (m != 15);
11659 register_index = ((m != 15) && (m != 13));
11660
11661 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11662 if ((d + regs) > 32)
11663 return false;
11664
11665 if (n == 15)
11666 return false;
11667
11668 }
11669 break;
11670
11671 default:
11672 return false;
11673 }
11674
Greg Claytonc07d4512011-04-26 23:48:45 +000011675 RegisterInfo base_reg;
11676 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011677
11678 uint32_t Rn = ReadCoreReg (n, &success);
11679 if (!success)
11680 return false;
11681
11682 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11683 addr_t address = Rn;
11684 if ((address % alignment) != 0)
11685 return false;
11686
11687 EmulateInstruction::Context context;
11688 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11689 if (wback)
11690 {
11691 uint32_t Rm = ReadCoreReg (m, &success);
11692 if (!success)
11693 return false;
11694
11695 uint32_t offset;
11696 if (register_index)
11697 offset = Rm;
11698 else
11699 offset = 8 * regs;
11700
11701 context.type = eContextAdjustBaseRegister;
11702 context.SetRegisterPlusOffset (base_reg, offset);
11703
11704 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11705 return false;
11706 }
11707
Greg Claytonc07d4512011-04-26 23:48:45 +000011708 RegisterInfo data_reg;
Caroline Tice1e542e32011-03-31 18:44:04 +000011709 context.type = eContextRegisterStore;
Caroline Tice1e542e32011-03-31 18:44:04 +000011710 // for r = 0 to regs-1
11711 for (int r = 0; r < regs; ++r)
11712 {
Greg Claytonc07d4512011-04-26 23:48:45 +000011713 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011714 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11715 if (!success)
11716 return false;
11717
11718 // for e = 0 to elements-1
11719 for (int e = 0; e < elements; ++e)
11720 {
11721 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011722 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011723
11724 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11725 if (!MemUWrite (context, address, word, ebytes))
11726 return false;
11727
11728 // address = address + ebytes;
11729 address = address + ebytes;
11730 }
11731 }
11732 }
11733 return true;
11734}
11735
Caroline Tice7b880942011-03-31 19:17:12 +000011736// A8.6.392 VST1 (single element from one lane)
11737// This instruction stores one element to memory from one element of a register.
11738bool
11739EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11740{
11741#if 0
11742 if ConditionPassed() then
11743 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11744 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11745 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11746 MemU[address,ebytes] = Elem[D[d],index,esize];
11747#endif
11748
11749 bool success = false;
11750
11751 if (ConditionPassed (opcode))
11752 {
11753 uint32_t ebytes;
11754 uint32_t esize;
11755 uint32_t index;
11756 uint32_t alignment;
11757 uint32_t d;
11758 uint32_t n;
11759 uint32_t m;
11760 bool wback;
11761 bool register_index;
11762
11763 switch (encoding)
11764 {
11765 case eEncodingT1:
11766 case eEncodingA1:
11767 {
11768 uint32_t size = Bits32 (opcode, 11, 10);
11769 uint32_t index_align = Bits32 (opcode, 7, 4);
11770
Greg Clayton061b79d2011-05-09 20:18:18 +000011771 // if size == Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011772 if (size == 3)
11773 return false;
11774
11775 // case size of
Greg Clayton061b79d2011-05-09 20:18:18 +000011776 if (size == 0) // when Ô00Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011777 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011778 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011779 if (BitIsClear (index_align, 0))
11780 return false;
11781 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11782 ebytes = 1;
11783 esize = 8;
11784 index = Bits32 (index_align, 3, 1);
11785 alignment = 1;
11786 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011787 else if (size == 1) // when Ô01Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011788 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011789 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011790 if (BitIsClear (index_align, 1))
11791 return false;
11792
11793 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11794 ebytes = 2;
11795 esize = 16;
11796 index = Bits32 (index_align, 3, 2);
11797
Greg Clayton061b79d2011-05-09 20:18:18 +000011798 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Tice7b880942011-03-31 19:17:12 +000011799 if (BitIsClear (index_align, 0))
11800 alignment = 1;
11801 else
11802 alignment = 2;
11803 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011804 else if (size == 2) // when Ô10Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011805 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011806 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011807 if (BitIsClear (index_align, 2))
11808 return false;
11809
Greg Clayton061b79d2011-05-09 20:18:18 +000011810 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011811 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11812 return false;
11813
11814 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11815 ebytes = 4;
11816 esize = 32;
11817 index = Bit32 (index_align, 3);
11818
Greg Clayton061b79d2011-05-09 20:18:18 +000011819 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Tice7b880942011-03-31 19:17:12 +000011820 if (Bits32 (index_align, 1, 0) == 0)
11821 alignment = 1;
11822 else
11823 alignment = 4;
11824 }
11825 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11826 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11827 n = Bits32 (opcode, 19, 16);
11828 m = Bits32 (opcode, 3, 0);
11829
11830 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11831 wback = (m != 15);
11832 register_index = ((m != 15) && (m != 13));
11833
11834 if (n == 15)
11835 return false;
11836 }
11837 break;
11838
11839 default:
11840 return false;
11841 }
11842
Greg Claytonc07d4512011-04-26 23:48:45 +000011843 RegisterInfo base_reg;
11844 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011845
11846 uint32_t Rn = ReadCoreReg (n, &success);
11847 if (!success)
11848 return false;
11849
11850 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11851 addr_t address = Rn;
11852 if ((address % alignment) != 0)
11853 return false;
11854
11855 EmulateInstruction::Context context;
11856 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11857 if (wback)
11858 {
11859 uint32_t Rm = ReadCoreReg (m, &success);
11860 if (!success)
11861 return false;
11862
11863 uint32_t offset;
11864 if (register_index)
11865 offset = Rm;
11866 else
11867 offset = ebytes;
11868
11869 context.type = eContextAdjustBaseRegister;
11870 context.SetRegisterPlusOffset (base_reg, offset);
11871
11872 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11873 return false;
11874 }
11875
11876 // MemU[address,ebytes] = Elem[D[d],index,esize];
11877 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11878 if (!success)
11879 return false;
11880
11881 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11882
Greg Claytonc07d4512011-04-26 23:48:45 +000011883 RegisterInfo data_reg;
11884 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011885 context.type = eContextRegisterStore;
11886 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11887
11888 if (!MemUWrite (context, address, word, ebytes))
11889 return false;
11890 }
11891 return true;
11892}
11893
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011894// A8.6.309 VLD1 (single element to all lanes)
11895// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011896bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011897EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011898{
11899#if 0
11900 if ConditionPassed() then
11901 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11902 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11903 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11904 replicated_element = Replicate(MemU[address,ebytes], elements);
11905 for r = 0 to regs-1
11906 D[d+r] = replicated_element;
11907#endif
11908
11909 bool success = false;
11910
11911 if (ConditionPassed (opcode))
11912 {
11913 uint32_t ebytes;
11914 uint32_t elements;
11915 uint32_t regs;
11916 uint32_t alignment;
11917 uint32_t d;
11918 uint32_t n;
11919 uint32_t m;
11920 bool wback;
11921 bool register_index;
11922
11923 switch (encoding)
11924 {
11925 case eEncodingT1:
11926 case eEncodingA1:
11927 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011928 //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
Caroline Tice93767b82011-03-31 21:15:29 +000011929 uint32_t size = Bits32 (opcode, 7, 6);
11930 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11931 return false;
11932
Greg Clayton061b79d2011-05-09 20:18:18 +000011933 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
Caroline Tice93767b82011-03-31 21:15:29 +000011934 ebytes = 1 << size;
11935 elements = 8 / ebytes;
11936 if (BitIsClear (opcode, 5))
11937 regs = 1;
11938 else
11939 regs = 2;
11940
Greg Clayton061b79d2011-05-09 20:18:18 +000011941 //alignment = if a == Ô0Õ then 1 else ebytes;
Caroline Tice93767b82011-03-31 21:15:29 +000011942 if (BitIsClear (opcode, 4))
11943 alignment = 1;
11944 else
11945 alignment = ebytes;
11946
11947 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11948 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11949 n = Bits32 (opcode, 19, 16);
11950 m = Bits32 (opcode, 3, 0);
11951
11952 //wback = (m != 15); register_index = (m != 15 && m != 13);
11953 wback = (m != 15);
11954 register_index = ((m != 15) && (m != 13));
11955
11956 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11957 if ((d + regs) > 32)
11958 return false;
11959
11960 if (n == 15)
11961 return false;
11962 }
Johnny Chen6ac9e542011-08-16 01:16:02 +000011963 break;
Caroline Tice93767b82011-03-31 21:15:29 +000011964
11965 default:
Johnny Chen6ac9e542011-08-16 01:16:02 +000011966 return false;
Caroline Tice93767b82011-03-31 21:15:29 +000011967 }
11968
Greg Claytonc07d4512011-04-26 23:48:45 +000011969 RegisterInfo base_reg;
11970 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice93767b82011-03-31 21:15:29 +000011971
11972 uint32_t Rn = ReadCoreReg (n, &success);
11973 if (!success)
11974 return false;
11975
11976 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11977 addr_t address = Rn;
11978 if ((address % alignment) != 0)
11979 return false;
11980
11981 EmulateInstruction::Context context;
11982 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11983 if (wback)
11984 {
11985 uint32_t Rm = ReadCoreReg (m, &success);
11986 if (!success)
11987 return false;
11988
11989 uint32_t offset;
11990 if (register_index)
11991 offset = Rm;
11992 else
11993 offset = ebytes;
11994
11995 context.type = eContextAdjustBaseRegister;
11996 context.SetRegisterPlusOffset (base_reg, offset);
11997
11998 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11999 return false;
12000 }
12001
12002 // replicated_element = Replicate(MemU[address,ebytes], elements);
12003
12004 context.type = eContextRegisterLoad;
12005 uint64_t word = MemURead (context, address, ebytes, 0, &success);
12006 if (!success)
12007 return false;
12008
Johnny Chen65f39ed2011-08-12 01:10:45 +000012009 uint64_t replicated_element = 0;
Caroline Tice93767b82011-03-31 21:15:29 +000012010 uint32_t esize = ebytes * 8;
12011 for (int e = 0; e < elements; ++e)
12012 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
12013
12014 // for r = 0 to regs-1
12015 for (int r = 0; r < regs; ++r)
12016 {
12017 // D[d+r] = replicated_element;
12018 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
12019 return false;
12020 }
12021 }
12022 return true;
12023}
12024
Caroline Tice1f954f52011-04-11 15:51:10 +000012025// B6.2.13 SUBS PC, LR and related instructions
12026//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
12027// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
12028bool
12029EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
12030{
12031#if 0
12032 if ConditionPassed() then
12033 EncodingSpecificOperations();
12034 if CurrentInstrSet() == InstrSet_ThumbEE then
12035 UNPREDICTABLE;
12036 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12037 case opcode of
Greg Clayton061b79d2011-05-09 20:18:18 +000012038 when Ô0000Õ result = R[n] AND operand2; // AND
12039 when Ô0001Õ result = R[n] EOR operand2; // EOR
12040 when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
12041 when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
12042 when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
12043 when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12044 when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12045 when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12046 when Ô1100Õ result = R[n] OR operand2; // ORR
12047 when Ô1101Õ result = operand2; // MOV
12048 when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
12049 when Ô1111Õ result = NOT(operand2); // MVN
12050 CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012051 BranchWritePC(result);
12052#endif
12053
12054 bool success = false;
12055
12056 if (ConditionPassed (opcode))
12057 {
12058 uint32_t n;
12059 uint32_t m;
12060 uint32_t imm32;
12061 bool register_form;
12062 ARM_ShifterType shift_t;
12063 uint32_t shift_n;
12064 uint32_t code;
12065
12066 switch (encoding)
12067 {
12068 case eEncodingT1:
12069 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
Greg Clayton061b79d2011-05-09 20:18:18 +000012070 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012071 n = 14;
12072 imm32 = Bits32 (opcode, 7, 0);
12073 register_form = false;
12074 code = 2;
12075
12076 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12077 if (InITBlock() && !LastInITBlock())
12078 return false;
12079
12080 break;
12081
12082 case eEncodingA1:
12083 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12084 n = Bits32 (opcode, 19, 16);
12085 imm32 = ARMExpandImm (opcode);
12086 register_form = false;
12087 code = Bits32 (opcode, 24, 21);
12088
12089 break;
12090
12091 case eEncodingA2:
12092 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12093 n = Bits32 (opcode, 19, 16);
12094 m = Bits32 (opcode, 3, 0);
12095 register_form = true;
12096
12097 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12098 shift_n = DecodeImmShiftARM (opcode, shift_t);
12099
12100 break;
12101
12102 default:
12103 return false;
12104 }
12105
12106 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12107 uint32_t operand2;
12108 if (register_form)
12109 {
12110 uint32_t Rm = ReadCoreReg (m, &success);
12111 if (!success)
12112 return false;
12113
Johnny Chena4438a72011-06-02 22:50:51 +000012114 operand2 = Shift (Rm, shift_t, shift_n, APSR_C, &success);
12115 if (!success)
12116 return false;
Caroline Tice1f954f52011-04-11 15:51:10 +000012117 }
12118 else
12119 {
12120 operand2 = imm32;
12121 }
12122
12123 uint32_t Rn = ReadCoreReg (n, &success);
12124 if (!success)
12125 return false;
12126
12127 AddWithCarryResult result;
12128
12129 // case opcode of
12130 switch (code)
12131 {
Greg Clayton061b79d2011-05-09 20:18:18 +000012132 case 0: // when Ô0000Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012133 // result = R[n] AND operand2; // AND
12134 result.result = Rn & operand2;
12135 break;
12136
Greg Clayton061b79d2011-05-09 20:18:18 +000012137 case 1: // when Ô0001Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012138 // result = R[n] EOR operand2; // EOR
12139 result.result = Rn ^ operand2;
12140 break;
12141
Greg Clayton061b79d2011-05-09 20:18:18 +000012142 case 2: // when Ô0010Õ
12143 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012144 result = AddWithCarry (Rn, ~(operand2), 1);
12145 break;
12146
Greg Clayton061b79d2011-05-09 20:18:18 +000012147 case 3: // when Ô0011Õ
12148 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
Caroline Tice1f954f52011-04-11 15:51:10 +000012149 result = AddWithCarry (~(Rn), operand2, 1);
12150 break;
12151
Greg Clayton061b79d2011-05-09 20:18:18 +000012152 case 4: // when Ô0100Õ
12153 // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
Caroline Tice1f954f52011-04-11 15:51:10 +000012154 result = AddWithCarry (Rn, operand2, 0);
12155 break;
12156
Greg Clayton061b79d2011-05-09 20:18:18 +000012157 case 5: // when Ô0101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012158 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12159 result = AddWithCarry (Rn, operand2, APSR_C);
12160 break;
12161
Greg Clayton061b79d2011-05-09 20:18:18 +000012162 case 6: // when Ô0110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012163 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12164 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12165 break;
12166
Greg Clayton061b79d2011-05-09 20:18:18 +000012167 case 7: // when Ô0111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012168 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12169 result = AddWithCarry (~(Rn), operand2, APSR_C);
12170 break;
12171
Greg Clayton061b79d2011-05-09 20:18:18 +000012172 case 10: // when Ô1100Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012173 // result = R[n] OR operand2; // ORR
12174 result.result = Rn | operand2;
12175 break;
12176
Greg Clayton061b79d2011-05-09 20:18:18 +000012177 case 11: // when Ô1101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012178 // result = operand2; // MOV
12179 result.result = operand2;
12180 break;
12181
Greg Clayton061b79d2011-05-09 20:18:18 +000012182 case 12: // when Ô1110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012183 // result = R[n] AND NOT(operand2); // BIC
12184 result.result = Rn & ~(operand2);
12185 break;
12186
Greg Clayton061b79d2011-05-09 20:18:18 +000012187 case 15: // when Ô1111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012188 // result = NOT(operand2); // MVN
12189 result.result = ~(operand2);
12190 break;
12191
12192 default:
12193 return false;
12194 }
Greg Clayton061b79d2011-05-09 20:18:18 +000012195 // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012196
12197 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12198 // the best.
12199 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12200 if (!success)
12201 return false;
12202
12203 CPSRWriteByInstr (spsr, 15, true);
12204
12205 // BranchWritePC(result);
12206 EmulateInstruction::Context context;
12207 context.type = eContextAdjustPC;
12208 context.SetImmediate (result.result);
12209
12210 BranchWritePC (context, result.result);
12211 }
12212 return true;
12213}
12214
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012215EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012216EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012217{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012218 static ARMOpcode
12219 g_arm_opcodes[] =
12220 {
12221 //----------------------------------------------------------------------
12222 // Prologue instructions
12223 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012224
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012225 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012226 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12227 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012228
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012229 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012230 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12231 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012232 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012233 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12234 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12235 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012236
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012237 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012238 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12239 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012240
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012241 // push one register
12242 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012243 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012244
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012245 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012246 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12247 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012248
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012249 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012250 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012251 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012252
Caroline Tice4f605582011-03-31 00:02:51 +000012253 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12254 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12255 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12256 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012257
12258 //----------------------------------------------------------------------
12259 // Supervisor Call (previously Software Interrupt)
12260 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012261 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012262
12263 //----------------------------------------------------------------------
12264 // Branch instructions
12265 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012266 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012267 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012268 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12269 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12270 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012271 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012272 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012273 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012274 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012275
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012276 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012277 // Data-processing instructions
12278 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012279 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012280 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012281 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012282 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012283 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012284 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012285 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012286 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012287 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012288 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012289 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012290 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12291 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012292 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012293 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012294 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012295 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012296 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012297 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012298 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012299 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012300 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012301 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012302 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012303 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012304 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012305 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012306 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012307 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012308 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012309 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012310 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012311 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012312 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012313 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012314 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012315 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012316 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012317 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012318 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012319 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012320 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012321 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012322 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012323 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012324 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012325 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012326 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012327 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012328 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012329 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012330 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012331 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012332 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012333 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012334
Caroline Tice89c6d582011-03-29 19:53:44 +000012335 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012336 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12337 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012338 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012339 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012340 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012341 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012342 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012343 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012344 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012345 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012346 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012347 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012348 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012349 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012350 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012351 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012352 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012353 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012354 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012355 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012356 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012357 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012358 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012359 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012360 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012361 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012362 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012363 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012364 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012365 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012366 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012367 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012368 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012369 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012370 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012371 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012372
12373 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012374 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12375 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012376
12377 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012378 // Load instructions
12379 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012380 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12381 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12382 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12383 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12384 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12385 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12386 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12387 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12388 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12389 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12390 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12391 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12392 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12393 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12394 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12395 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12396 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12397 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012398 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12399 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12400 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12401 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012402 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12403 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012404 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012405
12406 //----------------------------------------------------------------------
12407 // Store instructions
12408 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012409 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12410 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12411 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12412 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12413 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12414 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12415 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12416 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12417 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012418 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012419 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012420 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12421 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12422 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12423 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12424 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012425 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012426
Caroline Tice6bf65162011-03-03 17:42:58 +000012427 //----------------------------------------------------------------------
12428 // Other instructions
12429 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012430 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12431 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12432 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12433 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12434 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012435
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012436 };
12437 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12438
12439 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12440 {
Greg Clayton888a7332011-04-26 04:39:08 +000012441 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12442 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012443 return &g_arm_opcodes[i];
12444 }
12445 return NULL;
12446}
Greg Clayton64c84432011-01-21 22:02:52 +000012447
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012448
12449EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012450EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012451{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012452
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012453 static ARMOpcode
12454 g_thumb_opcodes[] =
12455 {
12456 //----------------------------------------------------------------------
12457 // Prologue instructions
12458 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012459
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012460 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012461 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12462 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12463 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012464
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012465 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012466 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012467 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012468 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012469 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012470 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012471
Johnny Chen864a8e82011-02-18 00:07:39 +000012472 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012473 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012474
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012475 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012476 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12477 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12478 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12479 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12480 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012481
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012482 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012483 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12484 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012485
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012486 //----------------------------------------------------------------------
12487 // Epilogue instructions
12488 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012489
Caroline Tice4f605582011-03-31 00:02:51 +000012490 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12491 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12492 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12493 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12494 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12495 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12496 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012497
12498 //----------------------------------------------------------------------
12499 // Supervisor Call (previously Software Interrupt)
12500 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012501 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012502
12503 //----------------------------------------------------------------------
12504 // If Then makes up to four following instructions conditional.
12505 //----------------------------------------------------------------------
Greg Clayton04d397c2011-05-23 18:04:09 +000012506 // The next 5 opcode _must_ come before the if then instruction
12507 { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"},
12508 { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
12509 { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
12510 { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
12511 { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
12512 { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012513
12514 //----------------------------------------------------------------------
12515 // Branch instructions
12516 //----------------------------------------------------------------------
12517 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012518 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12519 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12520 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12521 { 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 +000012522 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012523 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012524 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012525 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12526 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012527 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012528 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012529 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012530 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012531 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012532 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012533 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012534 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012535 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012536 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012537
12538 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012539 // Data-processing instructions
12540 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012541 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012542 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012543 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012544 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12545 { 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 +000012546 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012547 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012548 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012549 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012550 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012551 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12552 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12553 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012554 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012555 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012556 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012557 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12558 { 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 +000012559 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012560 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012561 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012562 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12563 { 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 +000012564 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012565 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012566 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012567 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12568 { 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 +000012569 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012570 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012571 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012572 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12573 { 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 +000012574 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012575 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12576 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012577 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012578 { 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 +000012579 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012580 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012581 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012582 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12583 { 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 +000012584 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012585 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12586 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12587 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12588 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012589 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012590 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12591 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12592 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12593 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012594 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012595 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12596 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012597 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012598 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12599 { 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 +000012600 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012601 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012602 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012603 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012604 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012605 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012606 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012607 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12608 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012609
Johnny Chen7c5234d2011-02-18 23:41:11 +000012610
Johnny Chen338bf542011-02-10 19:29:03 +000012611 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012612 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012613 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012614 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012615 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012616 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012617 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012618 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12619 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12620 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012621 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012622 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012623 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012624 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12625 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012626 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012627 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012628 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012629 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12630 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012631 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012632 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12633 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012634 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012635 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012636 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012637 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012638 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012639 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12640 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012641 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012642 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12643 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012644 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012645 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12646 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012647 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012648 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12649 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012650 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012651 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12652 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012653 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012654 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12655 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012656 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012657 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012658 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012659 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012660 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012661 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12662 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012663 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012664 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012665 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012666 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012667
12668 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012669 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012670
12671 //----------------------------------------------------------------------
12672 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12673 // otherwise the wrong instructions will be selected.
12674 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012675
Caroline Tice080bf612011-04-05 18:46:00 +000012676 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12677 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12678
Johnny Chen26863dc2011-02-09 23:43:29 +000012679 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012680 // Load instructions
12681 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012682 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12683 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12684 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12685 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12686 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12687 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12688 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012689 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012690 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12691 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12692 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12693 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12694 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012695 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012696 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12697 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12698 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12699 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12700 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12701 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12702 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12703 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12704 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12705 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12706 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12707 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12708 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12709 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12710 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12711 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12712 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12713 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12714 { 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 +000012715 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012716 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12717 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12718 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12719 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012720 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12721 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012722 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012723
12724 //----------------------------------------------------------------------
12725 // Store instructions
12726 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012727 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12728 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12729 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12730 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12731 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12732 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12733 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12734 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12735 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12736 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12737 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12738 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12739 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12740 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12741 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12742 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012743 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12744 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12745 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12746 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12747 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012748 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012749
12750 //----------------------------------------------------------------------
12751 // Other instructions
12752 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012753 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12754 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12755 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12756 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12757 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12758 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12759 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12760 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012761 };
12762
12763 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12764 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12765 {
Greg Clayton888a7332011-04-26 04:39:08 +000012766 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12767 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012768 return &g_thumb_opcodes[i];
12769 }
12770 return NULL;
12771}
Greg Clayton64c84432011-01-21 22:02:52 +000012772
Greg Clayton31e2a382011-01-30 20:03:56 +000012773bool
Greg Clayton395fc332011-02-15 21:59:32 +000012774EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012775{
Caroline Tice080bf612011-04-05 18:46:00 +000012776 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012777 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012778 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012779 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012780 {
Greg Clayton395fc332011-02-15 21:59:32 +000012781 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12782 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12783 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12784 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12785 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12786 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12787 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12788 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12789 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12790 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Johnny Chen1d29a852011-04-26 18:51:57 +000012791 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12792 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
Greg Clayton31e2a382011-01-30 20:03:56 +000012793 }
12794 return m_arm_isa != 0;
12795}
12796
Caroline Tice080bf612011-04-05 18:46:00 +000012797bool
Greg Clayton888a7332011-04-26 04:39:08 +000012798EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012799{
Greg Clayton888a7332011-04-26 04:39:08 +000012800 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12801 {
12802 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12803 m_opcode_mode = eModeThumb;
12804 else
12805 {
12806 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012807
Greg Clayton888a7332011-04-26 04:39:08 +000012808 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12809 m_opcode_mode = eModeARM;
12810 else if (addr_class == eAddressClassCodeAlternateISA)
12811 m_opcode_mode = eModeThumb;
12812 else
12813 return false;
12814 }
12815 if (m_opcode_mode == eModeThumb)
12816 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12817 else
12818 m_opcode_cpsr = CPSR_MODE_USR;
12819 return true;
12820 }
12821 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012822}
Greg Clayton31e2a382011-01-30 20:03:56 +000012823
Greg Clayton64c84432011-01-21 22:02:52 +000012824bool
12825EmulateInstructionARM::ReadInstruction ()
12826{
12827 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012828 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012829 if (success)
12830 {
12831 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12832 if (success)
12833 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012834 Context read_inst_context;
12835 read_inst_context.type = eContextReadOpcode;
12836 read_inst_context.SetNoArgs ();
12837
Greg Claytonb3448432011-03-24 21:19:54 +000012838 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012839 {
Greg Claytonb3448432011-03-24 21:19:54 +000012840 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012841 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012842
12843 if (success)
12844 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012845 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012846 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012847 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012848 }
12849 else
12850 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012851 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012852 }
12853 }
12854 }
12855 else
12856 {
Greg Claytonb3448432011-03-24 21:19:54 +000012857 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012858 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012859 }
12860 }
12861 }
12862 if (!success)
12863 {
Greg Claytonb3448432011-03-24 21:19:54 +000012864 m_opcode_mode = eModeInvalid;
Greg Clayton3063c952011-04-29 22:50:31 +000012865 m_addr = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012866 }
12867 return success;
12868}
12869
Johnny Chenee9b1f72011-02-09 01:00:31 +000012870uint32_t
12871EmulateInstructionARM::ArchVersion ()
12872{
12873 return m_arm_isa;
12874}
12875
Greg Clayton64c84432011-01-21 22:02:52 +000012876bool
Greg Clayton107e53d2011-07-06 04:07:21 +000012877EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional)
Greg Clayton64c84432011-01-21 22:02:52 +000012878{
Greg Clayton888a7332011-04-26 04:39:08 +000012879 // If we are ignoring conditions, then always return true.
12880 // this allows us to iterate over disassembly code and still
12881 // emulate an instruction even if we don't have all the right
12882 // bits set in the CPSR register...
12883 if (m_ignore_conditions)
12884 return true;
Greg Clayton107e53d2011-07-06 04:07:21 +000012885
12886 if (is_conditional)
12887 *is_conditional = true;
Greg Clayton64c84432011-01-21 22:02:52 +000012888
Greg Clayton7bc39082011-03-24 23:53:38 +000012889 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012890
12891 if (cond == UINT32_MAX)
12892 return false;
12893
12894 bool result = false;
12895 switch (UnsignedBits(cond, 3, 1))
12896 {
Caroline Tice080bf612011-04-05 18:46:00 +000012897 case 0:
12898 if (m_opcode_cpsr == 0)
Greg Clayton107e53d2011-07-06 04:07:21 +000012899 result = true;
12900 else
12901 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
Caroline Tice080bf612011-04-05 18:46:00 +000012902 break;
12903 case 1:
Greg Clayton107e53d2011-07-06 04:07:21 +000012904 if (m_opcode_cpsr == 0)
12905 result = true;
12906 else
12907 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
Caroline Tice080bf612011-04-05 18:46:00 +000012908 break;
12909 case 2:
Greg Clayton107e53d2011-07-06 04:07:21 +000012910 if (m_opcode_cpsr == 0)
12911 result = true;
12912 else
12913 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
Caroline Tice080bf612011-04-05 18:46:00 +000012914 break;
12915 case 3:
Greg Clayton107e53d2011-07-06 04:07:21 +000012916 if (m_opcode_cpsr == 0)
12917 result = true;
12918 else
12919 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
Caroline Tice080bf612011-04-05 18:46:00 +000012920 break;
12921 case 4:
Greg Clayton107e53d2011-07-06 04:07:21 +000012922 if (m_opcode_cpsr == 0)
12923 result = true;
12924 else
12925 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Caroline Tice080bf612011-04-05 18:46:00 +000012926 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012927 case 5:
Greg Clayton107e53d2011-07-06 04:07:21 +000012928 if (m_opcode_cpsr == 0)
12929 result = true;
12930 else
Caroline Tice080bf612011-04-05 18:46:00 +000012931 {
Greg Claytonb3448432011-03-24 21:19:54 +000012932 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12933 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012934 result = n == v;
12935 }
12936 break;
12937 case 6:
Greg Clayton107e53d2011-07-06 04:07:21 +000012938 if (m_opcode_cpsr == 0)
12939 result = true;
12940 else
Caroline Tice080bf612011-04-05 18:46:00 +000012941 {
Greg Claytonb3448432011-03-24 21:19:54 +000012942 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12943 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12944 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012945 }
12946 break;
12947 case 7:
Greg Clayton107e53d2011-07-06 04:07:21 +000012948 // Always execute (cond == 0b1110, or the special 0b1111 which gives
12949 // opcodes different meanings, but always means execution happpens.
12950 if (is_conditional)
12951 *is_conditional = false;
Greg Clayton64c84432011-01-21 22:02:52 +000012952 result = true;
12953 break;
12954 }
12955
12956 if (cond & 1)
12957 result = !result;
12958 return result;
12959}
12960
Johnny Chen9ee056b2011-02-08 00:06:35 +000012961uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012962EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012963{
Greg Claytonb3448432011-03-24 21:19:54 +000012964 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012965 {
12966 default:
12967 case eModeInvalid:
12968 break;
12969
12970 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012971 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012972
12973 case eModeThumb:
12974 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12975 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012976 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012977 const uint32_t byte_size = m_opcode.GetByteSize();
12978 if (byte_size == 2)
12979 {
12980 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12981 return Bits32(opcode, 11, 7);
12982 }
Johnny Chen6dc5a1a2011-06-02 23:19:06 +000012983 else if (byte_size == 4)
Greg Clayton7bc39082011-03-24 23:53:38 +000012984 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012985 if (Bits32(opcode, 31, 27) == 0x1e &&
12986 Bits32(opcode, 15, 14) == 0x02 &&
12987 Bits32(opcode, 12, 12) == 0x00 &&
12988 Bits32(opcode, 25, 22) <= 0x0d)
12989 {
12990 return Bits32(opcode, 25, 22);
12991 }
12992 }
Johnny Chen6dc5a1a2011-06-02 23:19:06 +000012993 else
12994 // We have an invalid thumb instruction, let's bail out.
12995 break;
Greg Clayton7bc39082011-03-24 23:53:38 +000012996
12997 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012998 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012999 }
13000 return UINT32_MAX; // Return invalid value
13001}
13002
Johnny Chen9ee056b2011-02-08 00:06:35 +000013003bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000013004EmulateInstructionARM::InITBlock()
13005{
13006 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13007}
13008
13009bool
13010EmulateInstructionARM::LastInITBlock()
13011{
13012 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13013}
13014
Caroline Ticeb27771d2011-03-03 22:37:46 +000013015bool
13016EmulateInstructionARM::BadMode (uint32_t mode)
13017{
13018
13019 switch (mode)
13020 {
13021 case 16: return false; // '10000'
13022 case 17: return false; // '10001'
13023 case 18: return false; // '10010'
13024 case 19: return false; // '10011'
13025 case 22: return false; // '10110'
13026 case 23: return false; // '10111'
13027 case 27: return false; // '11011'
13028 case 31: return false; // '11111'
13029 default: return true;
13030 }
13031 return true;
13032}
13033
13034bool
13035EmulateInstructionARM::CurrentModeIsPrivileged ()
13036{
Greg Claytonb3448432011-03-24 21:19:54 +000013037 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000013038
13039 if (BadMode (mode))
13040 return false;
13041
13042 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000013043 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000013044
13045 return true;
13046}
13047
13048void
13049EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
13050{
13051 bool privileged = CurrentModeIsPrivileged();
13052
Johnny Chen65f39ed2011-08-12 01:10:45 +000013053 uint32_t tmp_cpsr = Bits32 (m_opcode_cpsr, 23, 20) << 20;
Caroline Ticeb27771d2011-03-03 22:37:46 +000013054
13055 if (BitIsSet (bytemask, 3))
13056 {
13057 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
13058 if (affect_execstate)
13059 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
13060 }
13061
13062 if (BitIsSet (bytemask, 2))
13063 {
13064 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
13065 }
13066
13067 if (BitIsSet (bytemask, 1))
13068 {
13069 if (affect_execstate)
13070 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
13071 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
13072 if (privileged)
13073 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
13074 }
13075
13076 if (BitIsSet (bytemask, 0))
13077 {
13078 if (privileged)
13079 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
13080 if (affect_execstate)
13081 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
13082 if (privileged)
13083 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
13084 }
13085
Greg Claytonb3448432011-03-24 21:19:54 +000013086 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000013087}
13088
13089
Johnny Chen098ae2d2011-02-12 00:50:05 +000013090bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000013091EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
13092{
13093 addr_t target;
13094
Johnny Chenee9b1f72011-02-09 01:00:31 +000013095 // Check the current instruction set.
13096 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013097 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013098 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000013099 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013100
Johnny Chen9ee056b2011-02-08 00:06:35 +000013101 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013102 return false;
13103
13104 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013105}
13106
13107// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
13108bool
Johnny Chen668b4512011-02-15 21:08:58 +000013109EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013110{
13111 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000013112 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
13113 // we want to record it and issue a WriteRegister callback so the clients
13114 // can track the mode changes accordingly.
13115 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013116
13117 if (BitIsSet(addr, 0))
13118 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013119 if (CurrentInstrSet() != eModeThumb)
13120 {
13121 SelectInstrSet(eModeThumb);
13122 cpsr_changed = true;
13123 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013124 target = addr & 0xfffffffe;
Greg Claytonc07d4512011-04-26 23:48:45 +000013125 context.SetISA (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013126 }
13127 else if (BitIsClear(addr, 1))
13128 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013129 if (CurrentInstrSet() != eModeARM)
13130 {
13131 SelectInstrSet(eModeARM);
13132 cpsr_changed = true;
13133 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013134 target = addr & 0xfffffffc;
Greg Claytonc07d4512011-04-26 23:48:45 +000013135 context.SetISA (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013136 }
13137 else
13138 return false; // address<1:0> == '10' => UNPREDICTABLE
13139
Johnny Chen0f309db2011-02-09 19:11:32 +000013140 if (cpsr_changed)
13141 {
Johnny Chen558133b2011-02-09 23:59:17 +000013142 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000013143 return false;
13144 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013145 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013146 return false;
13147
13148 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013149}
Greg Clayton64c84432011-01-21 22:02:52 +000013150
Johnny Chenee9b1f72011-02-09 01:00:31 +000013151// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13152bool
Johnny Chen668b4512011-02-15 21:08:58 +000013153EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000013154{
13155 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000013156 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000013157 else
13158 return BranchWritePC((const Context)context, addr);
13159}
13160
Johnny Chen26863dc2011-02-09 23:43:29 +000013161// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13162bool
Johnny Chen668b4512011-02-15 21:08:58 +000013163EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000013164{
13165 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013166 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013167 else
13168 return BranchWritePC((const Context)context, addr);
13169}
13170
Johnny Chenee9b1f72011-02-09 01:00:31 +000013171EmulateInstructionARM::Mode
13172EmulateInstructionARM::CurrentInstrSet ()
13173{
Greg Claytonb3448432011-03-24 21:19:54 +000013174 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013175}
13176
Greg Claytonb3448432011-03-24 21:19:54 +000013177// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013178// ReadInstruction() is performed. This function has a side effect of updating
13179// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013180bool
13181EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13182{
Greg Claytonb3448432011-03-24 21:19:54 +000013183 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013184 switch (arm_or_thumb)
13185 {
13186 default:
13187 return false;
Greg Claytonb5169392011-10-31 23:51:19 +000013188 case eModeARM:
Johnny Chenee9b1f72011-02-09 01:00:31 +000013189 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013190 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013191 break;
Greg Claytonb5169392011-10-31 23:51:19 +000013192 case eModeThumb:
Johnny Chenee9b1f72011-02-09 01:00:31 +000013193 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013194 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013195 break;
13196 }
13197 return true;
13198}
13199
Johnny Chenef21b592011-02-10 01:52:38 +000013200// This function returns TRUE if the processor currently provides support for
13201// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13202// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13203bool
13204EmulateInstructionARM::UnalignedSupport()
13205{
13206 return (ArchVersion() >= ARMv7);
13207}
13208
Johnny Chenbf6ad172011-02-11 01:29:53 +000013209// The main addition and subtraction instructions can produce status information
13210// about both unsigned carry and signed overflow conditions. This status
13211// information can be used to synthesize multi-word additions and subtractions.
13212EmulateInstructionARM::AddWithCarryResult
13213EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13214{
13215 uint32_t result;
13216 uint8_t carry_out;
13217 uint8_t overflow;
13218
13219 uint64_t unsigned_sum = x + y + carry_in;
13220 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13221
13222 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013223// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013224 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013225
13226 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013227 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013228 else
13229 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013230
13231 AddWithCarryResult res = { result, carry_out, overflow };
13232 return res;
13233}
13234
Johnny Chen157b9592011-02-18 21:13:05 +000013235uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013236EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013237{
Johnny Chene39f22d2011-02-19 01:36:13 +000013238 uint32_t reg_kind, reg_num;
13239 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013240 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013241 case SP_REG:
13242 reg_kind = eRegisterKindGeneric;
13243 reg_num = LLDB_REGNUM_GENERIC_SP;
13244 break;
13245 case LR_REG:
13246 reg_kind = eRegisterKindGeneric;
13247 reg_num = LLDB_REGNUM_GENERIC_RA;
13248 break;
13249 case PC_REG:
13250 reg_kind = eRegisterKindGeneric;
13251 reg_num = LLDB_REGNUM_GENERIC_PC;
13252 break;
13253 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013254 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013255 {
13256 reg_kind = eRegisterKindDWARF;
13257 reg_num = dwarf_r0 + num;
13258 }
Johnny Chen157b9592011-02-18 21:13:05 +000013259 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013260 {
Greg Claytone1f47bb2011-06-02 22:23:35 +000013261 //assert(0 && "Invalid register number");
Johnny Chene39f22d2011-02-19 01:36:13 +000013262 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013263 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013264 }
13265 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013266 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013267
13268 // Read our register.
13269 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13270
13271 // When executing an ARM instruction , PC reads as the address of the current
13272 // instruction plus 8.
13273 // When executing a Thumb instruction , PC reads as the address of the current
13274 // instruction plus 4.
13275 if (num == 15)
13276 {
13277 if (CurrentInstrSet() == eModeARM)
13278 val += 8;
13279 else
13280 val += 4;
13281 }
Johnny Chen157b9592011-02-18 21:13:05 +000013282
13283 return val;
13284}
13285
Johnny Chenca67d1c2011-02-17 01:35:27 +000013286// Write the result to the ARM core register Rd, and optionally update the
13287// condition flags based on the result.
13288//
13289// This helper method tries to encapsulate the following pseudocode from the
13290// ARM Architecture Reference Manual:
13291//
13292// if d == 15 then // Can only occur for encoding A1
13293// ALUWritePC(result); // setflags is always FALSE here
13294// else
13295// R[d] = result;
13296// if setflags then
13297// APSR.N = result<31>;
13298// APSR.Z = IsZeroBit(result);
13299// APSR.C = carry;
13300// // APSR.V unchanged
13301//
13302// In the above case, the API client does not pass in the overflow arg, which
13303// defaults to ~0u.
13304bool
Johnny Chen10530c22011-02-17 22:37:12 +000013305EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13306 const uint32_t result,
13307 const uint32_t Rd,
13308 bool setflags,
13309 const uint32_t carry,
13310 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013311{
13312 if (Rd == 15)
13313 {
13314 if (!ALUWritePC (context, result))
13315 return false;
13316 }
13317 else
13318 {
Johnny Chena695f952011-02-23 21:24:25 +000013319 uint32_t reg_kind, reg_num;
13320 switch (Rd)
13321 {
13322 case SP_REG:
13323 reg_kind = eRegisterKindGeneric;
13324 reg_num = LLDB_REGNUM_GENERIC_SP;
13325 break;
13326 case LR_REG:
13327 reg_kind = eRegisterKindGeneric;
13328 reg_num = LLDB_REGNUM_GENERIC_RA;
13329 break;
13330 default:
13331 reg_kind = eRegisterKindDWARF;
13332 reg_num = dwarf_r0 + Rd;
13333 }
13334 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013335 return false;
13336 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013337 return WriteFlags (context, result, carry, overflow);
13338 }
13339 return true;
13340}
13341
13342// This helper method tries to encapsulate the following pseudocode from the
13343// ARM Architecture Reference Manual:
13344//
13345// APSR.N = result<31>;
13346// APSR.Z = IsZeroBit(result);
13347// APSR.C = carry;
13348// APSR.V = overflow
13349//
13350// Default arguments can be specified for carry and overflow parameters, which means
13351// not to update the respective flags.
13352bool
13353EmulateInstructionARM::WriteFlags (Context &context,
13354 const uint32_t result,
13355 const uint32_t carry,
13356 const uint32_t overflow)
13357{
Greg Claytonb3448432011-03-24 21:19:54 +000013358 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013359 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13360 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013361 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013362 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013363 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013364 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013365 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013366 {
13367 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13368 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013369 }
13370 return true;
13371}
13372
Greg Clayton64c84432011-01-21 22:02:52 +000013373bool
Greg Clayton888a7332011-04-26 04:39:08 +000013374EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013375{
Johnny Chenc315f862011-02-05 00:46:10 +000013376 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013377 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013378 m_it_session.ITAdvance();
13379
Greg Clayton888a7332011-04-26 04:39:08 +000013380 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013381
13382 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013383 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013384 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013385 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13386
13387 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013388 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013389
Greg Clayton888a7332011-04-26 04:39:08 +000013390 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13391 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013392
Greg Clayton888a7332011-04-26 04:39:08 +000013393 bool success = false;
13394 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013395 {
Greg Clayton888a7332011-04-26 04:39:08 +000013396 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
Greg Clayton061b79d2011-05-09 20:18:18 +000013397 dwarf_cpsr,
13398 0,
13399 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013400 }
13401
Greg Clayton888a7332011-04-26 04:39:08 +000013402 // Only return false if we are unable to read the CPSR if we care about conditions
13403 if (success == false && m_ignore_conditions == false)
13404 return false;
13405
13406 uint32_t orig_pc_value = 0;
13407 if (auto_advance_pc)
13408 {
13409 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13410 if (!success)
13411 return false;
13412 }
13413
13414 // Call the Emulate... function.
13415 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13416 if (!success)
13417 return false;
13418
13419 if (auto_advance_pc)
13420 {
13421 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13422 if (!success)
13423 return false;
13424
13425 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13426 {
13427 if (opcode_data->size == eSize32)
13428 after_pc_value += 4;
13429 else if (opcode_data->size == eSize16)
13430 after_pc_value += 2;
13431
13432 EmulateInstruction::Context context;
13433 context.type = eContextAdvancePC;
13434 context.SetNoArgs();
13435 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13436 return false;
13437
13438 }
13439 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013440 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013441}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013442
13443bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013444EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013445{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013446 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013447 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013448 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013449 return false;
13450 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013451
13452 static ConstString opcode_key ("opcode");
13453 static ConstString before_key ("before_state");
13454 static ConstString after_key ("after_state");
13455
13456 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013457
13458 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013459 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013460 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013461 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013462 return false;
13463 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013464 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013465
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013466 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13467 {
13468 m_opcode_mode = eModeARM;
13469 m_opcode.SetOpcode32 (test_opcode);
13470 }
13471 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13472 {
13473 m_opcode_mode = eModeThumb;
13474 if (test_opcode < 0x10000)
13475 m_opcode.SetOpcode16 (test_opcode);
13476 else
13477 m_opcode.SetOpcode32 (test_opcode);
13478
13479 }
13480 else
13481 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013482 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013483 return false;
13484 }
13485
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013486 EmulationStateARM before_state;
13487 EmulationStateARM after_state;
13488
Caroline Ticedfb2e202011-04-22 05:08:45 +000013489 value_sp = test_data->GetValueForKey (before_key);
13490 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013491 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013492 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013493 return false;
13494 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013495
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013496 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013497 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013498 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013499 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013500 return false;
13501 }
13502
Caroline Ticedfb2e202011-04-22 05:08:45 +000013503 value_sp = test_data->GetValueForKey (after_key);
13504 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013505 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013506 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013507 return false;
13508 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013509
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013510 state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013511 if (!after_state.LoadStateFromDictionary (state_dictionary))
13512 {
13513 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13514 return false;
13515 }
13516
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013517 SetBaton ((void *) &before_state);
13518 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13519 &EmulationStateARM::WritePseudoMemory,
13520 &EmulationStateARM::ReadPseudoRegister,
13521 &EmulationStateARM::WritePseudoRegister);
13522
Greg Clayton888a7332011-04-26 04:39:08 +000013523 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013524 if (!success)
13525 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013526 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013527 return false;
13528 }
13529
13530 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013531 if (!success)
13532 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13533
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013534 return success;
13535}
Greg Claytonc07d4512011-04-26 23:48:45 +000013536//
13537//
13538//const char *
13539//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13540//{
13541// if (reg_kind == eRegisterKindGeneric)
13542// {
13543// switch (reg_num)
13544// {
13545// case LLDB_REGNUM_GENERIC_PC: return "pc";
13546// case LLDB_REGNUM_GENERIC_SP: return "sp";
13547// case LLDB_REGNUM_GENERIC_FP: return "fp";
13548// case LLDB_REGNUM_GENERIC_RA: return "lr";
13549// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13550// default: return NULL;
13551// }
13552// }
13553// else if (reg_kind == eRegisterKindDWARF)
13554// {
13555// return GetARMDWARFRegisterName (reg_num);
13556// }
13557// return NULL;
13558//}
13559//
13560bool
13561EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
Greg Clayton888a7332011-04-26 04:39:08 +000013562{
Greg Clayton75906e42011-05-11 18:39:18 +000013563 unwind_plan.Clear();
Greg Claytonc07d4512011-04-26 23:48:45 +000013564 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13565
13566 UnwindPlan::Row row;
Greg Claytonc07d4512011-04-26 23:48:45 +000013567
13568 // Our previous Call Frame Address is the stack pointer
13569 row.SetCFARegister (dwarf_sp);
13570
13571 // Our previous PC is in the LR
Greg Clayton75906e42011-05-11 18:39:18 +000013572 row.SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
Greg Claytonc07d4512011-04-26 23:48:45 +000013573 unwind_plan.AppendRow (row);
13574
13575 // All other registers are the same.
13576
13577 unwind_plan.SetSourceName ("EmulateInstructionARM");
13578 return true;
Greg Clayton888a7332011-04-26 04:39:08 +000013579}
13580
Greg Claytonc07d4512011-04-26 23:48:45 +000013581
13582
13583