blob: 48e5c7f3ca7b8723d73e4a6bb021e14b4a653201 [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.
45static unsigned short CountITSize(unsigned ITMask) {
46 // First count the trailing zeros of the IT mask.
47 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
48 if (TZ > 3)
49 {
50 printf("Encoding error: IT Mask '0000'\n");
51 return 0;
52 }
53 return (4 - TZ);
54}
55
56// Init ITState. Note that at least one bit is always 1 in mask.
57bool ITSession::InitIT(unsigned short bits7_0)
58{
59 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
60 if (ITCounter == 0)
61 return false;
62
63 // A8.6.50 IT
64 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
65 if (FirstCond == 0xF)
66 {
67 printf("Encoding error: IT FirstCond '1111'\n");
68 return false;
69 }
70 if (FirstCond == 0xE && ITCounter != 1)
71 {
72 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
73 return false;
74 }
75
76 ITState = bits7_0;
77 return true;
78}
79
80// Update ITState if necessary.
81void ITSession::ITAdvance()
82{
83 assert(ITCounter);
84 --ITCounter;
85 if (ITCounter == 0)
86 ITState = 0;
87 else
88 {
89 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
90 SetBits32(ITState, 4, 0, NewITState4_0);
91 }
92}
93
94// Return true if we're inside an IT Block.
95bool ITSession::InITBlock()
96{
97 return ITCounter != 0;
98}
99
Johnny Chenc315f862011-02-05 00:46:10 +0000100// Return true if we're the last instruction inside an IT Block.
101bool ITSession::LastInITBlock()
102{
103 return ITCounter == 1;
104}
105
Johnny Chen93070472011-02-04 23:02:47 +0000106// Get condition bits for the current thumb instruction.
107uint32_t ITSession::GetCond()
108{
Johnny Chenc315f862011-02-05 00:46:10 +0000109 if (InITBlock())
110 return Bits32(ITState, 7, 4);
111 else
112 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000113}
114
Greg Clayton64c84432011-01-21 22:02:52 +0000115// ARM constants used during decoding
116#define REG_RD 0
117#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000118#define SP_REG 13
119#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000120#define PC_REG 15
121#define PC_REGLIST_BIT 0x8000
122
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMv4T (1u << 1)
125#define ARMv5T (1u << 2)
126#define ARMv5TE (1u << 3)
127#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000128#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000129#define ARMv6K (1u << 6)
130#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000131#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000132#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000133#define ARMvAll (0xffffffffu)
134
Johnny Chen9b8d7832011-02-02 01:13:56 +0000135#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
136#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice1697dd72011-03-30 17:11:45 +0000137#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000138#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000139#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000140#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000141
Caroline Tice4f605582011-03-31 00:02:51 +0000142#define No_VFP 0
143#define VFPv1 (1u << 1)
144#define VFPv2 (1u << 2)
145#define VFPv3 (1u << 3)
146#define AdvancedSIMD (1u << 4)
147
148#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
149#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
150#define VFPv2v3 (VFPv2 | VFPv3)
151
Johnny Chen0e00af22011-02-10 19:40:42 +0000152//----------------------------------------------------------------------
153//
154// EmulateInstructionARM implementation
155//
156//----------------------------------------------------------------------
157
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000158void
159EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000160{
Caroline Tice080bf612011-04-05 18:46:00 +0000161 PluginManager::RegisterPlugin (GetPluginNameStatic (),
162 GetPluginDescriptionStatic (),
163 CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000164}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000165
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000166void
167EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000168{
Caroline Tice080bf612011-04-05 18:46:00 +0000169 PluginManager::UnregisterPlugin (CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000170}
171
Caroline Tice080bf612011-04-05 18:46:00 +0000172const char *
173EmulateInstructionARM::GetPluginNameStatic ()
174{
175 return "lldb.emulate-instruction.arm";
176}
177
178const char *
179EmulateInstructionARM::GetPluginDescriptionStatic ()
180{
181 return "Emulate instructions for the ARM architecture.";
182}
183
184EmulateInstruction *
Greg Clayton888a7332011-04-26 04:39:08 +0000185EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
Caroline Tice080bf612011-04-05 18:46:00 +0000186{
Greg Clayton888a7332011-04-26 04:39:08 +0000187 if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
Caroline Tice080bf612011-04-05 18:46:00 +0000188 {
Greg Clayton888a7332011-04-26 04:39:08 +0000189 if (arch.GetTriple().getArch() == llvm::Triple::arm)
190 {
191 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
192
193 if (emulate_insn_ap.get())
194 return emulate_insn_ap.release();
195 }
196 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
197 {
198 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
199
200 if (emulate_insn_ap.get())
201 return emulate_insn_ap.release();
202 }
Caroline Tice080bf612011-04-05 18:46:00 +0000203 }
204
205 return NULL;
206}
207
208bool
209EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
210{
211 if (arch.GetTriple().getArch () == llvm::Triple::arm)
212 return true;
213 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
214 return true;
215
216 return false;
217}
218
Caroline Ticefa172202011-02-11 22:49:54 +0000219// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
220bool
221EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
222{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000223 EmulateInstruction::Context context;
224 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
225 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000226
227 uint32_t random_data = rand ();
228 const uint32_t addr_byte_size = GetAddressByteSize();
229
Caroline Ticecc96eb52011-02-17 19:20:40 +0000230 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000231 return false;
232
233 return true;
234}
235
Caroline Tice713c2662011-02-11 17:59:55 +0000236// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
237bool
238EmulateInstructionARM::WriteBits32Unknown (int n)
239{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000240 EmulateInstruction::Context context;
241 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
242 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000243
Johnny Chen62ff6f52011-02-11 18:11:22 +0000244 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000245 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
246
247 if (!success)
248 return false;
249
250 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
251 return false;
252
253 return true;
254}
255
Greg Claytonc07d4512011-04-26 23:48:45 +0000256bool
257EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
258{
259 if (reg_kind == eRegisterKindGeneric)
260 {
261 switch (reg_num)
262 {
263 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break;
264 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break;
265 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break;
266 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break;
267 case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break;
268 default: return false;
269 }
270 }
271
272 if (reg_kind == eRegisterKindDWARF)
273 return GetARMDWARFRegisterInfo(reg_num, reg_info);
274 return false;
275}
276
Johnny Chen08c25e82011-01-31 18:02:28 +0000277// Push Multiple Registers stores multiple registers to the stack, storing to
278// consecutive memory locations ending just below the address in SP, and updates
279// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000280bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000281EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000282{
283#if 0
284 // ARM pseudo code...
285 if (ConditionPassed())
286 {
287 EncodingSpecificOperations();
288 NullCheckIfThumbEE(13);
289 address = SP - 4*BitCount(registers);
290
291 for (i = 0 to 14)
292 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000293 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000294 {
295 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
296 MemA[address,4] = bits(32) UNKNOWN;
297 else
298 MemA[address,4] = R[i];
299 address = address + 4;
300 }
301 }
302
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000303 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000304 MemA[address,4] = PCStoreValue();
305
306 SP = SP - 4*BitCount(registers);
307 }
308#endif
309
310 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000311 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000312 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000313 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000314 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000315 if (!success)
316 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000317 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000318 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000319 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000320 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000321 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000322 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000323 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000324 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000325 // if BitCount(registers) < 1 then UNPREDICTABLE;
326 if (BitCount(registers) < 1)
327 return false;
328 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000329 case eEncodingT2:
330 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000331 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000332 // if BitCount(registers) < 2 then UNPREDICTABLE;
333 if (BitCount(registers) < 2)
334 return false;
335 break;
336 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000337 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000338 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000339 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000340 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000341 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000342 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000343 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000344 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000345 // Instead of return false, let's handle the following case as well,
346 // which amounts to pushing one reg onto the full descending stacks.
347 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000348 break;
349 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000350 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000351 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000352 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000353 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000354 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000355 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000356 default:
357 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000358 }
Johnny Chence1ca772011-01-25 01:13:00 +0000359 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000360 addr_t addr = sp - sp_offset;
361 uint32_t i;
362
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000363 EmulateInstruction::Context context;
364 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000365 RegisterInfo reg_info;
366 RegisterInfo sp_reg;
367 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Clayton64c84432011-01-21 22:02:52 +0000368 for (i=0; i<15; ++i)
369 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000370 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000371 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000372 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
373 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000374 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000375 if (!success)
376 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000377 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000378 return false;
379 addr += addr_byte_size;
380 }
381 }
382
Johnny Chen7c1bf922011-02-08 23:49:37 +0000383 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000384 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000385 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info);
386 context.SetRegisterPlusOffset (reg_info, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000387 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000388 if (!success)
389 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000390 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000391 return false;
392 }
393
394 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000395 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000396
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000397 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000398 return false;
399 }
400 return true;
401}
402
Johnny Chenef85e912011-01-31 23:07:40 +0000403// Pop Multiple Registers loads multiple registers from the stack, loading from
404// consecutive memory locations staring at the address in SP, and updates
405// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000406bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000407EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000408{
409#if 0
410 // ARM pseudo code...
411 if (ConditionPassed())
412 {
413 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
414 address = SP;
415 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000416 if registers<i> == '1' then
Greg Claytonc07d4512011-04-26 23:48:45 +0000417 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000418 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000419 if UnalignedAllowed then
420 LoadWritePC(MemU[address,4]);
421 else
422 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000423 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
424 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000425 }
426#endif
427
428 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000429
Greg Claytonc07d4512011-04-26 23:48:45 +0000430 if (ConditionPassed(opcode)) {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000431 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000432 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000433 if (!success)
434 return false;
435 uint32_t registers = 0;
436 uint32_t Rt; // the destination register
437 switch (encoding) {
438 case eEncodingT1:
439 registers = Bits32(opcode, 7, 0);
440 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000441 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000442 registers |= (1u << 15);
443 // if BitCount(registers) < 1 then UNPREDICTABLE;
444 if (BitCount(registers) < 1)
445 return false;
446 break;
447 case eEncodingT2:
448 // Ignore bit 13.
449 registers = Bits32(opcode, 15, 0) & ~0x2000;
450 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000451 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000452 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000453 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
454 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
455 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000456 break;
457 case eEncodingT3:
458 Rt = Bits32(opcode, 15, 12);
459 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000460 if (Rt == 13)
461 return false;
462 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000463 return false;
464 registers = (1u << Rt);
465 break;
466 case eEncodingA1:
467 registers = Bits32(opcode, 15, 0);
468 // Instead of return false, let's handle the following case as well,
469 // which amounts to popping one reg from the full descending stacks.
470 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
471
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000472 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000473 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000474 return false;
475 break;
476 case eEncodingA2:
477 Rt = Bits32(opcode, 15, 12);
478 // if t == 13 then UNPREDICTABLE;
479 if (Rt == dwarf_sp)
480 return false;
481 registers = (1u << Rt);
482 break;
483 default:
484 return false;
485 }
486 addr_t sp_offset = addr_byte_size * BitCount (registers);
487 addr_t addr = sp;
488 uint32_t i, data;
489
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000490 EmulateInstruction::Context context;
491 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000492
493 RegisterInfo sp_reg;
494 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
495
Johnny Chenef85e912011-01-31 23:07:40 +0000496 for (i=0; i<15; ++i)
497 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000498 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000499 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000500 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000501 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000502 if (!success)
503 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +0000504 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000505 return false;
506 addr += addr_byte_size;
507 }
508 }
509
Johnny Chen7c1bf922011-02-08 23:49:37 +0000510 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000511 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000512 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000513 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000514 if (!success)
515 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000516 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000517 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000518 return false;
519 addr += addr_byte_size;
520 }
521
522 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000523 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000524
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000525 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000526 return false;
527 }
528 return true;
529}
530
Johnny Chen5b442b72011-01-27 19:34:30 +0000531// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000532// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000533bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000534EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000535{
536#if 0
537 // ARM pseudo code...
538 if (ConditionPassed())
539 {
540 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000541 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000542 if d == 15 then
543 ALUWritePC(result); // setflags is always FALSE here
544 else
545 R[d] = result;
546 if setflags then
547 APSR.N = result<31>;
548 APSR.Z = IsZeroBit(result);
549 APSR.C = carry;
550 APSR.V = overflow;
551 }
552#endif
553
554 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000555
Greg Clayton7bc39082011-03-24 23:53:38 +0000556 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000557 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000558 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000559 if (!success)
560 return false;
561 uint32_t Rd; // the destination register
562 uint32_t imm32;
563 switch (encoding) {
564 case eEncodingT1:
565 Rd = 7;
566 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
567 break;
568 case eEncodingA1:
569 Rd = Bits32(opcode, 15, 12);
570 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
571 break;
572 default:
573 return false;
574 }
575 addr_t sp_offset = imm32;
576 addr_t addr = sp + sp_offset; // a pointer to the stack area
577
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000578 EmulateInstruction::Context context;
Greg Clayton75906e42011-05-11 18:39:18 +0000579 context.type = eContextSetFramePointer;
Greg Claytonc07d4512011-04-26 23:48:45 +0000580 RegisterInfo sp_reg;
581 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000582 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000583
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000584 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000585 return false;
586 }
587 return true;
588}
589
Johnny Chen2ccad832011-01-28 19:57:25 +0000590// Set r7 or ip to the current stack pointer.
591// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000592bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000593EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000594{
595#if 0
596 // ARM pseudo code...
597 if (ConditionPassed())
598 {
599 EncodingSpecificOperations();
600 result = R[m];
601 if d == 15 then
602 ALUWritePC(result); // setflags is always FALSE here
603 else
604 R[d] = result;
605 if setflags then
606 APSR.N = result<31>;
607 APSR.Z = IsZeroBit(result);
608 // APSR.C unchanged
609 // APSR.V unchanged
610 }
611#endif
612
613 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000614
Greg Clayton7bc39082011-03-24 23:53:38 +0000615 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000616 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000617 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000618 if (!success)
619 return false;
620 uint32_t Rd; // the destination register
621 switch (encoding) {
622 case eEncodingT1:
623 Rd = 7;
624 break;
625 case eEncodingA1:
626 Rd = 12;
627 break;
628 default:
629 return false;
630 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000631
632 EmulateInstruction::Context context;
633 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +0000634 RegisterInfo sp_reg;
635 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000636 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000637
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000638 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000639 return false;
640 }
641 return true;
642}
643
Johnny Chen1c13b622011-01-29 00:11:15 +0000644// Move from high register (r8-r15) to low register (r0-r7).
645// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000646bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000647EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000648{
Greg Clayton7bc39082011-03-24 23:53:38 +0000649 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000650}
651
652// Move from register to register.
653// MOV (register)
654bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000655EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000656{
Johnny Chen1c13b622011-01-29 00:11:15 +0000657#if 0
658 // ARM pseudo code...
659 if (ConditionPassed())
660 {
661 EncodingSpecificOperations();
662 result = R[m];
663 if d == 15 then
664 ALUWritePC(result); // setflags is always FALSE here
665 else
666 R[d] = result;
667 if setflags then
668 APSR.N = result<31>;
669 APSR.Z = IsZeroBit(result);
670 // APSR.C unchanged
671 // APSR.V unchanged
672 }
673#endif
674
675 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000676
Greg Clayton7bc39082011-03-24 23:53:38 +0000677 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000678 {
679 uint32_t Rm; // the source register
680 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000681 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000682 switch (encoding) {
683 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000684 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000685 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000686 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000687 if (Rd == 15 && InITBlock() && !LastInITBlock())
688 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000689 break;
690 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000691 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000692 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000693 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000694 if (InITBlock())
695 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000696 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000697 case eEncodingT3:
698 Rd = Bits32(opcode, 11, 8);
699 Rm = Bits32(opcode, 3, 0);
700 setflags = BitIsSet(opcode, 20);
701 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
702 if (setflags && (BadReg(Rd) || BadReg(Rm)))
703 return false;
704 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
705 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
706 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000707 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000708 case eEncodingA1:
709 Rd = Bits32(opcode, 15, 12);
710 Rm = Bits32(opcode, 3, 0);
711 setflags = BitIsSet(opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +0000712
Johnny Chen01d61572011-02-25 00:23:25 +0000713 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000714 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000715 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000716 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000717 default:
718 return false;
719 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000720 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000721 if (!success)
722 return false;
723
724 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000725 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000726 context.type = EmulateInstruction::eContextRegisterLoad;
Greg Claytonc07d4512011-04-26 23:48:45 +0000727 RegisterInfo dwarf_reg;
728 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000729 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000730
Johnny Chen10530c22011-02-17 22:37:12 +0000731 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000732 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000733 }
734 return true;
735}
736
Johnny Chen357c30f2011-02-14 22:04:25 +0000737// Move (immediate) writes an immediate value to the destination register. It
738// can optionally update the condition flags based on the value.
739// MOV (immediate)
740bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000741EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000742{
743#if 0
744 // ARM pseudo code...
745 if (ConditionPassed())
746 {
747 EncodingSpecificOperations();
748 result = imm32;
749 if d == 15 then // Can only occur for ARM encoding
750 ALUWritePC(result); // setflags is always FALSE here
751 else
752 R[d] = result;
753 if setflags then
754 APSR.N = result<31>;
755 APSR.Z = IsZeroBit(result);
756 APSR.C = carry;
757 // APSR.V unchanged
758 }
759#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000760
Greg Clayton7bc39082011-03-24 23:53:38 +0000761 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000762 {
763 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000764 uint32_t imm32; // the immediate value to be written to Rd
765 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
766 bool setflags;
767 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000768 case eEncodingT1:
769 Rd = Bits32(opcode, 10, 8);
770 setflags = !InITBlock();
771 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
772 carry = APSR_C;
773
774 break;
775
776 case eEncodingT2:
777 Rd = Bits32(opcode, 11, 8);
778 setflags = BitIsSet(opcode, 20);
779 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
780 if (BadReg(Rd))
781 return false;
782
783 break;
784
785 case eEncodingT3:
786 {
787 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
788 Rd = Bits32 (opcode, 11, 8);
789 setflags = false;
790 uint32_t imm4 = Bits32 (opcode, 19, 16);
791 uint32_t imm3 = Bits32 (opcode, 14, 12);
792 uint32_t i = Bit32 (opcode, 26);
793 uint32_t imm8 = Bits32 (opcode, 7, 0);
794 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
795
796 // if BadReg(d) then UNPREDICTABLE;
797 if (BadReg (Rd))
798 return false;
799 }
800 break;
801
802 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +0000803 // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
Caroline Tice89c6d582011-03-29 19:53:44 +0000804 Rd = Bits32 (opcode, 15, 12);
805 setflags = BitIsSet (opcode, 20);
806 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000807
Greg Clayton061b79d2011-05-09 20:18:18 +0000808 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +0000809 if ((Rd == 15) && setflags)
810 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000811
812 break;
813
814 case eEncodingA2:
815 {
816 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
817 Rd = Bits32 (opcode, 15, 12);
818 setflags = false;
819 uint32_t imm4 = Bits32 (opcode, 19, 16);
820 uint32_t imm12 = Bits32 (opcode, 11, 0);
821 imm32 = (imm4 << 12) | imm12;
822
823 // if d == 15 then UNPREDICTABLE;
824 if (Rd == 15)
825 return false;
826 }
827 break;
828
829 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000830 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000831 }
832 uint32_t result = imm32;
833
834 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000835 EmulateInstruction::Context context;
836 context.type = EmulateInstruction::eContextImmediate;
837 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000838
Johnny Chen10530c22011-02-17 22:37:12 +0000839 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000840 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000841 }
842 return true;
843}
844
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000845// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
846// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
847// unsigned values.
848//
849// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
850// limited to only a few forms of the instruction.
851bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000852EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000853{
854#if 0
855 if ConditionPassed() then
856 EncodingSpecificOperations();
857 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
858 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
859 result = operand1 * operand2;
860 R[d] = result<31:0>;
861 if setflags then
862 APSR.N = result<31>;
863 APSR.Z = IsZeroBit(result);
864 if ArchVersion() == 4 then
865 APSR.C = bit UNKNOWN;
866 // else APSR.C unchanged
867 // APSR.V always unchanged
868#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000869
Greg Clayton7bc39082011-03-24 23:53:38 +0000870 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000871 {
872 uint32_t d;
873 uint32_t n;
874 uint32_t m;
875 bool setflags;
876
877 // EncodingSpecificOperations();
878 switch (encoding)
879 {
880 case eEncodingT1:
881 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
882 d = Bits32 (opcode, 2, 0);
883 n = Bits32 (opcode, 5, 3);
884 m = Bits32 (opcode, 2, 0);
885 setflags = !InITBlock();
886
887 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
888 if ((ArchVersion() < ARMv6) && (d == n))
889 return false;
890
891 break;
892
893 case eEncodingT2:
894 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
895 d = Bits32 (opcode, 11, 8);
896 n = Bits32 (opcode, 19, 16);
897 m = Bits32 (opcode, 3, 0);
898 setflags = false;
899
900 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
901 if (BadReg (d) || BadReg (n) || BadReg (m))
902 return false;
903
904 break;
905
906 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000907 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000908 d = Bits32 (opcode, 19, 16);
909 n = Bits32 (opcode, 3, 0);
910 m = Bits32 (opcode, 11, 8);
911 setflags = BitIsSet (opcode, 20);
912
913 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
914 if ((d == 15) || (n == 15) || (m == 15))
915 return false;
916
917 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
918 if ((ArchVersion() < ARMv6) && (d == n))
919 return false;
920
921 break;
922
923 default:
924 return false;
925 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000926
927 bool success = false;
928
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000929 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
930 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
931 if (!success)
932 return false;
933
934 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
935 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
936 if (!success)
937 return false;
938
939 // result = operand1 * operand2;
940 uint64_t result = operand1 * operand2;
941
942 // R[d] = result<31:0>;
Greg Claytonc07d4512011-04-26 23:48:45 +0000943 RegisterInfo op1_reg;
944 RegisterInfo op2_reg;
945 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
946 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000947
948 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +0000949 context.type = eContextArithmetic;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000950 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
951
952 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
953 return false;
954
955 // if setflags then
956 if (setflags)
957 {
958 // APSR.N = result<31>;
959 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000960 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000961 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
962 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000963 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000964 {
965 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
966 return false;
967 }
968
969 // if ArchVersion() == 4 then
970 // APSR.C = bit UNKNOWN;
971 }
972 }
973 return true;
974}
975
Johnny Chend642a6a2011-02-22 01:01:03 +0000976// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
977// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000978bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000979EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000980{
981#if 0
982 // ARM pseudo code...
983 if (ConditionPassed())
984 {
985 EncodingSpecificOperations();
986 result = NOT(imm32);
987 if d == 15 then // Can only occur for ARM encoding
988 ALUWritePC(result); // setflags is always FALSE here
989 else
990 R[d] = result;
991 if setflags then
992 APSR.N = result<31>;
993 APSR.Z = IsZeroBit(result);
994 APSR.C = carry;
995 // APSR.V unchanged
996 }
997#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000998
Greg Clayton7bc39082011-03-24 23:53:38 +0000999 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001000 {
1001 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +00001002 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1003 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001004 bool setflags;
1005 switch (encoding) {
1006 case eEncodingT1:
1007 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001008 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001009 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001010 break;
1011 case eEncodingA1:
1012 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001013 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001014 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +00001015
Johnny Chend642a6a2011-02-22 01:01:03 +00001016 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +00001017 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001018 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001019 break;
1020 default:
1021 return false;
1022 }
1023 uint32_t result = ~imm32;
1024
1025 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001026 EmulateInstruction::Context context;
1027 context.type = EmulateInstruction::eContextImmediate;
1028 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001029
Johnny Chen10530c22011-02-17 22:37:12 +00001030 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001031 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001032 }
1033 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001034}
1035
Johnny Chend642a6a2011-02-22 01:01:03 +00001036// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1037// It can optionally update the condition flags based on the result.
1038bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001039EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001040{
1041#if 0
1042 // ARM pseudo code...
1043 if (ConditionPassed())
1044 {
1045 EncodingSpecificOperations();
1046 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1047 result = NOT(shifted);
1048 if d == 15 then // Can only occur for ARM encoding
1049 ALUWritePC(result); // setflags is always FALSE here
1050 else
1051 R[d] = result;
1052 if setflags then
1053 APSR.N = result<31>;
1054 APSR.Z = IsZeroBit(result);
1055 APSR.C = carry;
1056 // APSR.V unchanged
1057 }
1058#endif
1059
Greg Clayton7bc39082011-03-24 23:53:38 +00001060 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001061 {
1062 uint32_t Rm; // the source register
1063 uint32_t Rd; // the destination register
1064 ARM_ShifterType shift_t;
1065 uint32_t shift_n; // the shift applied to the value read from Rm
1066 bool setflags;
1067 uint32_t carry; // the carry bit after the shift operation
1068 switch (encoding) {
1069 case eEncodingT1:
1070 Rd = Bits32(opcode, 2, 0);
1071 Rm = Bits32(opcode, 5, 3);
1072 setflags = !InITBlock();
1073 shift_t = SRType_LSL;
1074 shift_n = 0;
1075 if (InITBlock())
1076 return false;
1077 break;
1078 case eEncodingT2:
1079 Rd = Bits32(opcode, 11, 8);
1080 Rm = Bits32(opcode, 3, 0);
1081 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001082 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001083 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001084 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001085 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001086 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001087 case eEncodingA1:
1088 Rd = Bits32(opcode, 15, 12);
1089 Rm = Bits32(opcode, 3, 0);
1090 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001091 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001092 break;
1093 default:
1094 return false;
1095 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001096 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001097 uint32_t value = ReadCoreReg(Rm, &success);
1098 if (!success)
1099 return false;
1100
1101 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1102 uint32_t result = ~shifted;
1103
1104 // The context specifies that an immediate is to be moved into Rd.
1105 EmulateInstruction::Context context;
1106 context.type = EmulateInstruction::eContextImmediate;
1107 context.SetNoArgs ();
1108
1109 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1110 return false;
1111 }
1112 return true;
1113}
1114
Johnny Chen788e0552011-01-27 22:52:23 +00001115// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1116// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001117bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001118EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001119{
1120#if 0
1121 // ARM pseudo code...
1122 if (ConditionPassed())
1123 {
1124 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1125 base = Align(PC,4);
1126 address = if add then (base + imm32) else (base - imm32);
1127 data = MemU[address,4];
1128 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001129 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1130 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001131 R[t] = data;
1132 else // Can only apply before ARMv7
1133 if CurrentInstrSet() == InstrSet_ARM then
1134 R[t] = ROR(data, 8*UInt(address<1:0>));
1135 else
1136 R[t] = bits(32) UNKNOWN;
1137 }
1138#endif
1139
Greg Clayton7bc39082011-03-24 23:53:38 +00001140 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001141 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001142 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001143 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001144 if (!success)
1145 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001146
1147 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001148 EmulateInstruction::Context context;
1149 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001150 RegisterInfo pc_reg;
1151 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001152 context.SetRegisterPlusOffset (pc_reg, 0);
1153
Johnny Chenc9de9102011-02-11 19:12:30 +00001154 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001155 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001156 bool add; // +imm32 or -imm32?
1157 addr_t base; // the base address
1158 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001159 uint32_t data; // the literal data value from the PC relative load
1160 switch (encoding) {
1161 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001162 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001163 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001164 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001165 break;
1166 case eEncodingT2:
1167 Rt = Bits32(opcode, 15, 12);
1168 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1169 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001170 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001171 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001172 break;
1173 default:
1174 return false;
1175 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001176
Johnny Chene39f22d2011-02-19 01:36:13 +00001177 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001178 if (add)
1179 address = base + imm32;
1180 else
1181 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001182
1183 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001184 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001185 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001186 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001187
1188 if (Rt == 15)
1189 {
1190 if (Bits32(address, 1, 0) == 0)
1191 {
1192 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001193 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001194 return false;
1195 }
1196 else
1197 return false;
1198 }
1199 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1200 {
1201 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1202 return false;
1203 }
1204 else // We don't handle ARM for now.
1205 return false;
1206
Johnny Chen788e0552011-01-27 22:52:23 +00001207 }
1208 return true;
1209}
1210
Johnny Chen5b442b72011-01-27 19:34:30 +00001211// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001212// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001213bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001214EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001215{
1216#if 0
1217 // ARM pseudo code...
1218 if (ConditionPassed())
1219 {
1220 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001221 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001222 if d == 15 then // Can only occur for ARM encoding
1223 ALUWritePC(result); // setflags is always FALSE here
1224 else
1225 R[d] = result;
1226 if setflags then
1227 APSR.N = result<31>;
1228 APSR.Z = IsZeroBit(result);
1229 APSR.C = carry;
1230 APSR.V = overflow;
1231 }
1232#endif
1233
1234 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001235
Greg Clayton7bc39082011-03-24 23:53:38 +00001236 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001237 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001238 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001239 if (!success)
1240 return false;
1241 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001242 uint32_t d;
1243 bool setflags;
1244 switch (encoding)
1245 {
1246 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001247 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001248 d = Bits32 (opcode, 10, 8);
1249 setflags = false;
1250 imm32 = (Bits32 (opcode, 7, 0) << 2);
1251
1252 break;
1253
1254 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001255 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001256 d = 13;
1257 setflags = false;
1258 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1259
1260 break;
1261
1262 default:
1263 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001264 }
1265 addr_t sp_offset = imm32;
1266 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1267
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001268 EmulateInstruction::Context context;
1269 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +00001270 RegisterInfo sp_reg;
1271 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001272 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001273
Caroline Ticee2212882011-03-22 22:38:28 +00001274 if (d == 15)
1275 {
1276 if (!ALUWritePC (context, addr))
1277 return false;
1278 }
1279 else
1280 {
1281 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1282 return false;
1283 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001284 }
1285 return true;
1286}
1287
1288// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001289// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001290bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001291EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001292{
1293#if 0
1294 // ARM pseudo code...
1295 if (ConditionPassed())
1296 {
1297 EncodingSpecificOperations();
1298 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001299 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001300 if d == 15 then
1301 ALUWritePC(result); // setflags is always FALSE here
1302 else
1303 R[d] = result;
1304 if setflags then
1305 APSR.N = result<31>;
1306 APSR.Z = IsZeroBit(result);
1307 APSR.C = carry;
1308 APSR.V = overflow;
1309 }
1310#endif
1311
1312 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001313
Greg Clayton7bc39082011-03-24 23:53:38 +00001314 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001315 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001316 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001317 if (!success)
1318 return false;
1319 uint32_t Rm; // the second operand
1320 switch (encoding) {
1321 case eEncodingT2:
1322 Rm = Bits32(opcode, 6, 3);
1323 break;
1324 default:
1325 return false;
1326 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001327 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001328 if (!success)
1329 return false;
1330
1331 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1332
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001333 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00001334 context.type = eContextArithmetic;
1335 RegisterInfo sp_reg;
1336 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1337
1338 RegisterInfo other_reg;
1339 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001340 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001341
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001342 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001343 return false;
1344 }
1345 return true;
1346}
1347
Johnny Chen9b8d7832011-02-02 01:13:56 +00001348// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1349// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1350// from Thumb to ARM.
1351// BLX (immediate)
1352bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001353EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001354{
1355#if 0
1356 // ARM pseudo code...
1357 if (ConditionPassed())
1358 {
1359 EncodingSpecificOperations();
1360 if CurrentInstrSet() == InstrSet_ARM then
1361 LR = PC - 4;
1362 else
1363 LR = PC<31:1> : '1';
1364 if targetInstrSet == InstrSet_ARM then
1365 targetAddress = Align(PC,4) + imm32;
1366 else
1367 targetAddress = PC + imm32;
1368 SelectInstrSet(targetInstrSet);
1369 BranchWritePC(targetAddress);
1370 }
1371#endif
1372
Greg Clayton7bc39082011-03-24 23:53:38 +00001373 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001374
Greg Clayton7bc39082011-03-24 23:53:38 +00001375 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001376 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001377 EmulateInstruction::Context context;
1378 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001379 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001380 if (!success)
1381 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001382 addr_t lr; // next instruction address
1383 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001384 int32_t imm32; // PC-relative offset
1385 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001386 case eEncodingT1:
1387 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001388 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001389 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001390 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001391 uint32_t J1 = Bit32(opcode, 13);
1392 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001393 uint32_t imm11 = Bits32(opcode, 10, 0);
1394 uint32_t I1 = !(J1 ^ S);
1395 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001396 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001397 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001398 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001399 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001400 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001401 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001402 break;
1403 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001404 case eEncodingT2:
1405 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001406 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001407 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001408 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001409 uint32_t J1 = Bit32(opcode, 13);
1410 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001411 uint32_t imm10L = Bits32(opcode, 10, 1);
1412 uint32_t I1 = !(J1 ^ S);
1413 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001414 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001415 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001416 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001417 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001418 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001419 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001420 break;
1421 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001422 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001423 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001424 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001425 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001426 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001427 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001428 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001429 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001430 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001431 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001432 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001433 break;
1434 default:
1435 return false;
1436 }
1437 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1438 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001439 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001440 return false;
1441 }
1442 return true;
1443}
1444
1445// Branch with Link and Exchange (register) calls a subroutine at an address and
1446// instruction set specified by a register.
1447// BLX (register)
1448bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001449EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001450{
1451#if 0
1452 // ARM pseudo code...
1453 if (ConditionPassed())
1454 {
1455 EncodingSpecificOperations();
1456 target = R[m];
1457 if CurrentInstrSet() == InstrSet_ARM then
1458 next_instr_addr = PC - 4;
1459 LR = next_instr_addr;
1460 else
1461 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001462 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001463 BXWritePC(target);
1464 }
1465#endif
1466
1467 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001468
Greg Clayton7bc39082011-03-24 23:53:38 +00001469 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001470 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001471 EmulateInstruction::Context context;
1472 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001473 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001474 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001475 if (!success)
1476 return false;
1477 uint32_t Rm; // the register with the target address
1478 switch (encoding) {
1479 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001480 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001481 Rm = Bits32(opcode, 6, 3);
1482 // if m == 15 then UNPREDICTABLE;
1483 if (Rm == 15)
1484 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001485 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001486 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001487 break;
1488 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001489 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001490 Rm = Bits32(opcode, 3, 0);
1491 // if m == 15 then UNPREDICTABLE;
1492 if (Rm == 15)
1493 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001494 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001495 default:
1496 return false;
1497 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001498 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001499 if (!success)
1500 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001501 RegisterInfo dwarf_reg;
1502 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001503 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001504 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1505 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001506 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001507 return false;
1508 }
1509 return true;
1510}
1511
Johnny Chenab3b3512011-02-12 00:10:51 +00001512// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001513bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001514EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001515{
1516#if 0
1517 // ARM pseudo code...
1518 if (ConditionPassed())
1519 {
1520 EncodingSpecificOperations();
1521 BXWritePC(R[m]);
1522 }
1523#endif
1524
Greg Clayton7bc39082011-03-24 23:53:38 +00001525 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001526 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001527 EmulateInstruction::Context context;
1528 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001529 uint32_t Rm; // the register with the target address
1530 switch (encoding) {
1531 case eEncodingT1:
1532 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001533 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001534 return false;
1535 break;
1536 case eEncodingA1:
1537 Rm = Bits32(opcode, 3, 0);
1538 break;
1539 default:
1540 return false;
1541 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001542 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001543 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001544 if (!success)
1545 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001546
1547 RegisterInfo dwarf_reg;
1548 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen668b4512011-02-15 21:08:58 +00001549 context.SetRegister (dwarf_reg);
1550 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001551 return false;
1552 }
1553 return true;
1554}
1555
Johnny Chen59e6ab72011-02-24 21:01:20 +00001556// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1557// address and instruction set specified by a register as though it were a BX instruction.
1558//
1559// TODO: Emulate Jazelle architecture?
1560// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1561bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001562EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001563{
1564#if 0
1565 // ARM pseudo code...
1566 if (ConditionPassed())
1567 {
1568 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001569 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001570 BXWritePC(R[m]);
1571 else
1572 if JazelleAcceptsExecution() then
1573 SwitchToJazelleExecution();
1574 else
1575 SUBARCHITECTURE_DEFINED handler call;
1576 }
1577#endif
1578
Greg Clayton7bc39082011-03-24 23:53:38 +00001579 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001580 {
1581 EmulateInstruction::Context context;
1582 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1583 uint32_t Rm; // the register with the target address
1584 switch (encoding) {
1585 case eEncodingT1:
1586 Rm = Bits32(opcode, 19, 16);
1587 if (BadReg(Rm))
1588 return false;
1589 if (InITBlock() && !LastInITBlock())
1590 return false;
1591 break;
1592 case eEncodingA1:
1593 Rm = Bits32(opcode, 3, 0);
1594 if (Rm == 15)
1595 return false;
1596 break;
1597 default:
1598 return false;
1599 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001600 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001601 addr_t target = ReadCoreReg (Rm, &success);
1602 if (!success)
1603 return false;
1604
Greg Claytonc07d4512011-04-26 23:48:45 +00001605 RegisterInfo dwarf_reg;
1606 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen59e6ab72011-02-24 21:01:20 +00001607 context.SetRegister (dwarf_reg);
1608 if (!BXWritePC(context, target))
1609 return false;
1610 }
1611 return true;
1612}
1613
Johnny Chen0d0148e2011-01-28 02:26:08 +00001614// Set r7 to point to some ip offset.
1615// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001616bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001617EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001618{
1619#if 0
1620 // ARM pseudo code...
1621 if (ConditionPassed())
1622 {
1623 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001624 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001625 if d == 15 then // Can only occur for ARM encoding
1626 ALUWritePC(result); // setflags is always FALSE here
1627 else
1628 R[d] = result;
1629 if setflags then
1630 APSR.N = result<31>;
1631 APSR.Z = IsZeroBit(result);
1632 APSR.C = carry;
1633 APSR.V = overflow;
1634 }
1635#endif
1636
Greg Clayton7bc39082011-03-24 23:53:38 +00001637 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001638 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001639 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001640 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001641 if (!success)
1642 return false;
1643 uint32_t imm32;
1644 switch (encoding) {
1645 case eEncodingA1:
1646 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1647 break;
1648 default:
1649 return false;
1650 }
1651 addr_t ip_offset = imm32;
1652 addr_t addr = ip - ip_offset; // the adjusted ip value
1653
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001654 EmulateInstruction::Context context;
1655 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001656 RegisterInfo dwarf_reg;
1657 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001658 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001659
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001660 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001661 return false;
1662 }
1663 return true;
1664}
1665
1666// Set ip to point to some stack offset.
1667// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001668bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001669EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001670{
1671#if 0
1672 // ARM pseudo code...
1673 if (ConditionPassed())
1674 {
1675 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001676 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001677 if d == 15 then // Can only occur for ARM encoding
1678 ALUWritePC(result); // setflags is always FALSE here
1679 else
1680 R[d] = result;
1681 if setflags then
1682 APSR.N = result<31>;
1683 APSR.Z = IsZeroBit(result);
1684 APSR.C = carry;
1685 APSR.V = overflow;
1686 }
1687#endif
1688
Greg Clayton7bc39082011-03-24 23:53:38 +00001689 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001690 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001691 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001692 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001693 if (!success)
1694 return false;
1695 uint32_t imm32;
1696 switch (encoding) {
1697 case eEncodingA1:
1698 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1699 break;
1700 default:
1701 return false;
1702 }
1703 addr_t sp_offset = imm32;
1704 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1705
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001706 EmulateInstruction::Context context;
1707 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001708 RegisterInfo dwarf_reg;
1709 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001710 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001711
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001712 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001713 return false;
1714 }
1715 return true;
1716}
1717
Johnny Chenc9e747f2011-02-23 01:55:07 +00001718// This instruction subtracts an immediate value from the SP value, and writes
1719// the result to the destination register.
1720//
1721// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001722bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001723EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001724{
1725#if 0
1726 // ARM pseudo code...
1727 if (ConditionPassed())
1728 {
1729 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001730 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001731 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001732 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001733 else
1734 R[d] = result;
1735 if setflags then
1736 APSR.N = result<31>;
1737 APSR.Z = IsZeroBit(result);
1738 APSR.C = carry;
1739 APSR.V = overflow;
1740 }
1741#endif
1742
1743 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001744 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001745 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001746 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001747 if (!success)
1748 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001749
1750 uint32_t Rd;
1751 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001752 uint32_t imm32;
1753 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001754 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001755 Rd = 13;
1756 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001757 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001758 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001759 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001760 Rd = Bits32(opcode, 11, 8);
1761 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001762 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001763 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001764 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001765 if (Rd == 15 && !setflags)
1766 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001767 break;
1768 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001769 Rd = Bits32(opcode, 11, 8);
1770 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001771 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001772 if (Rd == 15)
1773 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001774 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001775 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001776 Rd = Bits32(opcode, 15, 12);
1777 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001778 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001779
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001780 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001781 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001782 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001783 break;
1784 default:
1785 return false;
1786 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001787 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1788
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001789 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001790 if (Rd == 13)
1791 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001792 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1793 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001794 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001795 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001796 }
1797 else
1798 {
1799 context.type = EmulateInstruction::eContextImmediate;
1800 context.SetNoArgs ();
1801 }
1802
1803 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001804 return false;
1805 }
1806 return true;
1807}
1808
Johnny Chen08c25e82011-01-31 18:02:28 +00001809// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001810bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001811EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001812{
1813#if 0
1814 // ARM pseudo code...
1815 if (ConditionPassed())
1816 {
1817 EncodingSpecificOperations();
1818 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1819 address = if index then offset_addr else R[n];
1820 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1821 if wback then R[n] = offset_addr;
1822 }
1823#endif
1824
1825 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001826
Greg Clayton7bc39082011-03-24 23:53:38 +00001827 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001828 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001829 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001830 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001831 if (!success)
1832 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001833 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001834 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001835 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1836
1837 bool index;
1838 bool add;
1839 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001840 switch (encoding) {
1841 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001842 Rt = Bits32(opcode, 15, 12);
1843 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001844 Rn = Bits32 (opcode, 19, 16);
1845
1846 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1847 return false;
1848
1849 index = BitIsSet (opcode, 24);
1850 add = BitIsSet (opcode, 23);
1851 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1852
1853 if (wback && ((Rn == 15) || (Rn == Rt)))
1854 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001855 break;
1856 default:
1857 return false;
1858 }
Caroline Tice3e407972011-03-18 19:41:00 +00001859 addr_t offset_addr;
1860 if (add)
1861 offset_addr = sp + imm12;
1862 else
1863 offset_addr = sp - imm12;
1864
1865 addr_t addr;
1866 if (index)
1867 addr = offset_addr;
1868 else
1869 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001870
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001871 EmulateInstruction::Context context;
1872 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001873 RegisterInfo sp_reg;
1874 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice3e407972011-03-18 19:41:00 +00001875 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001876 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001877 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001878 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001879 if (!success)
1880 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001881 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001882 return false;
1883 }
1884 else
1885 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001886 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001887 if (!success)
1888 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001889 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001890 return false;
1891 }
1892
Caroline Tice3e407972011-03-18 19:41:00 +00001893
1894 if (wback)
1895 {
1896 context.type = EmulateInstruction::eContextAdjustStackPointer;
1897 context.SetImmediateSigned (addr - sp);
1898 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1899 return false;
1900 }
Johnny Chence1ca772011-01-25 01:13:00 +00001901 }
1902 return true;
1903}
1904
Johnny Chen08c25e82011-01-31 18:02:28 +00001905// Vector Push stores multiple extension registers to the stack.
1906// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001907bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001908EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001909{
1910#if 0
1911 // ARM pseudo code...
1912 if (ConditionPassed())
1913 {
1914 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1915 address = SP - imm32;
1916 SP = SP - imm32;
1917 if single_regs then
1918 for r = 0 to regs-1
1919 MemA[address,4] = S[d+r]; address = address+4;
1920 else
1921 for r = 0 to regs-1
1922 // Store as two word-aligned words in the correct order for current endianness.
1923 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1924 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1925 address = address+8;
1926 }
1927#endif
1928
1929 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001930
Greg Clayton7bc39082011-03-24 23:53:38 +00001931 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001932 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001933 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001934 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001935 if (!success)
1936 return false;
1937 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001938 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001939 uint32_t imm32; // stack offset
1940 uint32_t regs; // number of registers
1941 switch (encoding) {
1942 case eEncodingT1:
1943 case eEncodingA1:
1944 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001945 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001946 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1947 // If UInt(imm8) is odd, see "FSTMX".
1948 regs = Bits32(opcode, 7, 0) / 2;
1949 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1950 if (regs == 0 || regs > 16 || (d + regs) > 32)
1951 return false;
1952 break;
1953 case eEncodingT2:
1954 case eEncodingA2:
1955 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001956 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001957 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1958 regs = Bits32(opcode, 7, 0);
1959 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1960 if (regs == 0 || regs > 16 || (d + regs) > 32)
1961 return false;
1962 break;
1963 default:
1964 return false;
1965 }
1966 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1967 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1968 addr_t sp_offset = imm32;
1969 addr_t addr = sp - sp_offset;
1970 uint32_t i;
1971
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001972 EmulateInstruction::Context context;
1973 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001974 RegisterInfo dwarf_reg;
1975 RegisterInfo sp_reg;
1976 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001977 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001978 {
Greg Claytonc07d4512011-04-26 23:48:45 +00001979 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001980 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001981 // uint64_t to accommodate 64-bit registers.
Greg Clayton061b79d2011-05-09 20:18:18 +00001982 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001983 if (!success)
1984 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001985 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001986 return false;
1987 addr += reg_byte_size;
1988 }
1989
1990 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001991 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001992
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001993 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001994 return false;
1995 }
1996 return true;
1997}
1998
Johnny Chen587a0a42011-02-01 18:35:28 +00001999// Vector Pop loads multiple extension registers from the stack.
2000// It also updates SP to point just above the loaded data.
2001bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002002EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00002003{
2004#if 0
2005 // ARM pseudo code...
2006 if (ConditionPassed())
2007 {
2008 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2009 address = SP;
2010 SP = SP + imm32;
2011 if single_regs then
2012 for r = 0 to regs-1
2013 S[d+r] = MemA[address,4]; address = address+4;
2014 else
2015 for r = 0 to regs-1
2016 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2017 // Combine the word-aligned words in the correct order for current endianness.
2018 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2019 }
2020#endif
2021
2022 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002023
Greg Clayton7bc39082011-03-24 23:53:38 +00002024 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002025 {
2026 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002027 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002028 if (!success)
2029 return false;
2030 bool single_regs;
2031 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2032 uint32_t imm32; // stack offset
2033 uint32_t regs; // number of registers
2034 switch (encoding) {
2035 case eEncodingT1:
2036 case eEncodingA1:
2037 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002038 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002039 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2040 // If UInt(imm8) is odd, see "FLDMX".
2041 regs = Bits32(opcode, 7, 0) / 2;
2042 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2043 if (regs == 0 || regs > 16 || (d + regs) > 32)
2044 return false;
2045 break;
2046 case eEncodingT2:
2047 case eEncodingA2:
2048 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002049 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002050 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2051 regs = Bits32(opcode, 7, 0);
2052 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2053 if (regs == 0 || regs > 16 || (d + regs) > 32)
2054 return false;
2055 break;
2056 default:
2057 return false;
2058 }
2059 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2060 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2061 addr_t sp_offset = imm32;
2062 addr_t addr = sp;
2063 uint32_t i;
2064 uint64_t data; // uint64_t to accomodate 64-bit registers.
2065
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002066 EmulateInstruction::Context context;
2067 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002068 RegisterInfo dwarf_reg;
2069 RegisterInfo sp_reg;
2070 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002071 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002072 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002073 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002074 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002075 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002076 if (!success)
2077 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +00002078 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002079 return false;
2080 addr += reg_byte_size;
2081 }
2082
2083 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002084 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002085
2086 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2087 return false;
2088 }
2089 return true;
2090}
2091
Johnny Chenb77be412011-02-04 00:40:18 +00002092// SVC (previously SWI)
2093bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002094EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002095{
2096#if 0
2097 // ARM pseudo code...
2098 if (ConditionPassed())
2099 {
2100 EncodingSpecificOperations();
2101 CallSupervisor();
2102 }
2103#endif
2104
2105 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002106
Greg Clayton7bc39082011-03-24 23:53:38 +00002107 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002108 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002109 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002110 addr_t lr; // next instruction address
2111 if (!success)
2112 return false;
2113 uint32_t imm32; // the immediate constant
2114 uint32_t mode; // ARM or Thumb mode
2115 switch (encoding) {
2116 case eEncodingT1:
2117 lr = (pc + 2) | 1u; // return address
2118 imm32 = Bits32(opcode, 7, 0);
2119 mode = eModeThumb;
2120 break;
2121 case eEncodingA1:
2122 lr = pc + 4; // return address
2123 imm32 = Bits32(opcode, 23, 0);
2124 mode = eModeARM;
2125 break;
2126 default:
2127 return false;
2128 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002129
2130 EmulateInstruction::Context context;
2131 context.type = EmulateInstruction::eContextSupervisorCall;
Greg Claytonc07d4512011-04-26 23:48:45 +00002132 context.SetISAAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002133 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2134 return false;
2135 }
2136 return true;
2137}
2138
Johnny Chenc315f862011-02-05 00:46:10 +00002139// If Then makes up to four following instructions (the IT block) conditional.
2140bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002141EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002142{
2143#if 0
2144 // ARM pseudo code...
2145 EncodingSpecificOperations();
2146 ITSTATE.IT<7:0> = firstcond:mask;
2147#endif
2148
Johnny Chenc315f862011-02-05 00:46:10 +00002149 m_it_session.InitIT(Bits32(opcode, 7, 0));
2150 return true;
2151}
2152
Johnny Chen3b620b32011-02-07 20:11:47 +00002153// Branch causes a branch to a target address.
2154bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002155EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002156{
2157#if 0
2158 // ARM pseudo code...
2159 if (ConditionPassed())
2160 {
2161 EncodingSpecificOperations();
2162 BranchWritePC(PC + imm32);
2163 }
2164#endif
2165
2166 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002167
Greg Clayton7bc39082011-03-24 23:53:38 +00002168 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002169 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002170 EmulateInstruction::Context context;
2171 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002172 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002173 if (!success)
2174 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002175 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002176 int32_t imm32; // PC-relative offset
2177 switch (encoding) {
2178 case eEncodingT1:
2179 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2180 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002181 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002182 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002183 break;
2184 case eEncodingT2:
2185 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002186 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002187 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002188 break;
2189 case eEncodingT3:
2190 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2191 {
Johnny Chenbd599902011-02-10 21:39:01 +00002192 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002193 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002194 uint32_t J1 = Bit32(opcode, 13);
2195 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002196 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002197 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002198 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002199 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002200 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002201 break;
2202 }
2203 case eEncodingT4:
2204 {
Johnny Chenbd599902011-02-10 21:39:01 +00002205 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002206 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002207 uint32_t J1 = Bit32(opcode, 13);
2208 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002209 uint32_t imm11 = Bits32(opcode, 10, 0);
2210 uint32_t I1 = !(J1 ^ S);
2211 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002212 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002213 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002214 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002215 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002216 break;
2217 }
2218 case eEncodingA1:
2219 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002220 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002221 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002222 break;
2223 default:
2224 return false;
2225 }
2226 if (!BranchWritePC(context, target))
2227 return false;
2228 }
2229 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002230}
2231
Johnny Chen53ebab72011-02-08 23:21:57 +00002232// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2233// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2234// CBNZ, CBZ
2235bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002236EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002237{
2238#if 0
2239 // ARM pseudo code...
2240 EncodingSpecificOperations();
2241 if nonzero ^ IsZero(R[n]) then
2242 BranchWritePC(PC + imm32);
2243#endif
2244
2245 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002246
2247 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002248 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002249 if (!success)
2250 return false;
2251
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002252 EmulateInstruction::Context context;
2253 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002254 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002255 if (!success)
2256 return false;
2257
2258 addr_t target; // target address
2259 uint32_t imm32; // PC-relative offset to branch forward
2260 bool nonzero;
2261 switch (encoding) {
2262 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002263 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002264 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002265 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002266 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002267 break;
2268 default:
2269 return false;
2270 }
2271 if (nonzero ^ (reg_val == 0))
2272 if (!BranchWritePC(context, target))
2273 return false;
2274
2275 return true;
2276}
2277
Johnny Chen60299ec2011-02-17 19:34:27 +00002278// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2279// A base register provides a pointer to the table, and a second register supplies an index into the table.
2280// The branch length is twice the value of the byte returned from the table.
2281//
2282// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2283// A base register provides a pointer to the table, and a second register supplies an index into the table.
2284// The branch length is twice the value of the halfword returned from the table.
2285// TBB, TBH
2286bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002287EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002288{
2289#if 0
2290 // ARM pseudo code...
2291 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2292 if is_tbh then
2293 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2294 else
2295 halfwords = UInt(MemU[R[n]+R[m], 1]);
2296 BranchWritePC(PC + 2*halfwords);
2297#endif
2298
2299 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002300
2301 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2302 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2303 bool is_tbh; // true if table branch halfword
2304 switch (encoding) {
2305 case eEncodingT1:
2306 Rn = Bits32(opcode, 19, 16);
2307 Rm = Bits32(opcode, 3, 0);
2308 is_tbh = BitIsSet(opcode, 4);
2309 if (Rn == 13 || BadReg(Rm))
2310 return false;
2311 if (InITBlock() && !LastInITBlock())
2312 return false;
2313 break;
2314 default:
2315 return false;
2316 }
2317
2318 // Read the address of the table from the operand register Rn.
2319 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002320 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002321 if (!success)
2322 return false;
2323
2324 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002325 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002326 if (!success)
2327 return false;
2328
2329 // the offsetted table address
2330 addr_t addr = base + (is_tbh ? index*2 : index);
2331
2332 // PC-relative offset to branch forward
2333 EmulateInstruction::Context context;
2334 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002335 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002336 if (!success)
2337 return false;
2338
Johnny Chene39f22d2011-02-19 01:36:13 +00002339 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002340 if (!success)
2341 return false;
2342
2343 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002344 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002345 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Greg Claytonc07d4512011-04-26 23:48:45 +00002346 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
Johnny Chen60299ec2011-02-17 19:34:27 +00002347
2348 if (!BranchWritePC(context, target))
2349 return false;
2350
2351 return true;
2352}
2353
Caroline Ticedcc11b32011-03-02 23:57:02 +00002354// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2355// It can optionally update the condition flags based on the result.
2356bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002357EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002358{
2359#if 0
2360 if ConditionPassed() then
2361 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002362 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002363 R[d] = result;
2364 if setflags then
2365 APSR.N = result<31>;
2366 APSR.Z = IsZeroBit(result);
2367 APSR.C = carry;
2368 APSR.V = overflow;
2369#endif
2370
2371 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002372
Greg Clayton7bc39082011-03-24 23:53:38 +00002373 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002374 {
2375 uint32_t d;
2376 uint32_t n;
2377 bool setflags;
2378 uint32_t imm32;
2379 uint32_t carry_out;
2380
2381 //EncodingSpecificOperations();
2382 switch (encoding)
2383 {
2384 case eEncodingT1:
2385 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2386 d = Bits32 (opcode, 2, 0);
2387 n = Bits32 (opcode, 5, 3);
2388 setflags = !InITBlock();
2389 imm32 = Bits32 (opcode, 8,6);
2390
2391 break;
2392
2393 case eEncodingT2:
2394 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2395 d = Bits32 (opcode, 10, 8);
2396 n = Bits32 (opcode, 10, 8);
2397 setflags = !InITBlock();
2398 imm32 = Bits32 (opcode, 7, 0);
2399
2400 break;
2401
2402 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002403 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2404 // if Rn == '1101' then SEE ADD (SP plus immediate);
2405 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002406 d = Bits32 (opcode, 11, 8);
2407 n = Bits32 (opcode, 19, 16);
2408 setflags = BitIsSet (opcode, 20);
2409 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2410
2411 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2412 if (BadReg (d) || (n == 15))
2413 return false;
2414
2415 break;
2416
2417 case eEncodingT4:
2418 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002419 // if Rn == '1111' then SEE ADR;
2420 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002421 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2422 d = Bits32 (opcode, 11, 8);
2423 n = Bits32 (opcode, 19, 16);
2424 setflags = false;
2425 uint32_t i = Bit32 (opcode, 26);
2426 uint32_t imm3 = Bits32 (opcode, 14, 12);
2427 uint32_t imm8 = Bits32 (opcode, 7, 0);
2428 imm32 = (i << 11) | (imm3 << 8) | imm8;
2429
2430 // if BadReg(d) then UNPREDICTABLE;
2431 if (BadReg (d))
2432 return false;
2433
2434 break;
2435 }
2436 default:
2437 return false;
2438 }
2439
2440 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2441 if (!success)
2442 return false;
2443
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002444 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002445 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2446
Greg Claytonc07d4512011-04-26 23:48:45 +00002447 RegisterInfo reg_n;
2448 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002449
2450 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002451 context.type = eContextArithmetic;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002452 context.SetRegisterPlusOffset (reg_n, imm32);
2453
2454 //R[d] = result;
2455 //if setflags then
2456 //APSR.N = result<31>;
2457 //APSR.Z = IsZeroBit(result);
2458 //APSR.C = carry;
2459 //APSR.V = overflow;
2460 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2461 return false;
2462
2463 }
2464 return true;
2465}
2466
Johnny Chen8fa20592011-02-18 01:22:22 +00002467// This instruction adds an immediate value to a register value, and writes the result to the destination
2468// register. It can optionally update the condition flags based on the result.
2469bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002470EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002471{
2472#if 0
2473 // ARM pseudo code...
2474 if ConditionPassed() then
2475 EncodingSpecificOperations();
2476 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2477 if d == 15 then
2478 ALUWritePC(result); // setflags is always FALSE here
2479 else
2480 R[d] = result;
2481 if setflags then
2482 APSR.N = result<31>;
2483 APSR.Z = IsZeroBit(result);
2484 APSR.C = carry;
2485 APSR.V = overflow;
2486#endif
2487
2488 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002489
Greg Clayton7bc39082011-03-24 23:53:38 +00002490 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002491 {
2492 uint32_t Rd, Rn;
2493 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2494 bool setflags;
2495 switch (encoding)
2496 {
2497 case eEncodingA1:
2498 Rd = Bits32(opcode, 15, 12);
2499 Rn = Bits32(opcode, 19, 16);
2500 setflags = BitIsSet(opcode, 20);
2501 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2502 break;
2503 default:
2504 return false;
2505 }
2506
Johnny Chen8fa20592011-02-18 01:22:22 +00002507 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002508 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002509 if (!success)
2510 return false;
2511
2512 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2513
2514 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002515 context.type = eContextArithmetic;
2516 RegisterInfo dwarf_reg;
2517 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00002518 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002519
2520 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2521 return false;
2522 }
2523 return true;
2524}
2525
Johnny Chend761dcf2011-02-17 22:03:29 +00002526// This instruction adds a register value and an optionally-shifted register value, and writes the result
2527// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002528bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002529EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002530{
2531#if 0
2532 // ARM pseudo code...
2533 if ConditionPassed() then
2534 EncodingSpecificOperations();
2535 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2536 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2537 if d == 15 then
2538 ALUWritePC(result); // setflags is always FALSE here
2539 else
2540 R[d] = result;
2541 if setflags then
2542 APSR.N = result<31>;
2543 APSR.Z = IsZeroBit(result);
2544 APSR.C = carry;
2545 APSR.V = overflow;
2546#endif
2547
2548 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002549
Greg Clayton7bc39082011-03-24 23:53:38 +00002550 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002551 {
2552 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002553 ARM_ShifterType shift_t;
2554 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002555 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002556 switch (encoding)
2557 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002558 case eEncodingT1:
2559 Rd = Bits32(opcode, 2, 0);
2560 Rn = Bits32(opcode, 5, 3);
2561 Rm = Bits32(opcode, 8, 6);
2562 setflags = !InITBlock();
2563 shift_t = SRType_LSL;
2564 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002565 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002566 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002567 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002568 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002569 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002570 shift_t = SRType_LSL;
2571 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002572 if (Rn == 15 && Rm == 15)
2573 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002574 if (Rd == 15 && InITBlock() && !LastInITBlock())
2575 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002576 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002577 case eEncodingA1:
2578 Rd = Bits32(opcode, 15, 12);
2579 Rn = Bits32(opcode, 19, 16);
2580 Rm = Bits32(opcode, 3, 0);
2581 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002582 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002583 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002584 default:
2585 return false;
2586 }
2587
Johnny Chen26863dc2011-02-09 23:43:29 +00002588 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002589 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002590 if (!success)
2591 return false;
2592
2593 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002594 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002595 if (!success)
2596 return false;
2597
Johnny Chene97c0d52011-02-18 19:32:20 +00002598 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002599 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002600
2601 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002602 context.type = eContextArithmetic;
2603 RegisterInfo op1_reg;
2604 RegisterInfo op2_reg;
2605 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2606 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00002607 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002608
Johnny Chen10530c22011-02-17 22:37:12 +00002609 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002610 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002611 }
2612 return true;
2613}
2614
Johnny Chen34075cb2011-02-22 01:56:31 +00002615// Compare Negative (immediate) adds a register value and an immediate value.
2616// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002617bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002618EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002619{
2620#if 0
2621 // ARM pseudo code...
2622 if ConditionPassed() then
2623 EncodingSpecificOperations();
2624 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2625 APSR.N = result<31>;
2626 APSR.Z = IsZeroBit(result);
2627 APSR.C = carry;
2628 APSR.V = overflow;
2629#endif
2630
2631 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002632
2633 uint32_t Rn; // the first operand
2634 uint32_t imm32; // the immediate value to be compared with
2635 switch (encoding) {
2636 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002637 Rn = Bits32(opcode, 19, 16);
2638 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2639 if (Rn == 15)
2640 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002641 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002642 case eEncodingA1:
2643 Rn = Bits32(opcode, 19, 16);
2644 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2645 break;
2646 default:
2647 return false;
2648 }
2649 // Read the register value from the operand register Rn.
2650 uint32_t reg_val = ReadCoreReg(Rn, &success);
2651 if (!success)
2652 return false;
2653
Johnny Chen078fbc62011-02-22 19:48:22 +00002654 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002655
2656 EmulateInstruction::Context context;
2657 context.type = EmulateInstruction::eContextImmediate;
2658 context.SetNoArgs ();
2659 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2660 return false;
2661
2662 return true;
2663}
2664
2665// Compare Negative (register) adds a register value and an optionally-shifted register value.
2666// It updates the condition flags based on the result, and discards the result.
2667bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002668EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002669{
2670#if 0
2671 // ARM pseudo code...
2672 if ConditionPassed() then
2673 EncodingSpecificOperations();
2674 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2675 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2676 APSR.N = result<31>;
2677 APSR.Z = IsZeroBit(result);
2678 APSR.C = carry;
2679 APSR.V = overflow;
2680#endif
2681
2682 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002683
2684 uint32_t Rn; // the first operand
2685 uint32_t Rm; // the second operand
2686 ARM_ShifterType shift_t;
2687 uint32_t shift_n; // the shift applied to the value read from Rm
2688 switch (encoding) {
2689 case eEncodingT1:
2690 Rn = Bits32(opcode, 2, 0);
2691 Rm = Bits32(opcode, 5, 3);
2692 shift_t = SRType_LSL;
2693 shift_n = 0;
2694 break;
2695 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002696 Rn = Bits32(opcode, 19, 16);
2697 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002698 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002699 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2700 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002701 return false;
2702 break;
2703 case eEncodingA1:
2704 Rn = Bits32(opcode, 19, 16);
2705 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002706 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002707 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002708 default:
2709 return false;
2710 }
2711 // Read the register value from register Rn.
2712 uint32_t val1 = ReadCoreReg(Rn, &success);
2713 if (!success)
2714 return false;
2715
2716 // Read the register value from register Rm.
2717 uint32_t val2 = ReadCoreReg(Rm, &success);
2718 if (!success)
2719 return false;
2720
2721 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002722 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002723
2724 EmulateInstruction::Context context;
2725 context.type = EmulateInstruction::eContextImmediate;
2726 context.SetNoArgs();
2727 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2728 return false;
2729
2730 return true;
2731}
2732
2733// Compare (immediate) subtracts an immediate value from a register value.
2734// It updates the condition flags based on the result, and discards the result.
2735bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002736EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002737{
2738#if 0
2739 // ARM pseudo code...
2740 if ConditionPassed() then
2741 EncodingSpecificOperations();
2742 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2743 APSR.N = result<31>;
2744 APSR.Z = IsZeroBit(result);
2745 APSR.C = carry;
2746 APSR.V = overflow;
2747#endif
2748
2749 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002750
2751 uint32_t Rn; // the first operand
2752 uint32_t imm32; // the immediate value to be compared with
2753 switch (encoding) {
2754 case eEncodingT1:
2755 Rn = Bits32(opcode, 10, 8);
2756 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002757 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002758 case eEncodingT2:
2759 Rn = Bits32(opcode, 19, 16);
2760 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2761 if (Rn == 15)
2762 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002763 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002764 case eEncodingA1:
2765 Rn = Bits32(opcode, 19, 16);
2766 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002767 break;
2768 default:
2769 return false;
2770 }
2771 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002772 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002773 if (!success)
2774 return false;
2775
Johnny Chen10530c22011-02-17 22:37:12 +00002776 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2777
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002778 EmulateInstruction::Context context;
2779 context.type = EmulateInstruction::eContextImmediate;
2780 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002781 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2782 return false;
2783
Johnny Chend4dc4442011-02-11 02:02:56 +00002784 return true;
2785}
2786
Johnny Chen34075cb2011-02-22 01:56:31 +00002787// Compare (register) subtracts an optionally-shifted register value from a register value.
2788// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002789bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002790EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002791{
2792#if 0
2793 // ARM pseudo code...
2794 if ConditionPassed() then
2795 EncodingSpecificOperations();
2796 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2797 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2798 APSR.N = result<31>;
2799 APSR.Z = IsZeroBit(result);
2800 APSR.C = carry;
2801 APSR.V = overflow;
2802#endif
2803
2804 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002805
2806 uint32_t Rn; // the first operand
2807 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002808 ARM_ShifterType shift_t;
2809 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002810 switch (encoding) {
2811 case eEncodingT1:
2812 Rn = Bits32(opcode, 2, 0);
2813 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002814 shift_t = SRType_LSL;
2815 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002816 break;
2817 case eEncodingT2:
2818 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2819 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002820 shift_t = SRType_LSL;
2821 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002822 if (Rn < 8 && Rm < 8)
2823 return false;
2824 if (Rn == 15 || Rm == 15)
2825 return false;
2826 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002827 case eEncodingA1:
2828 Rn = Bits32(opcode, 19, 16);
2829 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002830 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002831 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002832 default:
2833 return false;
2834 }
2835 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002836 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002837 if (!success)
2838 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002839
Johnny Chene4a4d302011-02-11 21:53:58 +00002840 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002841 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002842 if (!success)
2843 return false;
2844
Johnny Chen34075cb2011-02-22 01:56:31 +00002845 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2846 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002847
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002848 EmulateInstruction::Context context;
2849 context.type = EmulateInstruction::eContextImmediate;
2850 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002851 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2852 return false;
2853
Johnny Chene4a4d302011-02-11 21:53:58 +00002854 return true;
2855}
2856
Johnny Chen82f16aa2011-02-15 20:10:55 +00002857// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2858// shifting in copies of its sign bit, and writes the result to the destination register. It can
2859// optionally update the condition flags based on the result.
2860bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002861EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002862{
2863#if 0
2864 // ARM pseudo code...
2865 if ConditionPassed() then
2866 EncodingSpecificOperations();
2867 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2868 if d == 15 then // Can only occur for ARM encoding
2869 ALUWritePC(result); // setflags is always FALSE here
2870 else
2871 R[d] = result;
2872 if setflags then
2873 APSR.N = result<31>;
2874 APSR.Z = IsZeroBit(result);
2875 APSR.C = carry;
2876 // APSR.V unchanged
2877#endif
2878
Greg Clayton7bc39082011-03-24 23:53:38 +00002879 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002880}
2881
2882// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2883// shifting in copies of its sign bit, and writes the result to the destination register.
2884// The variable number of bits is read from the bottom byte of a register. It can optionally update
2885// the condition flags based on the result.
2886bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002887EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002888{
2889#if 0
2890 // ARM pseudo code...
2891 if ConditionPassed() then
2892 EncodingSpecificOperations();
2893 shift_n = UInt(R[m]<7:0>);
2894 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2895 R[d] = result;
2896 if setflags then
2897 APSR.N = result<31>;
2898 APSR.Z = IsZeroBit(result);
2899 APSR.C = carry;
2900 // APSR.V unchanged
2901#endif
2902
Greg Clayton7bc39082011-03-24 23:53:38 +00002903 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002904}
2905
2906// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2907// shifting in zeros, and writes the result to the destination register. It can optionally
2908// update the condition flags based on the result.
2909bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002910EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002911{
2912#if 0
2913 // ARM pseudo code...
2914 if ConditionPassed() then
2915 EncodingSpecificOperations();
2916 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2917 if d == 15 then // Can only occur for ARM encoding
2918 ALUWritePC(result); // setflags is always FALSE here
2919 else
2920 R[d] = result;
2921 if setflags then
2922 APSR.N = result<31>;
2923 APSR.Z = IsZeroBit(result);
2924 APSR.C = carry;
2925 // APSR.V unchanged
2926#endif
2927
Greg Clayton7bc39082011-03-24 23:53:38 +00002928 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002929}
2930
2931// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2932// shifting in zeros, and writes the result to the destination register. The variable number
2933// of bits is read from the bottom byte of a register. It can optionally update the condition
2934// flags based on the result.
2935bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002936EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002937{
2938#if 0
2939 // ARM pseudo code...
2940 if ConditionPassed() then
2941 EncodingSpecificOperations();
2942 shift_n = UInt(R[m]<7:0>);
2943 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2944 R[d] = result;
2945 if setflags then
2946 APSR.N = result<31>;
2947 APSR.Z = IsZeroBit(result);
2948 APSR.C = carry;
2949 // APSR.V unchanged
2950#endif
2951
Greg Clayton7bc39082011-03-24 23:53:38 +00002952 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002953}
2954
2955// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2956// shifting in zeros, and writes the result to the destination register. It can optionally
2957// update the condition flags based on the result.
2958bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002959EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002960{
2961#if 0
2962 // ARM pseudo code...
2963 if ConditionPassed() then
2964 EncodingSpecificOperations();
2965 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2966 if d == 15 then // Can only occur for ARM encoding
2967 ALUWritePC(result); // setflags is always FALSE here
2968 else
2969 R[d] = result;
2970 if setflags then
2971 APSR.N = result<31>;
2972 APSR.Z = IsZeroBit(result);
2973 APSR.C = carry;
2974 // APSR.V unchanged
2975#endif
2976
Greg Clayton7bc39082011-03-24 23:53:38 +00002977 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002978}
2979
2980// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2981// shifting in zeros, and writes the result to the destination register. The variable number
2982// of bits is read from the bottom byte of a register. It can optionally update the condition
2983// flags based on the result.
2984bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002985EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002986{
2987#if 0
2988 // ARM pseudo code...
2989 if ConditionPassed() then
2990 EncodingSpecificOperations();
2991 shift_n = UInt(R[m]<7:0>);
2992 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2993 R[d] = result;
2994 if setflags then
2995 APSR.N = result<31>;
2996 APSR.Z = IsZeroBit(result);
2997 APSR.C = carry;
2998 // APSR.V unchanged
2999#endif
3000
Greg Clayton7bc39082011-03-24 23:53:38 +00003001 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003002}
3003
Johnny Cheneeab4852011-02-16 22:14:44 +00003004// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3005// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3006// It can optionally update the condition flags based on the result.
3007bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003008EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003009{
3010#if 0
3011 // ARM pseudo code...
3012 if ConditionPassed() then
3013 EncodingSpecificOperations();
3014 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3015 if d == 15 then // Can only occur for ARM encoding
3016 ALUWritePC(result); // setflags is always FALSE here
3017 else
3018 R[d] = result;
3019 if setflags then
3020 APSR.N = result<31>;
3021 APSR.Z = IsZeroBit(result);
3022 APSR.C = carry;
3023 // APSR.V unchanged
3024#endif
3025
Greg Clayton7bc39082011-03-24 23:53:38 +00003026 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003027}
3028
3029// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3030// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3031// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3032// flags based on the result.
3033bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003034EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003035{
3036#if 0
3037 // ARM pseudo code...
3038 if ConditionPassed() then
3039 EncodingSpecificOperations();
3040 shift_n = UInt(R[m]<7:0>);
3041 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3042 R[d] = result;
3043 if setflags then
3044 APSR.N = result<31>;
3045 APSR.Z = IsZeroBit(result);
3046 APSR.C = carry;
3047 // APSR.V unchanged
3048#endif
3049
Greg Clayton7bc39082011-03-24 23:53:38 +00003050 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003051}
3052
3053// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3054// with the carry flag shifted into bit [31].
3055//
3056// RRX can optionally update the condition flags based on the result.
3057// In that case, bit [0] is shifted into the carry flag.
3058bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003059EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003060{
3061#if 0
3062 // ARM pseudo code...
3063 if ConditionPassed() then
3064 EncodingSpecificOperations();
3065 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3066 if d == 15 then // Can only occur for ARM encoding
3067 ALUWritePC(result); // setflags is always FALSE here
3068 else
3069 R[d] = result;
3070 if setflags then
3071 APSR.N = result<31>;
3072 APSR.Z = IsZeroBit(result);
3073 APSR.C = carry;
3074 // APSR.V unchanged
3075#endif
3076
Greg Clayton7bc39082011-03-24 23:53:38 +00003077 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003078}
3079
Johnny Chen41a0a152011-02-16 01:27:54 +00003080bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003081EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003082{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003083 assert(shift_type == SRType_ASR
3084 || shift_type == SRType_LSL
3085 || shift_type == SRType_LSR
3086 || shift_type == SRType_ROR
3087 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003088
Johnny Chen82f16aa2011-02-15 20:10:55 +00003089 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003090
Greg Clayton7bc39082011-03-24 23:53:38 +00003091 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003092 {
Johnny Chene7f89532011-02-15 23:22:46 +00003093 uint32_t Rd; // the destination register
3094 uint32_t Rm; // the first operand register
3095 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003096 uint32_t carry; // the carry bit after the shift operation
3097 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003098
3099 // Special case handling!
3100 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003101 ARMEncoding use_encoding = encoding;
3102 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003103 {
3104 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3105 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003106 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003107 }
3108
Greg Clayton7bc39082011-03-24 23:53:38 +00003109 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003110 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003111 // Due to the above special case handling!
3112 assert(shift_type != SRType_ROR);
3113
Johnny Chen82f16aa2011-02-15 20:10:55 +00003114 Rd = Bits32(opcode, 2, 0);
3115 Rm = Bits32(opcode, 5, 3);
3116 setflags = !InITBlock();
3117 imm5 = Bits32(opcode, 10, 6);
3118 break;
3119 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003120 // A8.6.141 RRX
3121 assert(shift_type != SRType_RRX);
3122
Johnny Chen82f16aa2011-02-15 20:10:55 +00003123 Rd = Bits32(opcode, 11, 8);
3124 Rm = Bits32(opcode, 3, 0);
3125 setflags = BitIsSet(opcode, 20);
3126 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3127 if (BadReg(Rd) || BadReg(Rm))
3128 return false;
3129 break;
3130 case eEncodingA1:
3131 Rd = Bits32(opcode, 15, 12);
3132 Rm = Bits32(opcode, 3, 0);
3133 setflags = BitIsSet(opcode, 20);
3134 imm5 = Bits32(opcode, 11, 7);
3135 break;
3136 default:
3137 return false;
3138 }
3139
Johnny Cheneeab4852011-02-16 22:14:44 +00003140 // A8.6.139 ROR (immediate)
3141 if (shift_type == SRType_ROR && imm5 == 0)
3142 shift_type = SRType_RRX;
3143
Johnny Chen82f16aa2011-02-15 20:10:55 +00003144 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003145 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003146 if (!success)
3147 return false;
3148
Johnny Cheneeab4852011-02-16 22:14:44 +00003149 // Decode the shift amount if not RRX.
3150 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003151
Johnny Chene97c0d52011-02-18 19:32:20 +00003152 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003153
3154 // The context specifies that an immediate is to be moved into Rd.
3155 EmulateInstruction::Context context;
3156 context.type = EmulateInstruction::eContextImmediate;
3157 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003158
Johnny Chen10530c22011-02-17 22:37:12 +00003159 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003160 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003161 }
3162 return true;
3163}
3164
Johnny Chene7f89532011-02-15 23:22:46 +00003165bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003166EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003167{
Johnny Chen41a0a152011-02-16 01:27:54 +00003168 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003169
3170 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003171
Greg Clayton7bc39082011-03-24 23:53:38 +00003172 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003173 {
3174 uint32_t Rd; // the destination register
3175 uint32_t Rn; // the first operand register
3176 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3177 uint32_t carry; // the carry bit after the shift operation
3178 bool setflags;
3179 switch (encoding) {
3180 case eEncodingT1:
3181 Rd = Bits32(opcode, 2, 0);
3182 Rn = Rd;
3183 Rm = Bits32(opcode, 5, 3);
3184 setflags = !InITBlock();
3185 break;
3186 case eEncodingT2:
3187 Rd = Bits32(opcode, 11, 8);
3188 Rn = Bits32(opcode, 19, 16);
3189 Rm = Bits32(opcode, 3, 0);
3190 setflags = BitIsSet(opcode, 20);
3191 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3192 return false;
3193 break;
3194 case eEncodingA1:
3195 Rd = Bits32(opcode, 15, 12);
3196 Rn = Bits32(opcode, 3, 0);
3197 Rm = Bits32(opcode, 11, 8);
3198 setflags = BitIsSet(opcode, 20);
3199 if (Rd == 15 || Rn == 15 || Rm == 15)
3200 return false;
3201 break;
3202 default:
3203 return false;
3204 }
3205
3206 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003207 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003208 if (!success)
3209 return false;
3210 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003211 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003212 if (!success)
3213 return false;
3214
3215 // Get the shift amount.
3216 uint32_t amt = Bits32(val, 7, 0);
3217
Johnny Chene97c0d52011-02-18 19:32:20 +00003218 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +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 ();
3224
Johnny Chen10530c22011-02-17 22:37:12 +00003225 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003226 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003227 }
3228 return true;
3229}
3230
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003231// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003232// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003233// can be written back to the base register.
3234bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003235EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003236{
3237#if 0
3238 // ARM pseudo code...
3239 if ConditionPassed()
3240 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3241 address = R[n];
3242
3243 for i = 0 to 14
3244 if registers<i> == '1' then
3245 R[i] = MemA[address, 4]; address = address + 4;
3246 if registers<15> == '1' then
3247 LoadWritePC (MemA[address, 4]);
3248
3249 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3250 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3251
3252#endif
3253
3254 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003255
Greg Clayton7bc39082011-03-24 23:53:38 +00003256 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003257 {
3258 uint32_t n;
3259 uint32_t registers = 0;
3260 bool wback;
3261 const uint32_t addr_byte_size = GetAddressByteSize();
3262 switch (encoding)
3263 {
3264 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003265 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003266 n = Bits32 (opcode, 10, 8);
3267 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003268 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003269 wback = BitIsClear (registers, n);
3270 // if BitCount(registers) < 1 then UNPREDICTABLE;
3271 if (BitCount(registers) < 1)
3272 return false;
3273 break;
3274 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003275 // if W == '1' && Rn == '1101' then SEE POP;
3276 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003277 n = Bits32 (opcode, 19, 16);
3278 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003279 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003280 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003281
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003282 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003283 if ((n == 15)
3284 || (BitCount (registers) < 2)
3285 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3286 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003287
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003288 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003289 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003290 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003291
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003292 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003293 if (wback
3294 && BitIsSet (registers, n))
3295 return false;
3296 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003297
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003298 case eEncodingA1:
3299 n = Bits32 (opcode, 19, 16);
3300 registers = Bits32 (opcode, 15, 0);
3301 wback = BitIsSet (opcode, 21);
3302 if ((n == 15)
3303 || (BitCount (registers) < 1))
3304 return false;
3305 break;
3306 default:
3307 return false;
3308 }
3309
3310 int32_t offset = 0;
3311 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3312 if (!success)
3313 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003314
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003315 EmulateInstruction::Context context;
3316 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003317 RegisterInfo dwarf_reg;
3318 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003319 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003320
3321 for (int i = 0; i < 14; ++i)
3322 {
3323 if (BitIsSet (registers, i))
3324 {
Caroline Tice85aab332011-02-08 23:56:10 +00003325 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003326 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003327 if (wback && (n == 13)) // Pop Instruction
3328 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3329
3330 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003331 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003332 if (!success)
3333 return false;
3334
3335 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3336 return false;
3337
3338 offset += addr_byte_size;
3339 }
3340 }
3341
3342 if (BitIsSet (registers, 15))
3343 {
3344 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003345 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003346 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003347 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003348 if (!success)
3349 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003350 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003351 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003352 return false;
3353 }
3354
3355 if (wback && BitIsClear (registers, n))
3356 {
Caroline Ticefa172202011-02-11 22:49:54 +00003357 // R[n] = R[n] + 4 * BitCount (registers)
3358 int32_t offset = addr_byte_size * BitCount (registers);
3359 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003360 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003361
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003362 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3363 return false;
3364 }
3365 if (wback && BitIsSet (registers, n))
3366 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003367 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003368 }
3369 return true;
3370}
Caroline Tice713c2662011-02-11 17:59:55 +00003371
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003372// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3373// The consecutive memory locations end at this address and the address just below the lowest of those locations
3374// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003375bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003376EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003377{
3378#if 0
3379 // ARM pseudo code...
3380 if ConditionPassed() then
3381 EncodingSpecificOperations();
3382 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003383
Caroline Tice713c2662011-02-11 17:59:55 +00003384 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003385 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003386 R[i] = MemA[address,4]; address = address + 4;
3387
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003388 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003389 LoadWritePC(MemA[address,4]);
3390
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003391 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3392 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003393#endif
3394
3395 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003396
Greg Clayton7bc39082011-03-24 23:53:38 +00003397 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003398 {
3399 uint32_t n;
3400 uint32_t registers = 0;
3401 bool wback;
3402 const uint32_t addr_byte_size = GetAddressByteSize();
3403
3404 // EncodingSpecificOperations();
3405 switch (encoding)
3406 {
3407 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003408 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003409 n = Bits32 (opcode, 19, 16);
3410 registers = Bits32 (opcode, 15, 0);
3411 wback = BitIsSet (opcode, 21);
3412
3413 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3414 if ((n == 15) || (BitCount (registers) < 1))
3415 return false;
3416
3417 break;
3418
3419 default:
3420 return false;
3421 }
3422 // address = R[n] - 4*BitCount(registers) + 4;
3423
3424 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003425 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003426
3427 if (!success)
3428 return false;
3429
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003430 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003431
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003432 EmulateInstruction::Context context;
3433 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003434 RegisterInfo dwarf_reg;
3435 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003436 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003437
3438 // for i = 0 to 14
3439 for (int i = 0; i < 14; ++i)
3440 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003441 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003442 if (BitIsSet (registers, i))
3443 {
3444 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003445 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003446 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003447 if (!success)
3448 return false;
3449 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3450 return false;
3451 offset += addr_byte_size;
3452 }
3453 }
3454
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003455 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003456 // LoadWritePC(MemA[address,4]);
3457 if (BitIsSet (registers, 15))
3458 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003459 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003460 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003461 if (!success)
3462 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003463 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003464 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003465 return false;
3466 }
3467
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003468 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003469 if (wback && BitIsClear (registers, n))
3470 {
Caroline Tice713c2662011-02-11 17:59:55 +00003471 if (!success)
3472 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003473
3474 offset = (addr_byte_size * BitCount (registers)) * -1;
3475 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003476 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003477 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003478 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3479 return false;
3480 }
3481
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003482 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003483 if (wback && BitIsSet (registers, n))
3484 return WriteBits32Unknown (n);
3485 }
3486 return true;
3487}
3488
3489// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3490// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3491// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003492bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003493EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003494{
3495#if 0
3496 // ARM pseudo code...
3497 if ConditionPassed() then
3498 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3499 address = R[n] - 4*BitCount(registers);
3500
3501 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003502 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003503 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003504 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003505 LoadWritePC(MemA[address,4]);
3506
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003507 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3508 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003509#endif
3510
3511 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003512
Greg Clayton7bc39082011-03-24 23:53:38 +00003513 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003514 {
3515 uint32_t n;
3516 uint32_t registers = 0;
3517 bool wback;
3518 const uint32_t addr_byte_size = GetAddressByteSize();
3519 switch (encoding)
3520 {
3521 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003522 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003523 n = Bits32 (opcode, 19, 16);
3524 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003525 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003526 wback = BitIsSet (opcode, 21);
3527
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003528 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003529 if ((n == 15)
3530 || (BitCount (registers) < 2)
3531 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3532 return false;
3533
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003534 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003535 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003536 return false;
3537
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003538 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003539 if (wback && BitIsSet (registers, n))
3540 return false;
3541
3542 break;
3543
3544 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003545 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003546 n = Bits32 (opcode, 19, 16);
3547 registers = Bits32 (opcode, 15, 0);
3548 wback = BitIsSet (opcode, 21);
3549
3550 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3551 if ((n == 15) || (BitCount (registers) < 1))
3552 return false;
3553
3554 break;
3555
3556 default:
3557 return false;
3558 }
3559
Caroline Tice713c2662011-02-11 17:59:55 +00003560 // address = R[n] - 4*BitCount(registers);
3561
Caroline Tice0b29e242011-02-08 23:16:02 +00003562 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003563 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003564
3565 if (!success)
3566 return false;
3567
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003568 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003569 EmulateInstruction::Context context;
3570 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003571 RegisterInfo dwarf_reg;
3572 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003573 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003574
3575 for (int i = 0; i < 14; ++i)
3576 {
3577 if (BitIsSet (registers, i))
3578 {
3579 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003580 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003581 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003582 if (!success)
3583 return false;
3584
3585 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3586 return false;
3587
3588 offset += addr_byte_size;
3589 }
3590 }
3591
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003592 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003593 // LoadWritePC(MemA[address,4]);
3594 if (BitIsSet (registers, 15))
3595 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003596 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003597 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003598 if (!success)
3599 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003600 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003601 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003602 return false;
3603 }
3604
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003605 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003606 if (wback && BitIsClear (registers, n))
3607 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003608 if (!success)
3609 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003610
3611 offset = (addr_byte_size * BitCount (registers)) * -1;
3612 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003613 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003614 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003615 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3616 return false;
3617 }
3618
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003619 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003620 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003621 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003622 }
3623 return true;
3624}
Caroline Tice85aab332011-02-08 23:56:10 +00003625
Caroline Tice713c2662011-02-11 17:59:55 +00003626// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3627// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3628// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003629bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003630EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003631{
3632#if 0
3633 if ConditionPassed() then
3634 EncodingSpecificOperations();
3635 address = R[n] + 4;
3636
3637 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003638 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003639 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003640 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003641 LoadWritePC(MemA[address,4]);
3642
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003643 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3644 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003645#endif
3646
3647 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003648
Greg Clayton7bc39082011-03-24 23:53:38 +00003649 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003650 {
3651 uint32_t n;
3652 uint32_t registers = 0;
3653 bool wback;
3654 const uint32_t addr_byte_size = GetAddressByteSize();
3655 switch (encoding)
3656 {
3657 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003658 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003659 n = Bits32 (opcode, 19, 16);
3660 registers = Bits32 (opcode, 15, 0);
3661 wback = BitIsSet (opcode, 21);
3662
3663 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3664 if ((n == 15) || (BitCount (registers) < 1))
3665 return false;
3666
3667 break;
3668 default:
3669 return false;
3670 }
3671 // address = R[n] + 4;
3672
3673 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003674 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003675
3676 if (!success)
3677 return false;
3678
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003679 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003680
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003681 EmulateInstruction::Context context;
3682 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003683 RegisterInfo dwarf_reg;
3684 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003685 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003686
3687 for (int i = 0; i < 14; ++i)
3688 {
3689 if (BitIsSet (registers, i))
3690 {
3691 // R[i] = MemA[address,4]; address = address + 4;
3692
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003693 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003694 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003695 if (!success)
3696 return false;
3697
3698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3699 return false;
3700
3701 offset += addr_byte_size;
3702 }
3703 }
3704
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003705 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003706 // LoadWritePC(MemA[address,4]);
3707 if (BitIsSet (registers, 15))
3708 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003709 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003710 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003711 if (!success)
3712 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003713 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003714 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003715 return false;
3716 }
3717
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003718 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003719 if (wback && BitIsClear (registers, n))
3720 {
Caroline Tice85aab332011-02-08 23:56:10 +00003721 if (!success)
3722 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003723
3724 offset = addr_byte_size * BitCount (registers);
3725 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003726 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003727 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003728 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3729 return false;
3730 }
3731
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003732 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003733 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003734 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003735 }
3736 return true;
3737}
Caroline Tice0b29e242011-02-08 23:16:02 +00003738
Johnny Chenef21b592011-02-10 01:52:38 +00003739// Load Register (immediate) calculates an address from a base register value and
3740// an immediate offset, loads a word from memory, and writes to a register.
3741// LDR (immediate, Thumb)
3742bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003743EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003744{
3745#if 0
3746 // ARM pseudo code...
3747 if (ConditionPassed())
3748 {
3749 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3750 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3751 address = if index then offset_addr else R[n];
3752 data = MemU[address,4];
3753 if wback then R[n] = offset_addr;
3754 if t == 15 then
3755 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3756 elsif UnalignedSupport() || address<1:0> = '00' then
3757 R[t] = data;
3758 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3759 }
3760#endif
3761
3762 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003763
Greg Clayton7bc39082011-03-24 23:53:38 +00003764 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003765 {
3766 uint32_t Rt; // the destination register
3767 uint32_t Rn; // the base register
3768 uint32_t imm32; // the immediate offset used to form the address
3769 addr_t offset_addr; // the offset address
3770 addr_t address; // the calculated address
3771 uint32_t data; // the literal data value from memory load
3772 bool add, index, wback;
3773 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003774 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003775 Rt = Bits32(opcode, 2, 0);
3776 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003777 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3778 // index = TRUE; add = TRUE; wback = FALSE
3779 add = true;
3780 index = true;
3781 wback = false;
3782
3783 break;
3784
3785 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003786 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003787 Rt = Bits32 (opcode, 10, 8);
3788 Rn = 13;
3789 imm32 = Bits32 (opcode, 7, 0) << 2;
3790
3791 // index = TRUE; add = TRUE; wback = FALSE;
3792 index = true;
3793 add = true;
3794 wback = false;
3795
3796 break;
3797
3798 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003799 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003800 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3801 Rt = Bits32 (opcode, 15, 12);
3802 Rn = Bits32 (opcode, 19, 16);
3803 imm32 = Bits32 (opcode, 11, 0);
3804
3805 // index = TRUE; add = TRUE; wback = FALSE;
3806 index = true;
3807 add = true;
3808 wback = false;
3809
3810 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3811 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3812 return false;
3813
3814 break;
3815
3816 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003817 // if Rn == '1111' then SEE LDR (literal);
3818 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3819 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3820 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003821 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3822 return false;
3823
3824 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3825 Rt = Bits32 (opcode, 15, 12);
3826 Rn = Bits32 (opcode, 19, 16);
3827 imm32 = Bits32 (opcode, 7, 0);
3828
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003829 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003830 index = BitIsSet (opcode, 10);
3831 add = BitIsSet (opcode, 9);
3832 wback = BitIsSet (opcode, 8);
3833
3834 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3835 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3836 return false;
3837
3838 break;
3839
3840 default:
3841 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003842 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003843 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003844 if (!success)
3845 return false;
3846 if (add)
3847 offset_addr = base + imm32;
3848 else
3849 offset_addr = base - imm32;
3850
3851 address = (index ? offset_addr : base);
3852
Greg Claytonc07d4512011-04-26 23:48:45 +00003853 RegisterInfo base_reg;
3854 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
Johnny Chenef21b592011-02-10 01:52:38 +00003855 if (wback)
3856 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003857 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003858 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3859 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003860
Johnny Chenef21b592011-02-10 01:52:38 +00003861 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3862 return false;
3863 }
3864
3865 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003866 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003867 context.type = EmulateInstruction::eContextRegisterLoad;
3868 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003869
3870 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003871 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003872 if (!success)
3873 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003874
3875 if (Rt == 15)
3876 {
3877 if (Bits32(address, 1, 0) == 0)
3878 {
Johnny Chen668b4512011-02-15 21:08:58 +00003879 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003880 return false;
3881 }
3882 else
3883 return false;
3884 }
3885 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3886 {
3887 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3888 return false;
3889 }
3890 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003891 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003892 }
3893 return true;
3894}
3895
Caroline Ticeaf556562011-02-15 18:42:15 +00003896// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3897// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3898// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003899bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003900EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003901{
3902#if 0
3903 if ConditionPassed() then
3904 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3905 address = R[n];
3906
3907 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003908 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003909 if i == n && wback && i != LowestSetBit(registers) then
3910 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3911 else
3912 MemA[address,4] = R[i];
3913 address = address + 4;
3914
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003915 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003916 MemA[address,4] = PCStoreValue();
3917 if wback then R[n] = R[n] + 4*BitCount(registers);
3918#endif
3919
3920 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003921
Greg Clayton7bc39082011-03-24 23:53:38 +00003922 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003923 {
3924 uint32_t n;
3925 uint32_t registers = 0;
3926 bool wback;
3927 const uint32_t addr_byte_size = GetAddressByteSize();
3928
3929 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3930 switch (encoding)
3931 {
3932 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003933 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003934 n = Bits32 (opcode, 10, 8);
3935 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003936 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003937 wback = true;
3938
3939 // if BitCount(registers) < 1 then UNPREDICTABLE;
3940 if (BitCount (registers) < 1)
3941 return false;
3942
3943 break;
3944
3945 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003946 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003947 n = Bits32 (opcode, 19, 16);
3948 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003949 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003950 wback = BitIsSet (opcode, 21);
3951
3952 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3953 if ((n == 15) || (BitCount (registers) < 2))
3954 return false;
3955
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003956 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003957 if (wback && BitIsSet (registers, n))
3958 return false;
3959
3960 break;
3961
3962 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003963 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003964 n = Bits32 (opcode, 19, 16);
3965 registers = Bits32 (opcode, 15, 0);
3966 wback = BitIsSet (opcode, 21);
3967
3968 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3969 if ((n == 15) || (BitCount (registers) < 1))
3970 return false;
3971
3972 break;
3973
3974 default:
3975 return false;
3976 }
3977
3978 // address = R[n];
3979 int32_t offset = 0;
3980 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3981 if (!success)
3982 return false;
3983
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003984 EmulateInstruction::Context context;
3985 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00003986 RegisterInfo base_reg;
3987 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefa172202011-02-11 22:49:54 +00003988
3989 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003990 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003991 for (int i = 0; i < 14; ++i)
3992 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003993 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003994 if (BitIsSet (registers, i))
3995 {
3996 if (i < lowest_set_bit)
3997 lowest_set_bit = i;
3998 // if i == n && wback && i != LowestSetBit(registers) then
3999 if ((i == n) && wback && (i != lowest_set_bit))
4000 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4001 WriteBits32UnknownToMemory (address + offset);
4002 else
4003 {
4004 // MemA[address,4] = R[i];
4005 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4006 if (!success)
4007 return false;
4008
Greg Claytonc07d4512011-04-26 23:48:45 +00004009 RegisterInfo data_reg;
4010 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004011 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004012 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004013 return false;
4014 }
4015
4016 // address = address + 4;
4017 offset += addr_byte_size;
4018 }
4019 }
4020
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004021 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004022 // MemA[address,4] = PCStoreValue();
4023 if (BitIsSet (registers, 15))
4024 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004025 RegisterInfo pc_reg;
4026 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004027 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004028 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004029 if (!success)
4030 return false;
4031
Caroline Tice8d681f52011-03-17 23:50:16 +00004032 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004033 return false;
4034 }
4035
4036 // if wback then R[n] = R[n] + 4*BitCount(registers);
4037 if (wback)
4038 {
4039 offset = addr_byte_size * BitCount (registers);
4040 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004041 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004042 addr_t data = address + offset;
4043 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4044 return false;
4045 }
4046 }
4047 return true;
4048}
4049
Caroline Ticeaf556562011-02-15 18:42:15 +00004050// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4051// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4052// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004053bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004054EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004055{
4056#if 0
4057 if ConditionPassed() then
4058 EncodingSpecificOperations();
4059 address = R[n] - 4*BitCount(registers) + 4;
4060
4061 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004062 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004063 if i == n && wback && i != LowestSetBit(registers) then
4064 MemA[address,4] = bits(32) UNKNOWN;
4065 else
4066 MemA[address,4] = R[i];
4067 address = address + 4;
4068
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004069 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004070 MemA[address,4] = PCStoreValue();
4071
4072 if wback then R[n] = R[n] - 4*BitCount(registers);
4073#endif
4074
4075 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004076
Greg Clayton7bc39082011-03-24 23:53:38 +00004077 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004078 {
4079 uint32_t n;
4080 uint32_t registers = 0;
4081 bool wback;
4082 const uint32_t addr_byte_size = GetAddressByteSize();
4083
4084 // EncodingSpecificOperations();
4085 switch (encoding)
4086 {
4087 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004088 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004089 n = Bits32 (opcode, 19, 16);
4090 registers = Bits32 (opcode, 15, 0);
4091 wback = BitIsSet (opcode, 21);
4092
4093 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4094 if ((n == 15) || (BitCount (registers) < 1))
4095 return false;
4096 break;
4097 default:
4098 return false;
4099 }
4100
4101 // address = R[n] - 4*BitCount(registers) + 4;
4102 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004103 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004104 if (!success)
4105 return false;
4106
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004107 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004108
4109 EmulateInstruction::Context context;
4110 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004111 RegisterInfo base_reg;
4112 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004113
4114 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004115 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004116 for (int i = 0; i < 14; ++i)
4117 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004118 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004119 if (BitIsSet (registers, i))
4120 {
4121 if (i < lowest_bit_set)
4122 lowest_bit_set = i;
4123 //if i == n && wback && i != LowestSetBit(registers) then
4124 if ((i == n) && wback && (i != lowest_bit_set))
4125 // MemA[address,4] = bits(32) UNKNOWN;
4126 WriteBits32UnknownToMemory (address + offset);
4127 else
4128 {
4129 // MemA[address,4] = R[i];
4130 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4131 if (!success)
4132 return false;
4133
Greg Claytonc07d4512011-04-26 23:48:45 +00004134 RegisterInfo data_reg;
4135 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004136 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004137 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004138 return false;
4139 }
4140
4141 // address = address + 4;
4142 offset += addr_byte_size;
4143 }
4144 }
4145
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004146 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004147 // MemA[address,4] = PCStoreValue();
4148 if (BitIsSet (registers, 15))
4149 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004150 RegisterInfo pc_reg;
4151 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004152 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004153 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004154 if (!success)
4155 return false;
4156
Caroline Tice8d681f52011-03-17 23:50:16 +00004157 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004158 return false;
4159 }
4160
4161 // if wback then R[n] = R[n] - 4*BitCount(registers);
4162 if (wback)
4163 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004164 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004165 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4166 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004167 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004168 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4169 return false;
4170 }
4171 }
4172 return true;
4173}
4174
Caroline Ticeaf556562011-02-15 18:42:15 +00004175// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4176// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4177// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004178bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004179EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004180{
4181#if 0
4182 if ConditionPassed() then
4183 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4184 address = R[n] - 4*BitCount(registers);
4185
4186 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004187 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004188 if i == n && wback && i != LowestSetBit(registers) then
4189 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4190 else
4191 MemA[address,4] = R[i];
4192 address = address + 4;
4193
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004194 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004195 MemA[address,4] = PCStoreValue();
4196
4197 if wback then R[n] = R[n] - 4*BitCount(registers);
4198#endif
4199
4200
4201 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004202
Greg Clayton7bc39082011-03-24 23:53:38 +00004203 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004204 {
4205 uint32_t n;
4206 uint32_t registers = 0;
4207 bool wback;
4208 const uint32_t addr_byte_size = GetAddressByteSize();
4209
4210 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4211 switch (encoding)
4212 {
4213 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004214 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004215 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4216 {
4217 // See PUSH
4218 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004219 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004220 n = Bits32 (opcode, 19, 16);
4221 registers = Bits32 (opcode, 15, 0);
4222 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4223 wback = BitIsSet (opcode, 21);
4224 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4225 if ((n == 15) || BitCount (registers) < 2)
4226 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004227 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004228 if (wback && BitIsSet (registers, n))
4229 return false;
4230 break;
4231
4232 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00004233 // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004234 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4235 {
4236 // See Push
4237 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004238 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004239 n = Bits32 (opcode, 19, 16);
4240 registers = Bits32 (opcode, 15, 0);
4241 wback = BitIsSet (opcode, 21);
4242 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4243 if ((n == 15) || BitCount (registers) < 1)
4244 return false;
4245 break;
4246
4247 default:
4248 return false;
4249 }
4250
4251 // address = R[n] - 4*BitCount(registers);
4252
4253 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004254 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004255 if (!success)
4256 return false;
4257
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004258 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004259
4260 EmulateInstruction::Context context;
4261 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004262 RegisterInfo base_reg;
4263 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004264
4265 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004266 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004267 for (int i = 0; i < 14; ++i)
4268 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004269 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004270 if (BitIsSet (registers, i))
4271 {
4272 if (i < lowest_set_bit)
4273 lowest_set_bit = i;
4274 // if i == n && wback && i != LowestSetBit(registers) then
4275 if ((i == n) && wback && (i != lowest_set_bit))
4276 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4277 WriteBits32UnknownToMemory (address + offset);
4278 else
4279 {
4280 // MemA[address,4] = R[i];
4281 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4282 if (!success)
4283 return false;
4284
Greg Claytonc07d4512011-04-26 23:48:45 +00004285 RegisterInfo data_reg;
4286 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004287 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004288 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004289 return false;
4290 }
4291
4292 // address = address + 4;
4293 offset += addr_byte_size;
4294 }
4295 }
4296
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004297 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004298 // MemA[address,4] = PCStoreValue();
4299 if (BitIsSet (registers, 15))
4300 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004301 RegisterInfo pc_reg;
4302 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004303 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004304 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004305 if (!success)
4306 return false;
4307
Caroline Tice8d681f52011-03-17 23:50:16 +00004308 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004309 return false;
4310 }
4311
4312 // if wback then R[n] = R[n] - 4*BitCount(registers);
4313 if (wback)
4314 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004315 offset = (addr_byte_size * BitCount (registers)) * -1;
4316 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4317 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004318 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004319 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4320 return false;
4321 }
4322 }
4323 return true;
4324}
4325
4326// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4327// from a base register. The consecutive memory locations start just above this address, and the address of the last
4328// of those locations can optionally be written back to the base register.
4329bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004330EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004331{
4332#if 0
4333 if ConditionPassed() then
4334 EncodingSpecificOperations();
4335 address = R[n] + 4;
4336
4337 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004338 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004339 if i == n && wback && i != LowestSetBit(registers) then
4340 MemA[address,4] = bits(32) UNKNOWN;
4341 else
4342 MemA[address,4] = R[i];
4343 address = address + 4;
4344
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004345 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004346 MemA[address,4] = PCStoreValue();
4347
4348 if wback then R[n] = R[n] + 4*BitCount(registers);
4349#endif
4350
4351 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004352
Greg Clayton7bc39082011-03-24 23:53:38 +00004353 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004354 {
4355 uint32_t n;
4356 uint32_t registers = 0;
4357 bool wback;
4358 const uint32_t addr_byte_size = GetAddressByteSize();
4359
4360 // EncodingSpecificOperations();
4361 switch (encoding)
4362 {
4363 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004364 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004365 n = Bits32 (opcode, 19, 16);
4366 registers = Bits32 (opcode, 15, 0);
4367 wback = BitIsSet (opcode, 21);
4368
4369 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4370 if ((n == 15) && (BitCount (registers) < 1))
4371 return false;
4372 break;
4373 default:
4374 return false;
4375 }
4376 // address = R[n] + 4;
4377
4378 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004379 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004380 if (!success)
4381 return false;
4382
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004383 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004384
4385 EmulateInstruction::Context context;
4386 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004387 RegisterInfo base_reg;
4388 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004389
4390 uint32_t lowest_set_bit = 14;
4391 // for i = 0 to 14
4392 for (int i = 0; i < 14; ++i)
4393 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004394 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004395 if (BitIsSet (registers, i))
4396 {
4397 if (i < lowest_set_bit)
4398 lowest_set_bit = i;
4399 // if i == n && wback && i != LowestSetBit(registers) then
4400 if ((i == n) && wback && (i != lowest_set_bit))
4401 // MemA[address,4] = bits(32) UNKNOWN;
4402 WriteBits32UnknownToMemory (address + offset);
4403 // else
4404 else
4405 {
4406 // MemA[address,4] = R[i];
4407 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4408 if (!success)
4409 return false;
4410
Greg Claytonc07d4512011-04-26 23:48:45 +00004411 RegisterInfo data_reg;
4412 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004413 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004414 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004415 return false;
4416 }
4417
4418 // address = address + 4;
4419 offset += addr_byte_size;
4420 }
4421 }
4422
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004423 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004424 // MemA[address,4] = PCStoreValue();
4425 if (BitIsSet (registers, 15))
4426 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004427 RegisterInfo pc_reg;
4428 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004429 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004430 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004431 if (!success)
4432 return false;
4433
Caroline Tice8d681f52011-03-17 23:50:16 +00004434 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004435 return false;
4436 }
4437
4438 // if wback then R[n] = R[n] + 4*BitCount(registers);
4439 if (wback)
4440 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004441 offset = addr_byte_size * BitCount (registers);
4442 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4443 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004444 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004445 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4446 return false;
4447 }
4448 }
4449 return true;
4450}
Caroline Tice7fac8572011-02-15 22:53:54 +00004451
4452// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4453// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4454bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004455EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004456{
4457#if 0
4458 if ConditionPassed() then
4459 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4460 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4461 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004462 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004463 MemU[address,4] = R[t];
4464 else // Can only occur before ARMv7
4465 MemU[address,4] = bits(32) UNKNOWN;
4466 if wback then R[n] = offset_addr;
4467#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004468
Caroline Tice7fac8572011-02-15 22:53:54 +00004469 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004470
Greg Clayton7bc39082011-03-24 23:53:38 +00004471 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004472 {
4473 const uint32_t addr_byte_size = GetAddressByteSize();
4474
4475 uint32_t t;
4476 uint32_t n;
4477 uint32_t imm32;
4478 bool index;
4479 bool add;
4480 bool wback;
4481 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4482 switch (encoding)
4483 {
4484 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004485 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004486 t = Bits32 (opcode, 2, 0);
4487 n = Bits32 (opcode, 5, 3);
4488 imm32 = Bits32 (opcode, 10, 6) << 2;
4489
4490 // index = TRUE; add = TRUE; wback = FALSE;
4491 index = true;
4492 add = false;
4493 wback = false;
4494 break;
4495
4496 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004497 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004498 t = Bits32 (opcode, 10, 8);
4499 n = 13;
4500 imm32 = Bits32 (opcode, 7, 0) << 2;
4501
4502 // index = TRUE; add = TRUE; wback = FALSE;
4503 index = true;
4504 add = true;
4505 wback = false;
4506 break;
4507
4508 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004509 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004510 if (Bits32 (opcode, 19, 16) == 15)
4511 return false;
4512
4513 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4514 t = Bits32 (opcode, 15, 12);
4515 n = Bits32 (opcode, 19, 16);
4516 imm32 = Bits32 (opcode, 11, 0);
4517
4518 // index = TRUE; add = TRUE; wback = FALSE;
4519 index = true;
4520 add = true;
4521 wback = false;
4522
4523 // if t == 15 then UNPREDICTABLE;
4524 if (t == 15)
4525 return false;
4526 break;
4527
4528 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004529 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4530 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4531 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004532 if ((Bits32 (opcode, 19, 16) == 15)
4533 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4534 return false;
4535
4536 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4537 t = Bits32 (opcode, 15, 12);
4538 n = Bits32 (opcode, 19, 16);
4539 imm32 = Bits32 (opcode, 7, 0);
4540
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004541 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004542 index = BitIsSet (opcode, 10);
4543 add = BitIsSet (opcode, 9);
4544 wback = BitIsSet (opcode, 8);
4545
4546 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4547 if ((t == 15) || (wback && (n == t)))
4548 return false;
4549 break;
4550
4551 default:
4552 return false;
4553 }
4554
4555 addr_t offset_addr;
4556 addr_t address;
4557
4558 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004559 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004560 if (!success)
4561 return false;
4562
4563 if (add)
4564 offset_addr = base_address + imm32;
4565 else
4566 offset_addr = base_address - imm32;
4567
4568 // address = if index then offset_addr else R[n];
4569 if (index)
4570 address = offset_addr;
4571 else
4572 address = base_address;
4573
4574 EmulateInstruction::Context context;
4575 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004576 RegisterInfo base_reg;
4577 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004578
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004579 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004580 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4581 {
4582 // MemU[address,4] = R[t];
4583 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4584 if (!success)
4585 return false;
4586
Greg Claytonc07d4512011-04-26 23:48:45 +00004587 RegisterInfo data_reg;
4588 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004589 int32_t offset = address - base_address;
4590 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004591 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004592 return false;
4593 }
4594 else
4595 {
4596 // MemU[address,4] = bits(32) UNKNOWN;
4597 WriteBits32UnknownToMemory (address);
4598 }
4599
4600 // if wback then R[n] = offset_addr;
4601 if (wback)
4602 {
4603 context.type = eContextRegisterLoad;
4604 context.SetAddress (offset_addr);
4605 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4606 return false;
4607 }
4608 }
4609 return true;
4610}
Caroline Ticeaf556562011-02-15 18:42:15 +00004611
Caroline Tice3fd63e92011-02-16 00:33:43 +00004612// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4613// word from a register to memory. The offset register value can optionally be shifted.
4614bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004615EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004616{
4617#if 0
4618 if ConditionPassed() then
4619 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4620 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4621 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4622 address = if index then offset_addr else R[n];
4623 if t == 15 then // Only possible for encoding A1
4624 data = PCStoreValue();
4625 else
4626 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004627 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004628 MemU[address,4] = data;
4629 else // Can only occur before ARMv7
4630 MemU[address,4] = bits(32) UNKNOWN;
4631 if wback then R[n] = offset_addr;
4632#endif
4633
4634 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004635
Greg Clayton7bc39082011-03-24 23:53:38 +00004636 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004637 {
4638 const uint32_t addr_byte_size = GetAddressByteSize();
4639
4640 uint32_t t;
4641 uint32_t n;
4642 uint32_t m;
4643 ARM_ShifterType shift_t;
4644 uint32_t shift_n;
4645 bool index;
4646 bool add;
4647 bool wback;
4648
4649 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4650 switch (encoding)
4651 {
4652 case eEncodingT1:
4653 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4654 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4655 t = Bits32 (opcode, 2, 0);
4656 n = Bits32 (opcode, 5, 3);
4657 m = Bits32 (opcode, 8, 6);
4658
4659 // index = TRUE; add = TRUE; wback = FALSE;
4660 index = true;
4661 add = true;
4662 wback = false;
4663
4664 // (shift_t, shift_n) = (SRType_LSL, 0);
4665 shift_t = SRType_LSL;
4666 shift_n = 0;
4667 break;
4668
4669 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004670 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004671 if (Bits32 (opcode, 19, 16) == 15)
4672 return false;
4673
4674 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4675 t = Bits32 (opcode, 15, 12);
4676 n = Bits32 (opcode, 19, 16);
4677 m = Bits32 (opcode, 3, 0);
4678
4679 // index = TRUE; add = TRUE; wback = FALSE;
4680 index = true;
4681 add = true;
4682 wback = false;
4683
4684 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4685 shift_t = SRType_LSL;
4686 shift_n = Bits32 (opcode, 5, 4);
4687
4688 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4689 if ((t == 15) || (BadReg (m)))
4690 return false;
4691 break;
4692
4693 case eEncodingA1:
4694 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004695 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004696 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4697 t = Bits32 (opcode, 15, 12);
4698 n = Bits32 (opcode, 19, 16);
4699 m = Bits32 (opcode, 3, 0);
4700
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004701 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004702 index = BitIsSet (opcode, 24);
4703 add = BitIsSet (opcode, 23);
4704 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4705
4706 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4707 uint32_t typ = Bits32 (opcode, 6, 5);
4708 uint32_t imm5 = Bits32 (opcode, 11, 7);
4709 shift_n = DecodeImmShift(typ, imm5, shift_t);
4710
4711 // if m == 15 then UNPREDICTABLE;
4712 if (m == 15)
4713 return false;
4714
4715 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4716 if (wback && ((n == 15) || (n == t)))
4717 return false;
4718
4719 break;
4720 }
4721 default:
4722 return false;
4723 }
4724
4725 addr_t offset_addr;
4726 addr_t address;
4727 int32_t offset = 0;
4728
4729 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4730 if (!success)
4731 return false;
4732
4733 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4734 if (!success)
4735 return false;
4736
4737 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004738 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004739
4740 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4741 if (add)
4742 offset_addr = base_address + offset;
4743 else
4744 offset_addr = base_address - offset;
4745
4746 // address = if index then offset_addr else R[n];
4747 if (index)
4748 address = offset_addr;
4749 else
4750 address = base_address;
4751
4752 uint32_t data;
4753 // if t == 15 then // Only possible for encoding A1
4754 if (t == 15)
4755 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004756 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004757 else
4758 // data = R[t];
4759 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4760
4761 if (!success)
4762 return false;
4763
4764 EmulateInstruction::Context context;
4765 context.type = eContextRegisterStore;
4766
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004767 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004768 if (UnalignedSupport ()
4769 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4770 || CurrentInstrSet() == eModeARM)
4771 {
4772 // MemU[address,4] = data;
4773
Greg Claytonc07d4512011-04-26 23:48:45 +00004774 RegisterInfo base_reg;
4775 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004776
Greg Claytonc07d4512011-04-26 23:48:45 +00004777 RegisterInfo data_reg;
4778 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004779
4780 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004781 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004782 return false;
4783
4784 }
4785 else
4786 // MemU[address,4] = bits(32) UNKNOWN;
4787 WriteBits32UnknownToMemory (address);
4788
4789 // if wback then R[n] = offset_addr;
4790 if (wback)
4791 {
4792 context.type = eContextRegisterLoad;
4793 context.SetAddress (offset_addr);
4794 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4795 return false;
4796 }
4797
4798 }
4799 return true;
4800}
Caroline Tice73a29de2011-02-16 20:22:22 +00004801
4802bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004803EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004804{
4805#if 0
4806 if ConditionPassed() then
4807 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4808 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4809 address = if index then offset_addr else R[n];
4810 MemU[address,1] = R[t]<7:0>;
4811 if wback then R[n] = offset_addr;
4812#endif
4813
4814
4815 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004816
Greg Clayton7bc39082011-03-24 23:53:38 +00004817 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004818 {
4819 uint32_t t;
4820 uint32_t n;
4821 uint32_t imm32;
4822 bool index;
4823 bool add;
4824 bool wback;
4825 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4826 switch (encoding)
4827 {
4828 case eEncodingT1:
4829 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4830 t = Bits32 (opcode, 2, 0);
4831 n = Bits32 (opcode, 5, 3);
4832 imm32 = Bits32 (opcode, 10, 6);
4833
4834 // index = TRUE; add = TRUE; wback = FALSE;
4835 index = true;
4836 add = true;
4837 wback = false;
4838 break;
4839
4840 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004841 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004842 if (Bits32 (opcode, 19, 16) == 15)
4843 return false;
4844
4845 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4846 t = Bits32 (opcode, 15, 12);
4847 n = Bits32 (opcode, 19, 16);
4848 imm32 = Bits32 (opcode, 11, 0);
4849
4850 // index = TRUE; add = TRUE; wback = FALSE;
4851 index = true;
4852 add = true;
4853 wback = false;
4854
4855 // if BadReg(t) then UNPREDICTABLE;
4856 if (BadReg (t))
4857 return false;
4858 break;
4859
4860 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004861 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4862 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004863 if (Bits32 (opcode, 19, 16) == 15)
4864 return false;
4865
4866 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4867 t = Bits32 (opcode, 15, 12);
4868 n = Bits32 (opcode, 19, 16);
4869 imm32 = Bits32 (opcode, 7, 0);
4870
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004871 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004872 index = BitIsSet (opcode, 10);
4873 add = BitIsSet (opcode, 9);
4874 wback = BitIsSet (opcode, 8);
4875
4876 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4877 if ((BadReg (t)) || (wback && (n == t)))
4878 return false;
4879 break;
4880
4881 default:
4882 return false;
4883 }
4884
4885 addr_t offset_addr;
4886 addr_t address;
4887 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4888 if (!success)
4889 return false;
4890
4891 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4892 if (add)
4893 offset_addr = base_address + imm32;
4894 else
4895 offset_addr = base_address - imm32;
4896
4897 // address = if index then offset_addr else R[n];
4898 if (index)
4899 address = offset_addr;
4900 else
4901 address = base_address;
4902
Caroline Ticecc96eb52011-02-17 19:20:40 +00004903 // MemU[address,1] = R[t]<7:0>
Greg Claytonc07d4512011-04-26 23:48:45 +00004904 RegisterInfo base_reg;
4905 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004906
Greg Claytonc07d4512011-04-26 23:48:45 +00004907 RegisterInfo data_reg;
4908 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004909
4910 EmulateInstruction::Context context;
4911 context.type = eContextRegisterStore;
4912 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4913
4914 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4915 if (!success)
4916 return false;
4917
4918 data = Bits32 (data, 7, 0);
4919
Caroline Ticecc96eb52011-02-17 19:20:40 +00004920 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004921 return false;
4922
4923 // if wback then R[n] = offset_addr;
4924 if (wback)
4925 {
4926 context.type = eContextRegisterLoad;
4927 context.SetAddress (offset_addr);
4928 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4929 return false;
4930 }
4931
4932 }
4933
4934 return true;
4935}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004936
4937// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4938// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4939bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004940EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004941{
4942#if 0
4943 if ConditionPassed() then
4944 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4945 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4946 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4947 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004948 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004949 MemU[address,2] = R[t]<15:0>;
4950 else // Can only occur before ARMv7
4951 MemU[address,2] = bits(16) UNKNOWN;
4952 if wback then R[n] = offset_addr;
4953#endif
4954
4955 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004956
Greg Clayton7bc39082011-03-24 23:53:38 +00004957 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004958 {
4959 uint32_t t;
4960 uint32_t n;
4961 uint32_t m;
4962 bool index;
4963 bool add;
4964 bool wback;
4965 ARM_ShifterType shift_t;
4966 uint32_t shift_n;
4967
4968 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4969 switch (encoding)
4970 {
4971 case eEncodingT1:
4972 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4973 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4974 t = Bits32 (opcode, 2, 0);
4975 n = Bits32 (opcode, 5, 3);
4976 m = Bits32 (opcode, 8, 6);
4977
4978 // index = TRUE; add = TRUE; wback = FALSE;
4979 index = true;
4980 add = true;
4981 wback = false;
4982
4983 // (shift_t, shift_n) = (SRType_LSL, 0);
4984 shift_t = SRType_LSL;
4985 shift_n = 0;
4986
4987 break;
4988
4989 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004990 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004991 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4992 t = Bits32 (opcode, 15, 12);
4993 n = Bits32 (opcode, 19, 16);
4994 m = Bits32 (opcode, 3, 0);
4995 if (n == 15)
4996 return false;
4997
4998 // index = TRUE; add = TRUE; wback = FALSE;
4999 index = true;
5000 add = true;
5001 wback = false;
5002
5003 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5004 shift_t = SRType_LSL;
5005 shift_n = Bits32 (opcode, 5, 4);
5006
5007 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5008 if (BadReg (t) || BadReg (m))
5009 return false;
5010
5011 break;
5012
5013 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005014 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005015 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5016 t = Bits32 (opcode, 15, 12);
5017 n = Bits32 (opcode, 19, 16);
5018 m = Bits32 (opcode, 3, 0);
5019
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005020 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005021 index = BitIsSet (opcode, 24);
5022 add = BitIsSet (opcode, 23);
5023 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5024
5025 // (shift_t, shift_n) = (SRType_LSL, 0);
5026 shift_t = SRType_LSL;
5027 shift_n = 0;
5028
5029 // if t == 15 || m == 15 then UNPREDICTABLE;
5030 if ((t == 15) || (m == 15))
5031 return false;
5032
5033 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5034 if (wback && ((n == 15) || (n == t)))
5035 return false;
5036
5037 break;
5038
5039 default:
5040 return false;
5041 }
5042
5043 uint32_t Rm = ReadCoreReg (m, &success);
5044 if (!success)
5045 return false;
5046
5047 uint32_t Rn = ReadCoreReg (n, &success);
5048 if (!success)
5049 return false;
5050
5051 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5052 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5053
5054 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5055 addr_t offset_addr;
5056 if (add)
5057 offset_addr = Rn + offset;
5058 else
5059 offset_addr = Rn - offset;
5060
5061 // address = if index then offset_addr else R[n];
5062 addr_t address;
5063 if (index)
5064 address = offset_addr;
5065 else
5066 address = Rn;
5067
5068 EmulateInstruction::Context context;
5069 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005070 RegisterInfo base_reg;
5071 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5072 RegisterInfo offset_reg;
5073 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005074
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005075 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005076 if (UnalignedSupport() || BitIsClear (address, 0))
5077 {
5078 // MemU[address,2] = R[t]<15:0>;
5079 uint32_t Rt = ReadCoreReg (t, &success);
5080 if (!success)
5081 return false;
5082
5083 EmulateInstruction::Context context;
5084 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005085 RegisterInfo base_reg;
5086 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5087 RegisterInfo offset_reg;
5088 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5089 RegisterInfo data_reg;
5090 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005091 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5092
5093 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5094 return false;
5095 }
5096 else // Can only occur before ARMv7
5097 {
5098 // MemU[address,2] = bits(16) UNKNOWN;
5099 }
5100
5101 // if wback then R[n] = offset_addr;
5102 if (wback)
5103 {
5104 context.type = eContextAdjustBaseRegister;
5105 context.SetAddress (offset_addr);
5106 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5107 return false;
5108 }
5109 }
5110
5111 return true;
5112}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005113
Johnny Chen157b9592011-02-18 21:13:05 +00005114// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5115// and writes the result to the destination register. It can optionally update the condition flags
5116// based on the result.
5117bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005118EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005119{
5120#if 0
5121 // ARM pseudo code...
5122 if ConditionPassed() then
5123 EncodingSpecificOperations();
5124 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5125 if d == 15 then // Can only occur for ARM encoding
5126 ALUWritePC(result); // setflags is always FALSE here
5127 else
5128 R[d] = result;
5129 if setflags then
5130 APSR.N = result<31>;
5131 APSR.Z = IsZeroBit(result);
5132 APSR.C = carry;
5133 APSR.V = overflow;
5134#endif
5135
5136 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005137
Greg Clayton7bc39082011-03-24 23:53:38 +00005138 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005139 {
5140 uint32_t Rd, Rn;
5141 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5142 bool setflags;
5143 switch (encoding)
5144 {
5145 case eEncodingT1:
5146 Rd = Bits32(opcode, 11, 8);
5147 Rn = Bits32(opcode, 19, 16);
5148 setflags = BitIsSet(opcode, 20);
5149 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5150 if (BadReg(Rd) || BadReg(Rn))
5151 return false;
5152 break;
5153 case eEncodingA1:
5154 Rd = Bits32(opcode, 15, 12);
5155 Rn = Bits32(opcode, 19, 16);
5156 setflags = BitIsSet(opcode, 20);
5157 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005158
Johnny Chen157b9592011-02-18 21:13:05 +00005159 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005160 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005161 break;
5162 default:
5163 return false;
5164 }
5165
5166 // Read the first operand.
5167 int32_t val1 = ReadCoreReg(Rn, &success);
5168 if (!success)
5169 return false;
5170
5171 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5172
5173 EmulateInstruction::Context context;
5174 context.type = EmulateInstruction::eContextImmediate;
5175 context.SetNoArgs ();
5176
5177 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5178 return false;
5179 }
5180 return true;
5181}
5182
5183// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5184// register value, and writes the result to the destination register. It can optionally update the
5185// condition flags based on the result.
5186bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005187EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005188{
5189#if 0
5190 // ARM pseudo code...
5191 if ConditionPassed() then
5192 EncodingSpecificOperations();
5193 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5194 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5195 if d == 15 then // Can only occur for ARM encoding
5196 ALUWritePC(result); // setflags is always FALSE here
5197 else
5198 R[d] = result;
5199 if setflags then
5200 APSR.N = result<31>;
5201 APSR.Z = IsZeroBit(result);
5202 APSR.C = carry;
5203 APSR.V = overflow;
5204#endif
5205
5206 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005207
Greg Clayton7bc39082011-03-24 23:53:38 +00005208 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005209 {
5210 uint32_t Rd, Rn, Rm;
5211 ARM_ShifterType shift_t;
5212 uint32_t shift_n; // the shift applied to the value read from Rm
5213 bool setflags;
5214 switch (encoding)
5215 {
5216 case eEncodingT1:
5217 Rd = Rn = Bits32(opcode, 2, 0);
5218 Rm = Bits32(opcode, 5, 3);
5219 setflags = !InITBlock();
5220 shift_t = SRType_LSL;
5221 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005222 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005223 case eEncodingT2:
5224 Rd = Bits32(opcode, 11, 8);
5225 Rn = Bits32(opcode, 19, 16);
5226 Rm = Bits32(opcode, 3, 0);
5227 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005228 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005229 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5230 return false;
5231 break;
5232 case eEncodingA1:
5233 Rd = Bits32(opcode, 15, 12);
5234 Rn = Bits32(opcode, 19, 16);
5235 Rm = Bits32(opcode, 3, 0);
5236 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005237 shift_n = DecodeImmShiftARM(opcode, shift_t);
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 // Read the second operand.
5252 int32_t val2 = ReadCoreReg(Rm, &success);
5253 if (!success)
5254 return false;
5255
5256 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5257 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5258
5259 EmulateInstruction::Context context;
5260 context.type = EmulateInstruction::eContextImmediate;
5261 context.SetNoArgs ();
5262
5263 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5264 return false;
5265 }
5266 return true;
5267}
5268
Johnny Chena695f952011-02-23 21:24:25 +00005269// This instruction adds an immediate value to the PC value to form a PC-relative address,
5270// and writes the result to the destination register.
5271bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005272EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005273{
5274#if 0
5275 // ARM pseudo code...
5276 if ConditionPassed() then
5277 EncodingSpecificOperations();
5278 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5279 if d == 15 then // Can only occur for ARM encodings
5280 ALUWritePC(result);
5281 else
5282 R[d] = result;
5283#endif
5284
5285 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005286
Greg Clayton7bc39082011-03-24 23:53:38 +00005287 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005288 {
5289 uint32_t Rd;
5290 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5291 bool add;
5292 switch (encoding)
5293 {
5294 case eEncodingT1:
5295 Rd = Bits32(opcode, 10, 8);
5296 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5297 break;
5298 case eEncodingT2:
5299 case eEncodingT3:
5300 Rd = Bits32(opcode, 11, 8);
5301 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5302 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5303 if (BadReg(Rd))
5304 return false;
5305 break;
5306 case eEncodingA1:
5307 case eEncodingA2:
5308 Rd = Bits32(opcode, 15, 12);
5309 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5310 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5311 break;
5312 default:
5313 return false;
5314 }
5315
5316 // Read the PC value.
5317 uint32_t pc = ReadCoreReg(PC_REG, &success);
5318 if (!success)
5319 return false;
5320
5321 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5322
5323 EmulateInstruction::Context context;
5324 context.type = EmulateInstruction::eContextImmediate;
5325 context.SetNoArgs ();
5326
5327 if (!WriteCoreReg(context, result, Rd))
5328 return false;
5329 }
5330 return true;
5331}
5332
Johnny Chene97c0d52011-02-18 19:32:20 +00005333// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5334// to the destination register. It can optionally update the condition flags based on the result.
5335bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005336EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005337{
5338#if 0
5339 // ARM pseudo code...
5340 if ConditionPassed() then
5341 EncodingSpecificOperations();
5342 result = R[n] AND imm32;
5343 if d == 15 then // Can only occur for ARM encoding
5344 ALUWritePC(result); // setflags is always FALSE here
5345 else
5346 R[d] = result;
5347 if setflags then
5348 APSR.N = result<31>;
5349 APSR.Z = IsZeroBit(result);
5350 APSR.C = carry;
5351 // APSR.V unchanged
5352#endif
5353
5354 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005355
Greg Clayton7bc39082011-03-24 23:53:38 +00005356 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005357 {
5358 uint32_t Rd, Rn;
5359 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5360 bool setflags;
5361 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5362 switch (encoding)
5363 {
5364 case eEncodingT1:
5365 Rd = Bits32(opcode, 11, 8);
5366 Rn = Bits32(opcode, 19, 16);
5367 setflags = BitIsSet(opcode, 20);
5368 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005369 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005370 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005371 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005372 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5373 return false;
5374 break;
5375 case eEncodingA1:
5376 Rd = Bits32(opcode, 15, 12);
5377 Rn = Bits32(opcode, 19, 16);
5378 setflags = BitIsSet(opcode, 20);
5379 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005380
Johnny Chene97c0d52011-02-18 19:32:20 +00005381 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005382 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005383 break;
5384 default:
5385 return false;
5386 }
5387
Johnny Chene97c0d52011-02-18 19:32:20 +00005388 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005389 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005390 if (!success)
5391 return false;
5392
5393 uint32_t result = val1 & imm32;
5394
5395 EmulateInstruction::Context context;
5396 context.type = EmulateInstruction::eContextImmediate;
5397 context.SetNoArgs ();
5398
5399 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5400 return false;
5401 }
5402 return true;
5403}
5404
5405// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5406// and writes the result to the destination register. It can optionally update the condition flags
5407// based on the result.
5408bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005409EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005410{
5411#if 0
5412 // ARM pseudo code...
5413 if ConditionPassed() then
5414 EncodingSpecificOperations();
5415 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5416 result = R[n] AND shifted;
5417 if d == 15 then // Can only occur for ARM encoding
5418 ALUWritePC(result); // setflags is always FALSE here
5419 else
5420 R[d] = result;
5421 if setflags then
5422 APSR.N = result<31>;
5423 APSR.Z = IsZeroBit(result);
5424 APSR.C = carry;
5425 // APSR.V unchanged
5426#endif
5427
5428 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005429
Greg Clayton7bc39082011-03-24 23:53:38 +00005430 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005431 {
5432 uint32_t Rd, Rn, Rm;
5433 ARM_ShifterType shift_t;
5434 uint32_t shift_n; // the shift applied to the value read from Rm
5435 bool setflags;
5436 uint32_t carry;
5437 switch (encoding)
5438 {
5439 case eEncodingT1:
5440 Rd = Rn = Bits32(opcode, 2, 0);
5441 Rm = Bits32(opcode, 5, 3);
5442 setflags = !InITBlock();
5443 shift_t = SRType_LSL;
5444 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005445 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005446 case eEncodingT2:
5447 Rd = Bits32(opcode, 11, 8);
5448 Rn = Bits32(opcode, 19, 16);
5449 Rm = Bits32(opcode, 3, 0);
5450 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005451 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005452 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005453 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005454 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005455 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5456 return false;
5457 break;
5458 case eEncodingA1:
5459 Rd = Bits32(opcode, 15, 12);
5460 Rn = Bits32(opcode, 19, 16);
5461 Rm = Bits32(opcode, 3, 0);
5462 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005463 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005464
Johnny Chene97c0d52011-02-18 19:32:20 +00005465 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005466 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005467 break;
5468 default:
5469 return false;
5470 }
5471
Johnny Chene97c0d52011-02-18 19:32:20 +00005472 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005473 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005474 if (!success)
5475 return false;
5476
5477 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005478 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005479 if (!success)
5480 return false;
5481
5482 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5483 uint32_t result = val1 & shifted;
5484
5485 EmulateInstruction::Context context;
5486 context.type = EmulateInstruction::eContextImmediate;
5487 context.SetNoArgs ();
5488
5489 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5490 return false;
5491 }
5492 return true;
5493}
5494
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005495// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5496// immediate value, and writes the result to the destination register. It can optionally update the
5497// condition flags based on the result.
5498bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005499EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005500{
5501#if 0
5502 // ARM pseudo code...
5503 if ConditionPassed() then
5504 EncodingSpecificOperations();
5505 result = R[n] AND NOT(imm32);
5506 if d == 15 then // Can only occur for ARM encoding
5507 ALUWritePC(result); // setflags is always FALSE here
5508 else
5509 R[d] = result;
5510 if setflags then
5511 APSR.N = result<31>;
5512 APSR.Z = IsZeroBit(result);
5513 APSR.C = carry;
5514 // APSR.V unchanged
5515#endif
5516
5517 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005518
Greg Clayton7bc39082011-03-24 23:53:38 +00005519 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005520 {
5521 uint32_t Rd, Rn;
5522 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5523 bool setflags;
5524 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5525 switch (encoding)
5526 {
5527 case eEncodingT1:
5528 Rd = Bits32(opcode, 11, 8);
5529 Rn = Bits32(opcode, 19, 16);
5530 setflags = BitIsSet(opcode, 20);
5531 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5532 if (BadReg(Rd) || BadReg(Rn))
5533 return false;
5534 break;
5535 case eEncodingA1:
5536 Rd = Bits32(opcode, 15, 12);
5537 Rn = Bits32(opcode, 19, 16);
5538 setflags = BitIsSet(opcode, 20);
5539 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005540
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005541 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005542 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005543 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005544 break;
5545 default:
5546 return false;
5547 }
5548
5549 // Read the first operand.
5550 uint32_t val1 = ReadCoreReg(Rn, &success);
5551 if (!success)
5552 return false;
5553
5554 uint32_t result = val1 & ~imm32;
5555
5556 EmulateInstruction::Context context;
5557 context.type = EmulateInstruction::eContextImmediate;
5558 context.SetNoArgs ();
5559
5560 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5561 return false;
5562 }
5563 return true;
5564}
5565
5566// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5567// optionally-shifted register value, and writes the result to the destination register.
5568// It can optionally update the condition flags based on the result.
5569bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005570EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005571{
5572#if 0
5573 // ARM pseudo code...
5574 if ConditionPassed() then
5575 EncodingSpecificOperations();
5576 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5577 result = R[n] AND NOT(shifted);
5578 if d == 15 then // Can only occur for ARM encoding
5579 ALUWritePC(result); // setflags is always FALSE here
5580 else
5581 R[d] = result;
5582 if setflags then
5583 APSR.N = result<31>;
5584 APSR.Z = IsZeroBit(result);
5585 APSR.C = carry;
5586 // APSR.V unchanged
5587#endif
5588
5589 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005590
Greg Clayton7bc39082011-03-24 23:53:38 +00005591 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005592 {
5593 uint32_t Rd, Rn, Rm;
5594 ARM_ShifterType shift_t;
5595 uint32_t shift_n; // the shift applied to the value read from Rm
5596 bool setflags;
5597 uint32_t carry;
5598 switch (encoding)
5599 {
5600 case eEncodingT1:
5601 Rd = Rn = Bits32(opcode, 2, 0);
5602 Rm = Bits32(opcode, 5, 3);
5603 setflags = !InITBlock();
5604 shift_t = SRType_LSL;
5605 shift_n = 0;
5606 break;
5607 case eEncodingT2:
5608 Rd = Bits32(opcode, 11, 8);
5609 Rn = Bits32(opcode, 19, 16);
5610 Rm = Bits32(opcode, 3, 0);
5611 setflags = BitIsSet(opcode, 20);
5612 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5613 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5614 return false;
5615 break;
5616 case eEncodingA1:
5617 Rd = Bits32(opcode, 15, 12);
5618 Rn = Bits32(opcode, 19, 16);
5619 Rm = Bits32(opcode, 3, 0);
5620 setflags = BitIsSet(opcode, 20);
5621 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005622
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005623 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005624 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005625 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005626 break;
5627 default:
5628 return false;
5629 }
5630
5631 // Read the first operand.
5632 uint32_t val1 = ReadCoreReg(Rn, &success);
5633 if (!success)
5634 return false;
5635
5636 // Read the second operand.
5637 uint32_t val2 = ReadCoreReg(Rm, &success);
5638 if (!success)
5639 return false;
5640
5641 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5642 uint32_t result = val1 & ~shifted;
5643
5644 EmulateInstruction::Context context;
5645 context.type = EmulateInstruction::eContextImmediate;
5646 context.SetNoArgs ();
5647
5648 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5649 return false;
5650 }
5651 return true;
5652}
5653
Caroline Tice4d729c52011-02-18 00:55:53 +00005654// 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 +00005655// 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 +00005656bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005657EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005658{
5659#if 0
5660 if ConditionPassed() then
5661 EncodingSpecificOperations();
5662 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5663 address = if index then offset_addr else R[n];
5664 data = MemU[address,4];
5665 if wback then R[n] = offset_addr;
5666 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005667 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5668 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005669 R[t] = data;
5670 else // Can only apply before ARMv7
5671 R[t] = ROR(data, 8*UInt(address<1:0>));
5672#endif
5673
5674 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005675
Greg Clayton7bc39082011-03-24 23:53:38 +00005676 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005677 {
5678 const uint32_t addr_byte_size = GetAddressByteSize();
5679
5680 uint32_t t;
5681 uint32_t n;
5682 uint32_t imm32;
5683 bool index;
5684 bool add;
5685 bool wback;
5686
5687 switch (encoding)
5688 {
5689 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005690 // if Rn == '1111' then SEE LDR (literal);
5691 // if P == '0' && W == '1' then SEE LDRT;
5692 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005693 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5694 t = Bits32 (opcode, 15, 12);
5695 n = Bits32 (opcode, 19, 16);
5696 imm32 = Bits32 (opcode, 11, 0);
5697
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005698 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5699 index = BitIsSet (opcode, 24);
5700 add = BitIsSet (opcode, 23);
5701 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005702
5703 // if wback && n == t then UNPREDICTABLE;
5704 if (wback && (n == t))
5705 return false;
5706
5707 break;
5708
5709 default:
5710 return false;
5711 }
5712
5713 addr_t address;
5714 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005715 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005716 if (!success)
5717 return false;
5718
5719 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5720 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005721 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005722 else
5723 offset_addr = base_address - imm32;
5724
5725 // address = if index then offset_addr else R[n];
5726 if (index)
5727 address = offset_addr;
5728 else
5729 address = base_address;
5730
5731 // data = MemU[address,4];
5732
Greg Claytonc07d4512011-04-26 23:48:45 +00005733 RegisterInfo base_reg;
5734 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4d729c52011-02-18 00:55:53 +00005735
5736 EmulateInstruction::Context context;
5737 context.type = eContextRegisterLoad;
5738 context.SetRegisterPlusOffset (base_reg, address - base_address);
5739
5740 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5741 if (!success)
5742 return false;
5743
5744 // if wback then R[n] = offset_addr;
5745 if (wback)
5746 {
5747 context.type = eContextAdjustBaseRegister;
5748 context.SetAddress (offset_addr);
5749 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5750 return false;
5751 }
5752
5753 // if t == 15 then
5754 if (t == 15)
5755 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005756 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005757 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5758 {
5759 // LoadWritePC (data);
5760 context.type = eContextRegisterLoad;
5761 context.SetRegisterPlusOffset (base_reg, address - base_address);
5762 LoadWritePC (context, data);
5763 }
5764 else
5765 return false;
5766 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005767 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005768 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5769 {
5770 // R[t] = data;
5771 context.type = eContextRegisterLoad;
5772 context.SetRegisterPlusOffset (base_reg, address - base_address);
5773 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5774 return false;
5775 }
5776 // else // Can only apply before ARMv7
5777 else
5778 {
5779 // R[t] = ROR(data, 8*UInt(address<1:0>));
5780 data = ROR (data, Bits32 (address, 1, 0));
5781 context.type = eContextRegisterLoad;
5782 context.SetImmediate (data);
5783 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5784 return false;
5785 }
5786
5787 }
5788 return true;
5789}
5790
Caroline Ticefe479112011-02-18 18:52:37 +00005791// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5792// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5793bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005794EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005795{
5796#if 0
5797 if ConditionPassed() then
5798 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5799 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5800 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5801 address = if index then offset_addr else R[n];
5802 data = MemU[address,4];
5803 if wback then R[n] = offset_addr;
5804 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005805 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5806 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005807 R[t] = data;
5808 else // Can only apply before ARMv7
5809 if CurrentInstrSet() == InstrSet_ARM then
5810 R[t] = ROR(data, 8*UInt(address<1:0>));
5811 else
5812 R[t] = bits(32) UNKNOWN;
5813#endif
5814
5815 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005816
Greg Clayton7bc39082011-03-24 23:53:38 +00005817 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005818 {
5819 const uint32_t addr_byte_size = GetAddressByteSize();
5820
5821 uint32_t t;
5822 uint32_t n;
5823 uint32_t m;
5824 bool index;
5825 bool add;
5826 bool wback;
5827 ARM_ShifterType shift_t;
5828 uint32_t shift_n;
5829
5830 switch (encoding)
5831 {
5832 case eEncodingT1:
5833 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5834 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5835 t = Bits32 (opcode, 2, 0);
5836 n = Bits32 (opcode, 5, 3);
5837 m = Bits32 (opcode, 8, 6);
5838
5839 // index = TRUE; add = TRUE; wback = FALSE;
5840 index = true;
5841 add = true;
5842 wback = false;
5843
5844 // (shift_t, shift_n) = (SRType_LSL, 0);
5845 shift_t = SRType_LSL;
5846 shift_n = 0;
5847
5848 break;
5849
5850 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005851 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005852 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5853 t = Bits32 (opcode, 15, 12);
5854 n = Bits32 (opcode, 19, 16);
5855 m = Bits32 (opcode, 3, 0);
5856
5857 // index = TRUE; add = TRUE; wback = FALSE;
5858 index = true;
5859 add = true;
5860 wback = false;
5861
5862 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5863 shift_t = SRType_LSL;
5864 shift_n = Bits32 (opcode, 5, 4);
5865
5866 // if BadReg(m) then UNPREDICTABLE;
5867 if (BadReg (m))
5868 return false;
5869
5870 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5871 if ((t == 15) && InITBlock() && !LastInITBlock())
5872 return false;
5873
5874 break;
5875
5876 case eEncodingA1:
5877 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005878 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005879 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5880 t = Bits32 (opcode, 15, 12);
5881 n = Bits32 (opcode, 19, 16);
5882 m = Bits32 (opcode, 3, 0);
5883
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005884 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005885 index = BitIsSet (opcode, 24);
5886 add = BitIsSet (opcode, 23);
5887 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5888
5889 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5890 uint32_t type = Bits32 (opcode, 6, 5);
5891 uint32_t imm5 = Bits32 (opcode, 11, 7);
5892 shift_n = DecodeImmShift (type, imm5, shift_t);
5893
5894 // if m == 15 then UNPREDICTABLE;
5895 if (m == 15)
5896 return false;
5897
5898 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5899 if (wback && ((n == 15) || (n == t)))
5900 return false;
5901 }
5902 break;
5903
5904
5905 default:
5906 return false;
5907 }
5908
5909 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5910 if (!success)
5911 return false;
5912
5913 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5914 if (!success)
5915 return false;
5916
5917 addr_t offset_addr;
5918 addr_t address;
5919
5920 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Greg Claytonb3448432011-03-24 21:19:54 +00005921 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005922
5923 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5924 if (add)
5925 offset_addr = Rn + offset;
5926 else
5927 offset_addr = Rn - offset;
5928
5929 // address = if index then offset_addr else R[n];
5930 if (index)
5931 address = offset_addr;
5932 else
5933 address = Rn;
5934
5935 // data = MemU[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +00005936 RegisterInfo base_reg;
5937 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefe479112011-02-18 18:52:37 +00005938
5939 EmulateInstruction::Context context;
5940 context.type = eContextRegisterLoad;
5941 context.SetRegisterPlusOffset (base_reg, address - Rn);
5942
5943 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5944 if (!success)
5945 return false;
5946
5947 // if wback then R[n] = offset_addr;
5948 if (wback)
5949 {
5950 context.type = eContextAdjustBaseRegister;
5951 context.SetAddress (offset_addr);
5952 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5953 return false;
5954 }
5955
5956 // if t == 15 then
5957 if (t == 15)
5958 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005959 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005960 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5961 {
5962 context.type = eContextRegisterLoad;
5963 context.SetRegisterPlusOffset (base_reg, address - Rn);
5964 LoadWritePC (context, data);
5965 }
5966 else
5967 return false;
5968 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005969 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005970 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5971 {
5972 // R[t] = data;
5973 context.type = eContextRegisterLoad;
5974 context.SetRegisterPlusOffset (base_reg, address - Rn);
5975 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5976 return false;
5977 }
5978 else // Can only apply before ARMv7
5979 {
5980 // if CurrentInstrSet() == InstrSet_ARM then
5981 if (CurrentInstrSet () == eModeARM)
5982 {
5983 // R[t] = ROR(data, 8*UInt(address<1:0>));
5984 data = ROR (data, Bits32 (address, 1, 0));
5985 context.type = eContextRegisterLoad;
5986 context.SetImmediate (data);
5987 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5988 return false;
5989 }
5990 else
5991 {
5992 // R[t] = bits(32) UNKNOWN;
5993 WriteBits32Unknown (t);
5994 }
5995 }
5996 }
5997 return true;
5998}
Caroline Tice21b604b2011-02-18 21:06:04 +00005999
6000// LDRB (immediate, Thumb)
6001bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006002EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00006003{
6004#if 0
6005 if ConditionPassed() then
6006 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6007 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6008 address = if index then offset_addr else R[n];
6009 R[t] = ZeroExtend(MemU[address,1], 32);
6010 if wback then R[n] = offset_addr;
6011#endif
6012
6013 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00006014
Greg Clayton7bc39082011-03-24 23:53:38 +00006015 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00006016 {
6017 uint32_t t;
6018 uint32_t n;
6019 uint32_t imm32;
6020 bool index;
6021 bool add;
6022 bool wback;
6023
6024 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6025 switch (encoding)
6026 {
6027 case eEncodingT1:
6028 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6029 t = Bits32 (opcode, 2, 0);
6030 n = Bits32 (opcode, 5, 3);
6031 imm32 = Bits32 (opcode, 10, 6);
6032
6033 // index = TRUE; add = TRUE; wback = FALSE;
6034 index = true;
6035 add = true;
6036 wback= false;
6037
6038 break;
6039
6040 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006041 // if Rt == '1111' then SEE PLD;
6042 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006043 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6044 t = Bits32 (opcode, 15, 12);
6045 n = Bits32 (opcode, 19, 16);
6046 imm32 = Bits32 (opcode, 11, 0);
6047
6048 // index = TRUE; add = TRUE; wback = FALSE;
6049 index = true;
6050 add = true;
6051 wback = false;
6052
6053 // if t == 13 then UNPREDICTABLE;
6054 if (t == 13)
6055 return false;
6056
6057 break;
6058
6059 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006060 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6061 // if Rn == '1111' then SEE LDRB (literal);
6062 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6063 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006064 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6065 return false;
6066
6067 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6068 t = Bits32 (opcode, 15, 12);
6069 n = Bits32 (opcode, 19, 16);
6070 imm32 = Bits32 (opcode, 7, 0);
6071
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006072 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006073 index = BitIsSet (opcode, 10);
6074 add = BitIsSet (opcode, 9);
6075 wback = BitIsSet (opcode, 8);
6076
6077 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6078 if (BadReg (t) || (wback && (n == t)))
6079 return false;
6080
6081 break;
6082
6083 default:
6084 return false;
6085 }
6086
6087 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6088 if (!success)
6089 return false;
6090
6091 addr_t address;
6092 addr_t offset_addr;
6093
6094 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6095 if (add)
6096 offset_addr = Rn + imm32;
6097 else
6098 offset_addr = Rn - imm32;
6099
6100 // address = if index then offset_addr else R[n];
6101 if (index)
6102 address = offset_addr;
6103 else
6104 address = Rn;
6105
6106 // R[t] = ZeroExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006107 RegisterInfo base_reg;
6108 RegisterInfo data_reg;
6109 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6110 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice21b604b2011-02-18 21:06:04 +00006111
6112 EmulateInstruction::Context context;
6113 context.type = eContextRegisterLoad;
6114 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6115
6116 uint64_t data = MemURead (context, address, 1, 0, &success);
6117 if (!success)
6118 return false;
6119
6120 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6121 return false;
6122
6123 // if wback then R[n] = offset_addr;
6124 if (wback)
6125 {
6126 context.type = eContextAdjustBaseRegister;
6127 context.SetAddress (offset_addr);
6128 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6129 return false;
6130 }
6131 }
6132 return true;
6133}
Caroline Ticef55261f2011-02-18 22:24:22 +00006134
6135// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6136// zero-extends it to form a 32-bit word and writes it to a register.
6137bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006138EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006139{
6140#if 0
6141 if ConditionPassed() then
6142 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6143 base = Align(PC,4);
6144 address = if add then (base + imm32) else (base - imm32);
6145 R[t] = ZeroExtend(MemU[address,1], 32);
6146#endif
6147
6148 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006149
Greg Clayton7bc39082011-03-24 23:53:38 +00006150 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006151 {
6152 uint32_t t;
6153 uint32_t imm32;
6154 bool add;
6155 switch (encoding)
6156 {
6157 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006158 // if Rt == '1111' then SEE PLD;
6159 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006160 t = Bits32 (opcode, 15, 12);
6161 imm32 = Bits32 (opcode, 11, 0);
6162 add = BitIsSet (opcode, 23);
6163
6164 // if t == 13 then UNPREDICTABLE;
6165 if (t == 13)
6166 return false;
6167
6168 break;
6169
6170 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006171 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006172 t = Bits32 (opcode, 15, 12);
6173 imm32 = Bits32 (opcode, 11, 0);
6174 add = BitIsSet (opcode, 23);
6175
6176 // if t == 15 then UNPREDICTABLE;
6177 if (t == 15)
6178 return false;
6179 break;
6180
6181 default:
6182 return false;
6183 }
6184
6185 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006186 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006187 if (!success)
6188 return false;
6189
6190 uint32_t base = AlignPC (pc_val);
6191
6192 addr_t address;
6193 // address = if add then (base + imm32) else (base - imm32);
6194 if (add)
6195 address = base + imm32;
6196 else
6197 address = base - imm32;
6198
6199 // R[t] = ZeroExtend(MemU[address,1], 32);
6200 EmulateInstruction::Context context;
6201 context.type = eContextRelativeBranchImmediate;
6202 context.SetImmediate (address - base);
6203
6204 uint64_t data = MemURead (context, address, 1, 0, &success);
6205 if (!success)
6206 return false;
6207
6208 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6209 return false;
6210 }
6211 return true;
6212}
Caroline Tice30fec122011-02-18 23:52:21 +00006213
6214// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6215// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6216// optionally be shifted.
6217bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006218EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006219{
6220#if 0
6221 if ConditionPassed() then
6222 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6223 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6224 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6225 address = if index then offset_addr else R[n];
6226 R[t] = ZeroExtend(MemU[address,1],32);
6227 if wback then R[n] = offset_addr;
6228#endif
6229
6230 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006231
Greg Clayton7bc39082011-03-24 23:53:38 +00006232 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006233 {
6234 uint32_t t;
6235 uint32_t n;
6236 uint32_t m;
6237 bool index;
6238 bool add;
6239 bool wback;
6240 ARM_ShifterType shift_t;
6241 uint32_t shift_n;
6242
6243 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6244 switch (encoding)
6245 {
6246 case eEncodingT1:
6247 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6248 t = Bits32 (opcode, 2, 0);
6249 n = Bits32 (opcode, 5, 3);
6250 m = Bits32 (opcode, 8, 6);
6251
6252 // index = TRUE; add = TRUE; wback = FALSE;
6253 index = true;
6254 add = true;
6255 wback = false;
6256
6257 // (shift_t, shift_n) = (SRType_LSL, 0);
6258 shift_t = SRType_LSL;
6259 shift_n = 0;
6260 break;
6261
6262 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006263 // if Rt == '1111' then SEE PLD;
6264 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006265 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6266 t = Bits32 (opcode, 15, 12);
6267 n = Bits32 (opcode, 19, 16);
6268 m = Bits32 (opcode, 3, 0);
6269
6270 // index = TRUE; add = TRUE; wback = FALSE;
6271 index = true;
6272 add = true;
6273 wback = false;
6274
6275 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6276 shift_t = SRType_LSL;
6277 shift_n = Bits32 (opcode, 5, 4);
6278
6279 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6280 if ((t == 13) || BadReg (m))
6281 return false;
6282 break;
6283
6284 case eEncodingA1:
6285 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006286 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006287 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6288 t = Bits32 (opcode, 15, 12);
6289 n = Bits32 (opcode, 19, 16);
6290 m = Bits32 (opcode, 3, 0);
6291
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006292 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006293 index = BitIsSet (opcode, 24);
6294 add = BitIsSet (opcode, 23);
6295 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6296
6297 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6298 uint32_t type = Bits32 (opcode, 6, 5);
6299 uint32_t imm5 = Bits32 (opcode, 11, 7);
6300 shift_n = DecodeImmShift (type, imm5, shift_t);
6301
6302 // if t == 15 || m == 15 then UNPREDICTABLE;
6303 if ((t == 15) || (m == 15))
6304 return false;
6305
6306 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6307 if (wback && ((n == 15) || (n == t)))
6308 return false;
6309 }
6310 break;
6311
6312 default:
6313 return false;
6314 }
6315
6316 addr_t offset_addr;
6317 addr_t address;
6318
6319 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6320 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6321 if (!success)
6322 return false;
6323
6324 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6325
6326 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6327 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6328 if (!success)
6329 return false;
6330
6331 if (add)
6332 offset_addr = Rn + offset;
6333 else
6334 offset_addr = Rn - offset;
6335
6336 // address = if index then offset_addr else R[n];
6337 if (index)
6338 address = offset_addr;
6339 else
6340 address = Rn;
6341
6342 // R[t] = ZeroExtend(MemU[address,1],32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006343 RegisterInfo base_reg;
6344 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice30fec122011-02-18 23:52:21 +00006345
6346 EmulateInstruction::Context context;
6347 context.type = eContextRegisterLoad;
6348 context.SetRegisterPlusOffset (base_reg, address - Rn);
6349
6350 uint64_t data = MemURead (context, address, 1, 0, &success);
6351 if (!success)
6352 return false;
6353
6354 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6355 return false;
6356
6357 // if wback then R[n] = offset_addr;
6358 if (wback)
6359 {
6360 context.type = eContextAdjustBaseRegister;
6361 context.SetAddress (offset_addr);
6362 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6363 return false;
6364 }
6365 }
6366 return true;
6367}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006368
6369// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6370// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6371// post-indexed, or pre-indexed addressing.
6372bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006373EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006374{
6375#if 0
6376 if ConditionPassed() then
6377 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6378 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6379 address = if index then offset_addr else R[n];
6380 data = MemU[address,2];
6381 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006382 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006383 R[t] = ZeroExtend(data, 32);
6384 else // Can only apply before ARMv7
6385 R[t] = bits(32) UNKNOWN;
6386#endif
6387
6388
6389 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006390
Greg Clayton7bc39082011-03-24 23:53:38 +00006391 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006392 {
6393 uint32_t t;
6394 uint32_t n;
6395 uint32_t imm32;
6396 bool index;
6397 bool add;
6398 bool wback;
6399
6400 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6401 switch (encoding)
6402 {
6403 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006404 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006405 t = Bits32 (opcode, 2, 0);
6406 n = Bits32 (opcode, 5, 3);
6407 imm32 = Bits32 (opcode, 10, 6) << 1;
6408
6409 // index = TRUE; add = TRUE; wback = FALSE;
6410 index = true;
6411 add = true;
6412 wback = false;
6413
6414 break;
6415
6416 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006417 // if Rt == '1111' then SEE "Unallocated memory hints";
6418 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006419 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6420 t = Bits32 (opcode, 15, 12);
6421 n = Bits32 (opcode, 19, 16);
6422 imm32 = Bits32 (opcode, 11, 0);
6423
6424 // index = TRUE; add = TRUE; wback = FALSE;
6425 index = true;
6426 add = true;
6427 wback = false;
6428
6429 // if t == 13 then UNPREDICTABLE;
6430 if (t == 13)
6431 return false;
6432 break;
6433
6434 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006435 // if Rn == '1111' then SEE LDRH (literal);
6436 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6437 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6438 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006439 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6440 return false;
6441
6442 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6443 t = Bits32 (opcode, 15, 12);
6444 n = Bits32 (opcode, 19, 16);
6445 imm32 = Bits32 (opcode, 7, 0);
6446
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006447 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006448 index = BitIsSet (opcode, 10);
6449 add = BitIsSet (opcode, 9);
6450 wback = BitIsSet (opcode, 8);
6451
6452 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6453 if (BadReg (t) || (wback && (n == t)))
6454 return false;
6455 break;
6456
6457 default:
6458 return false;
6459 }
6460
6461 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6462 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6463 if (!success)
6464 return false;
6465
6466 addr_t offset_addr;
6467 addr_t address;
6468
6469 if (add)
6470 offset_addr = Rn + imm32;
6471 else
6472 offset_addr = Rn - imm32;
6473
6474 // address = if index then offset_addr else R[n];
6475 if (index)
6476 address = offset_addr;
6477 else
6478 address = Rn;
6479
6480 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006481 RegisterInfo base_reg;
6482 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006483
6484 EmulateInstruction::Context context;
6485 context.type = eContextRegisterLoad;
6486 context.SetRegisterPlusOffset (base_reg, address - Rn);
6487
6488 uint64_t data = MemURead (context, address, 2, 0, &success);
6489 if (!success)
6490 return false;
6491
6492 // if wback then R[n] = offset_addr;
6493 if (wback)
6494 {
6495 context.type = eContextAdjustBaseRegister;
6496 context.SetAddress (offset_addr);
6497 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6498 return false;
6499 }
6500
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006501 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006502 if (UnalignedSupport () || BitIsClear (address, 0))
6503 {
6504 // R[t] = ZeroExtend(data, 32);
6505 context.type = eContextRegisterLoad;
6506 context.SetRegisterPlusOffset (base_reg, address - Rn);
6507 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6508 return false;
6509 }
6510 else // Can only apply before ARMv7
6511 {
6512 // R[t] = bits(32) UNKNOWN;
6513 WriteBits32Unknown (t);
6514 }
6515 }
6516 return true;
6517}
Caroline Ticefe479112011-02-18 18:52:37 +00006518
Caroline Tice952b5382011-02-28 23:15:24 +00006519// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6520// zero-extends it to form a 32-bit word, and writes it to a register.
6521bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006522EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006523{
6524#if 0
6525 if ConditionPassed() then
6526 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6527 base = Align(PC,4);
6528 address = if add then (base + imm32) else (base - imm32);
6529 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006530 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006531 R[t] = ZeroExtend(data, 32);
6532 else // Can only apply before ARMv7
6533 R[t] = bits(32) UNKNOWN;
6534#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006535
Caroline Tice952b5382011-02-28 23:15:24 +00006536 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006537
Greg Clayton7bc39082011-03-24 23:53:38 +00006538 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006539 {
6540 uint32_t t;
6541 uint32_t imm32;
6542 bool add;
6543
6544 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6545 switch (encoding)
6546 {
6547 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006548 // if Rt == '1111' then SEE "Unallocated memory hints";
6549 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006550 t = Bits32 (opcode, 15, 12);
6551 imm32 = Bits32 (opcode, 11, 0);
6552 add = BitIsSet (opcode, 23);
6553
6554 // if t == 13 then UNPREDICTABLE;
6555 if (t == 13)
6556 return false;
6557
6558 break;
6559
6560 case eEncodingA1:
6561 {
6562 uint32_t imm4H = Bits32 (opcode, 11, 8);
6563 uint32_t imm4L = Bits32 (opcode, 3, 0);
6564
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006565 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006566 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006567 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006568 add = BitIsSet (opcode, 23);
6569
6570 // if t == 15 then UNPREDICTABLE;
6571 if (t == 15)
6572 return false;
6573 break;
6574 }
6575
6576 default:
6577 return false;
6578 }
6579
6580 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006581 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006582 if (!success)
6583 return false;
6584
6585 addr_t base = AlignPC (pc_value);
6586 addr_t address;
6587
6588 // address = if add then (base + imm32) else (base - imm32);
6589 if (add)
6590 address = base + imm32;
6591 else
6592 address = base - imm32;
6593
6594 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006595 RegisterInfo base_reg;
6596 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice952b5382011-02-28 23:15:24 +00006597
6598 EmulateInstruction::Context context;
6599 context.type = eContextRegisterLoad;
6600 context.SetRegisterPlusOffset (base_reg, address - base);
6601
6602 uint64_t data = MemURead (context, address, 2, 0, &success);
6603 if (!success)
6604 return false;
6605
6606
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006607 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006608 if (UnalignedSupport () || BitIsClear (address, 0))
6609 {
6610 // R[t] = ZeroExtend(data, 32);
6611 context.type = eContextRegisterLoad;
6612 context.SetRegisterPlusOffset (base_reg, address - base);
6613 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6614 return false;
6615
6616 }
6617 else // Can only apply before ARMv7
6618 {
6619 // R[t] = bits(32) UNKNOWN;
6620 WriteBits32Unknown (t);
6621 }
6622 }
6623 return true;
6624}
6625
Caroline Tice0e6bc952011-03-01 18:00:42 +00006626// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6627// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6628// be shifted left by 0, 1, 2, or 3 bits.
6629bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006630EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006631{
6632#if 0
6633 if ConditionPassed() then
6634 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6635 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6636 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6637 address = if index then offset_addr else R[n];
6638 data = MemU[address,2];
6639 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006640 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006641 R[t] = ZeroExtend(data, 32);
6642 else // Can only apply before ARMv7
6643 R[t] = bits(32) UNKNOWN;
6644#endif
6645
6646 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006647
Greg Clayton7bc39082011-03-24 23:53:38 +00006648 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006649 {
6650 uint32_t t;
6651 uint32_t n;
6652 uint32_t m;
6653 bool index;
6654 bool add;
6655 bool wback;
6656 ARM_ShifterType shift_t;
6657 uint32_t shift_n;
6658
6659 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6660 switch (encoding)
6661 {
6662 case eEncodingT1:
6663 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6664 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6665 t = Bits32 (opcode, 2, 0);
6666 n = Bits32 (opcode, 5, 3);
6667 m = Bits32 (opcode, 8, 6);
6668
6669 // index = TRUE; add = TRUE; wback = FALSE;
6670 index = true;
6671 add = true;
6672 wback = false;
6673
6674 // (shift_t, shift_n) = (SRType_LSL, 0);
6675 shift_t = SRType_LSL;
6676 shift_n = 0;
6677
6678 break;
6679
6680 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006681 // if Rn == '1111' then SEE LDRH (literal);
6682 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006683 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6684 t = Bits32 (opcode, 15, 12);
6685 n = Bits32 (opcode, 19, 16);
6686 m = Bits32 (opcode, 3, 0);
6687
6688 // index = TRUE; add = TRUE; wback = FALSE;
6689 index = true;
6690 add = true;
6691 wback = false;
6692
6693 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6694 shift_t = SRType_LSL;
6695 shift_n = Bits32 (opcode, 5, 4);
6696
6697 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6698 if ((t == 13) || BadReg (m))
6699 return false;
6700 break;
6701
6702 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006703 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006704 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6705 t = Bits32 (opcode, 15, 12);
6706 n = Bits32 (opcode, 19, 16);
6707 m = Bits32 (opcode, 3, 0);
6708
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006709 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006710 index = BitIsSet (opcode, 24);
6711 add = BitIsSet (opcode, 23);
6712 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6713
6714 // (shift_t, shift_n) = (SRType_LSL, 0);
6715 shift_t = SRType_LSL;
6716 shift_n = 0;
6717
6718 // if t == 15 || m == 15 then UNPREDICTABLE;
6719 if ((t == 15) || (m == 15))
6720 return false;
6721
6722 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6723 if (wback && ((n == 15) || (n == t)))
6724 return false;
6725
6726 break;
6727
6728 default:
6729 return false;
6730 }
6731
6732 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6733
6734 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6735 if (!success)
6736 return false;
6737
6738 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6739
6740 addr_t offset_addr;
6741 addr_t address;
6742
6743 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6744 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6745 if (!success)
6746 return false;
6747
6748 if (add)
6749 offset_addr = Rn + offset;
6750 else
6751 offset_addr = Rn - offset;
6752
6753 // address = if index then offset_addr else R[n];
6754 if (index)
6755 address = offset_addr;
6756 else
6757 address = Rn;
6758
6759 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006760 RegisterInfo base_reg;
6761 RegisterInfo offset_reg;
6762 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6763 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice0e6bc952011-03-01 18:00:42 +00006764
6765 EmulateInstruction::Context context;
6766 context.type = eContextRegisterLoad;
6767 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6768 uint64_t data = MemURead (context, address, 2, 0, &success);
6769 if (!success)
6770 return false;
6771
6772 // if wback then R[n] = offset_addr;
6773 if (wback)
6774 {
6775 context.type = eContextAdjustBaseRegister;
6776 context.SetAddress (offset_addr);
6777 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6778 return false;
6779 }
6780
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006781 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006782 if (UnalignedSupport() || BitIsClear (address, 0))
6783 {
6784 // R[t] = ZeroExtend(data, 32);
6785 context.type = eContextRegisterLoad;
6786 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6787 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6788 return false;
6789 }
6790 else // Can only apply before ARMv7
6791 {
6792 // R[t] = bits(32) UNKNOWN;
6793 WriteBits32Unknown (t);
6794 }
6795 }
6796 return true;
6797}
6798
Caroline Ticea5e28af2011-03-01 21:53:03 +00006799// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6800// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6801// or pre-indexed addressing.
6802bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006803EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006804{
6805#if 0
6806 if ConditionPassed() then
6807 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6808 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6809 address = if index then offset_addr else R[n];
6810 R[t] = SignExtend(MemU[address,1], 32);
6811 if wback then R[n] = offset_addr;
6812#endif
6813
6814 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006815
Greg Clayton7bc39082011-03-24 23:53:38 +00006816 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006817 {
6818 uint32_t t;
6819 uint32_t n;
6820 uint32_t imm32;
6821 bool index;
6822 bool add;
6823 bool wback;
6824
6825 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6826 switch (encoding)
6827 {
6828 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006829 // if Rt == '1111' then SEE PLI;
6830 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006831 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6832 t = Bits32 (opcode, 15, 12);
6833 n = Bits32 (opcode, 19, 16);
6834 imm32 = Bits32 (opcode, 11, 0);
6835
6836 // index = TRUE; add = TRUE; wback = FALSE;
6837 index = true;
6838 add = true;
6839 wback = false;
6840
6841 // if t == 13 then UNPREDICTABLE;
6842 if (t == 13)
6843 return false;
6844
6845 break;
6846
6847 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006848 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6849 // if Rn == '1111' then SEE LDRSB (literal);
6850 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6851 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006852 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6853 return false;
6854
6855 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6856 t = Bits32 (opcode, 15, 12);
6857 n = Bits32 (opcode, 19, 16);
6858 imm32 = Bits32 (opcode, 7, 0);
6859
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006860 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006861 index = BitIsSet (opcode, 10);
6862 add = BitIsSet (opcode, 9);
6863 wback = BitIsSet (opcode, 8);
6864
6865 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006866 if (((t == 13) || ((t == 15)
6867 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6868 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006869 return false;
6870
6871 break;
6872
6873 case eEncodingA1:
6874 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006875 // if Rn == '1111' then SEE LDRSB (literal);
6876 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006877 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6878 t = Bits32 (opcode, 15, 12);
6879 n = Bits32 (opcode, 19, 16);
6880
6881 uint32_t imm4H = Bits32 (opcode, 11, 8);
6882 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006883 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006884
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006885 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006886 index = BitIsSet (opcode, 24);
6887 add = BitIsSet (opcode, 23);
6888 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6889
6890 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6891 if ((t == 15) || (wback && (n == t)))
6892 return false;
6893
6894 break;
6895 }
6896
6897 default:
6898 return false;
6899 }
6900
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006901 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006902 if (!success)
6903 return false;
6904
6905 addr_t offset_addr;
6906 addr_t address;
6907
6908 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6909 if (add)
6910 offset_addr = Rn + imm32;
6911 else
6912 offset_addr = Rn - imm32;
6913
6914 // address = if index then offset_addr else R[n];
6915 if (index)
6916 address = offset_addr;
6917 else
6918 address = Rn;
6919
6920 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006921 RegisterInfo base_reg;
6922 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006923
6924 EmulateInstruction::Context context;
6925 context.type = eContextRegisterLoad;
6926 context.SetRegisterPlusOffset (base_reg, address - Rn);
6927
6928 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6929 if (!success)
6930 return false;
6931
6932 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6933 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6934 return false;
6935
6936 // if wback then R[n] = offset_addr;
6937 if (wback)
6938 {
6939 context.type = eContextAdjustBaseRegister;
6940 context.SetAddress (offset_addr);
6941 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6942 return false;
6943 }
6944 }
6945
6946 return true;
6947}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006948
Caroline Tice5f593912011-03-01 22:25:17 +00006949// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6950// sign-extends it to form a 32-bit word, and writes tit to a register.
6951bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006952EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006953{
6954#if 0
6955 if ConditionPassed() then
6956 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6957 base = Align(PC,4);
6958 address = if add then (base + imm32) else (base - imm32);
6959 R[t] = SignExtend(MemU[address,1], 32);
6960#endif
6961
6962 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006963
Greg Clayton7bc39082011-03-24 23:53:38 +00006964 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006965 {
6966 uint32_t t;
6967 uint32_t imm32;
6968 bool add;
6969
6970 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6971 switch (encoding)
6972 {
6973 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006974 // if Rt == '1111' then SEE PLI;
6975 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006976 t = Bits32 (opcode, 15, 12);
6977 imm32 = Bits32 (opcode, 11, 0);
6978 add = BitIsSet (opcode, 23);
6979
6980 // if t == 13 then UNPREDICTABLE;
6981 if (t == 13)
6982 return false;
6983
6984 break;
6985
6986 case eEncodingA1:
6987 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006988 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006989 t = Bits32 (opcode, 15, 12);
6990 uint32_t imm4H = Bits32 (opcode, 11, 8);
6991 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006992 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006993 add = BitIsSet (opcode, 23);
6994
6995 // if t == 15 then UNPREDICTABLE;
6996 if (t == 15)
6997 return false;
6998
6999 break;
7000 }
7001
7002 default:
7003 return false;
7004 }
7005
7006 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007007 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007008 if (!success)
7009 return false;
7010 uint64_t base = AlignPC (pc_value);
7011
7012 // address = if add then (base + imm32) else (base - imm32);
7013 addr_t address;
7014 if (add)
7015 address = base + imm32;
7016 else
7017 address = base - imm32;
7018
7019 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007020 RegisterInfo base_reg;
7021 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice5f593912011-03-01 22:25:17 +00007022
7023 EmulateInstruction::Context context;
7024 context.type = eContextRegisterLoad;
7025 context.SetRegisterPlusOffset (base_reg, address - base);
7026
7027 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7028 if (!success)
7029 return false;
7030
7031 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7032 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7033 return false;
7034 }
7035 return true;
7036}
7037
Caroline Tice672f3112011-03-01 23:55:59 +00007038// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7039// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7040// shifted left by 0, 1, 2, or 3 bits.
7041bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007042EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007043{
7044#if 0
7045 if ConditionPassed() then
7046 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7047 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7048 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7049 address = if index then offset_addr else R[n];
7050 R[t] = SignExtend(MemU[address,1], 32);
7051 if wback then R[n] = offset_addr;
7052#endif
7053
7054 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007055
Greg Clayton7bc39082011-03-24 23:53:38 +00007056 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007057 {
7058 uint32_t t;
7059 uint32_t n;
7060 uint32_t m;
7061 bool index;
7062 bool add;
7063 bool wback;
7064 ARM_ShifterType shift_t;
7065 uint32_t shift_n;
7066
7067 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7068 switch (encoding)
7069 {
7070 case eEncodingT1:
7071 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7072 t = Bits32 (opcode, 2, 0);
7073 n = Bits32 (opcode, 5, 3);
7074 m = Bits32 (opcode, 8, 6);
7075
7076 // index = TRUE; add = TRUE; wback = FALSE;
7077 index = true;
7078 add = true;
7079 wback = false;
7080
7081 // (shift_t, shift_n) = (SRType_LSL, 0);
7082 shift_t = SRType_LSL;
7083 shift_n = 0;
7084
7085 break;
7086
7087 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007088 // if Rt == '1111' then SEE PLI;
7089 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007090 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7091 t = Bits32 (opcode, 15, 12);
7092 n = Bits32 (opcode, 19, 16);
7093 m = Bits32 (opcode, 3, 0);
7094
7095 // index = TRUE; add = TRUE; wback = FALSE;
7096 index = true;
7097 add = true;
7098 wback = false;
7099
7100 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7101 shift_t = SRType_LSL;
7102 shift_n = Bits32 (opcode, 5, 4);
7103
7104 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7105 if ((t == 13) || BadReg (m))
7106 return false;
7107 break;
7108
7109 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007110 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007111 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7112 t = Bits32 (opcode, 15, 12);
7113 n = Bits32 (opcode, 19, 16);
7114 m = Bits32 (opcode, 3, 0);
7115
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007116 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007117 index = BitIsSet (opcode, 24);
7118 add = BitIsSet (opcode, 23);
7119 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7120
7121 // (shift_t, shift_n) = (SRType_LSL, 0);
7122 shift_t = SRType_LSL;
7123 shift_n = 0;
7124
7125 // if t == 15 || m == 15 then UNPREDICTABLE;
7126 if ((t == 15) || (m == 15))
7127 return false;
7128
7129 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7130 if (wback && ((n == 15) || (n == t)))
7131 return false;
7132 break;
7133
7134 default:
7135 return false;
7136 }
7137
7138 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7139 if (!success)
7140 return false;
7141
7142 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7143 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7144
7145 addr_t offset_addr;
7146 addr_t address;
7147
7148 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7149 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7150 if (!success)
7151 return false;
7152
7153 if (add)
7154 offset_addr = Rn + offset;
7155 else
7156 offset_addr = Rn - offset;
7157
7158 // address = if index then offset_addr else R[n];
7159 if (index)
7160 address = offset_addr;
7161 else
7162 address = Rn;
7163
7164 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007165 RegisterInfo base_reg;
7166 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7167 RegisterInfo offset_reg;
7168 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice672f3112011-03-01 23:55:59 +00007169
7170 EmulateInstruction::Context context;
7171 context.type = eContextRegisterLoad;
7172 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7173
7174 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7175 if (!success)
7176 return false;
7177
7178 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7179 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7180 return false;
7181
7182 // if wback then R[n] = offset_addr;
7183 if (wback)
7184 {
7185 context.type = eContextAdjustBaseRegister;
7186 context.SetAddress (offset_addr);
7187 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7188 return false;
7189 }
7190 }
7191 return true;
7192}
7193
Caroline Tice78fb5632011-03-02 00:39:42 +00007194// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7195// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7196// pre-indexed addressing.
7197bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007198EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007199{
7200#if 0
7201 if ConditionPassed() then
7202 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7203 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7204 address = if index then offset_addr else R[n];
7205 data = MemU[address,2];
7206 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007207 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007208 R[t] = SignExtend(data, 32);
7209 else // Can only apply before ARMv7
7210 R[t] = bits(32) UNKNOWN;
7211#endif
7212
7213 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007214
Greg Clayton7bc39082011-03-24 23:53:38 +00007215 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007216 {
7217 uint32_t t;
7218 uint32_t n;
7219 uint32_t imm32;
7220 bool index;
7221 bool add;
7222 bool wback;
7223
7224 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7225 switch (encoding)
7226 {
7227 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007228 // if Rn == '1111' then SEE LDRSH (literal);
7229 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007230 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7231 t = Bits32 (opcode, 15, 12);
7232 n = Bits32 (opcode, 19, 16);
7233 imm32 = Bits32 (opcode, 11, 0);
7234
7235 // index = TRUE; add = TRUE; wback = FALSE;
7236 index = true;
7237 add = true;
7238 wback = false;
7239
7240 // if t == 13 then UNPREDICTABLE;
7241 if (t == 13)
7242 return false;
7243
7244 break;
7245
7246 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007247 // if Rn == '1111' then SEE LDRSH (literal);
7248 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7249 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7250 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007251 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7252 return false;
7253
7254 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7255 t = Bits32 (opcode, 15, 12);
7256 n = Bits32 (opcode, 19, 16);
7257 imm32 = Bits32 (opcode, 7, 0);
7258
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007259 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007260 index = BitIsSet (opcode, 10);
7261 add = BitIsSet (opcode, 9);
7262 wback = BitIsSet (opcode, 8);
7263
7264 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7265 if (BadReg (t) || (wback && (n == t)))
7266 return false;
7267
7268 break;
7269
7270 case eEncodingA1:
7271 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007272 // if Rn == '1111' then SEE LDRSH (literal);
7273 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007274 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7275 t = Bits32 (opcode, 15, 12);
7276 n = Bits32 (opcode, 19, 16);
7277 uint32_t imm4H = Bits32 (opcode, 11,8);
7278 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007279 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007280
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007281 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007282 index = BitIsSet (opcode, 24);
7283 add = BitIsSet (opcode, 23);
7284 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7285
7286 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7287 if ((t == 15) || (wback && (n == t)))
7288 return false;
7289
7290 break;
7291 }
7292
7293 default:
7294 return false;
7295 }
7296
7297 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7298 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7299 if (!success)
7300 return false;
7301
7302 addr_t offset_addr;
7303 if (add)
7304 offset_addr = Rn + imm32;
7305 else
7306 offset_addr = Rn - imm32;
7307
7308 // address = if index then offset_addr else R[n];
7309 addr_t address;
7310 if (index)
7311 address = offset_addr;
7312 else
7313 address = Rn;
7314
7315 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007316 RegisterInfo base_reg;
7317 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice78fb5632011-03-02 00:39:42 +00007318
7319 EmulateInstruction::Context context;
7320 context.type = eContextRegisterLoad;
7321 context.SetRegisterPlusOffset (base_reg, address - Rn);
7322
7323 uint64_t data = MemURead (context, address, 2, 0, &success);
7324 if (!success)
7325 return false;
7326
7327 // if wback then R[n] = offset_addr;
7328 if (wback)
7329 {
7330 context.type = eContextAdjustBaseRegister;
7331 context.SetAddress (offset_addr);
7332 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7333 return false;
7334 }
7335
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007336 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007337 if (UnalignedSupport() || BitIsClear (address, 0))
7338 {
7339 // R[t] = SignExtend(data, 32);
7340 int64_t signed_data = llvm::SignExtend64<16>(data);
7341 context.type = eContextRegisterLoad;
7342 context.SetRegisterPlusOffset (base_reg, address - Rn);
7343 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7344 return false;
7345 }
7346 else // Can only apply before ARMv7
7347 {
7348 // R[t] = bits(32) UNKNOWN;
7349 WriteBits32Unknown (t);
7350 }
7351 }
7352 return true;
7353}
7354
Caroline Ticed2fac092011-03-02 19:45:34 +00007355// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7356// sign-extends it to from a 32-bit word, and writes it to a register.
7357bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007358EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007359{
7360#if 0
7361 if ConditionPassed() then
7362 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7363 base = Align(PC,4);
7364 address = if add then (base + imm32) else (base - imm32);
7365 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007366 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007367 R[t] = SignExtend(data, 32);
7368 else // Can only apply before ARMv7
7369 R[t] = bits(32) UNKNOWN;
7370#endif
7371
7372 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007373
Greg Clayton7bc39082011-03-24 23:53:38 +00007374 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007375 {
7376 uint32_t t;
7377 uint32_t imm32;
7378 bool add;
7379
7380 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7381 switch (encoding)
7382 {
7383 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007384 // if Rt == '1111' then SEE "Unallocated memory hints";
7385 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007386 t = Bits32 (opcode, 15, 12);
7387 imm32 = Bits32 (opcode, 11, 0);
7388 add = BitIsSet (opcode, 23);
7389
7390 // if t == 13 then UNPREDICTABLE;
7391 if (t == 13)
7392 return false;
7393
7394 break;
7395
7396 case eEncodingA1:
7397 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007398 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007399 t = Bits32 (opcode, 15, 12);
7400 uint32_t imm4H = Bits32 (opcode, 11, 8);
7401 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007402 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007403 add = BitIsSet (opcode, 23);
7404
7405 // if t == 15 then UNPREDICTABLE;
7406 if (t == 15)
7407 return false;
7408
7409 break;
7410 }
7411 default:
7412 return false;
7413 }
7414
7415 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007416 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007417 if (!success)
7418 return false;
7419
7420 uint64_t base = AlignPC (pc_value);
7421
7422 addr_t address;
7423 // address = if add then (base + imm32) else (base - imm32);
7424 if (add)
7425 address = base + imm32;
7426 else
7427 address = base - imm32;
7428
7429 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007430 RegisterInfo base_reg;
7431 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Ticed2fac092011-03-02 19:45:34 +00007432
7433 EmulateInstruction::Context context;
7434 context.type = eContextRegisterLoad;
7435 context.SetRegisterPlusOffset (base_reg, imm32);
7436
7437 uint64_t data = MemURead (context, address, 2, 0, &success);
7438 if (!success)
7439 return false;
7440
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007441 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007442 if (UnalignedSupport() || BitIsClear (address, 0))
7443 {
7444 // R[t] = SignExtend(data, 32);
7445 int64_t signed_data = llvm::SignExtend64<16>(data);
7446 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7447 return false;
7448 }
7449 else // Can only apply before ARMv7
7450 {
7451 // R[t] = bits(32) UNKNOWN;
7452 WriteBits32Unknown (t);
7453 }
7454 }
7455 return true;
7456}
7457
Caroline Tice291a3e92011-03-02 21:13:44 +00007458// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7459// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7460// shifted left by 0, 1, 2, or 3 bits.
7461bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007462EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007463{
7464#if 0
7465 if ConditionPassed() then
7466 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7467 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7468 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7469 address = if index then offset_addr else R[n];
7470 data = MemU[address,2];
7471 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007472 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007473 R[t] = SignExtend(data, 32);
7474 else // Can only apply before ARMv7
7475 R[t] = bits(32) UNKNOWN;
7476#endif
7477
7478 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007479
Greg Clayton7bc39082011-03-24 23:53:38 +00007480 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007481 {
7482 uint32_t t;
7483 uint32_t n;
7484 uint32_t m;
7485 bool index;
7486 bool add;
7487 bool wback;
7488 ARM_ShifterType shift_t;
7489 uint32_t shift_n;
7490
7491 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7492 switch (encoding)
7493 {
7494 case eEncodingT1:
7495 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7496 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7497 t = Bits32 (opcode, 2, 0);
7498 n = Bits32 (opcode, 5, 3);
7499 m = Bits32 (opcode, 8, 6);
7500
7501 // index = TRUE; add = TRUE; wback = FALSE;
7502 index = true;
7503 add = true;
7504 wback = false;
7505
7506 // (shift_t, shift_n) = (SRType_LSL, 0);
7507 shift_t = SRType_LSL;
7508 shift_n = 0;
7509
7510 break;
7511
7512 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007513 // if Rn == '1111' then SEE LDRSH (literal);
7514 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007515 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7516 t = Bits32 (opcode, 15, 12);
7517 n = Bits32 (opcode, 19, 16);
7518 m = Bits32 (opcode, 3, 0);
7519
7520 // index = TRUE; add = TRUE; wback = FALSE;
7521 index = true;
7522 add = true;
7523 wback = false;
7524
7525 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7526 shift_t = SRType_LSL;
7527 shift_n = Bits32 (opcode, 5, 4);
7528
7529 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7530 if ((t == 13) || BadReg (m))
7531 return false;
7532
7533 break;
7534
7535 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007536 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007537 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7538 t = Bits32 (opcode, 15, 12);
7539 n = Bits32 (opcode, 19, 16);
7540 m = Bits32 (opcode, 3, 0);
7541
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007542 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007543 index = BitIsSet (opcode, 24);
7544 add = BitIsSet (opcode, 23);
7545 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7546
7547 // (shift_t, shift_n) = (SRType_LSL, 0);
7548 shift_t = SRType_LSL;
7549 shift_n = 0;
7550
7551 // if t == 15 || m == 15 then UNPREDICTABLE;
7552 if ((t == 15) || (m == 15))
7553 return false;
7554
7555 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7556 if (wback && ((n == 15) || (n == t)))
7557 return false;
7558
7559 break;
7560
7561 default:
7562 break;
7563 }
7564
7565 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7566 if (!success)
7567 return false;
7568
7569 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7570 if (!success)
7571 return false;
7572
7573 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7574 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7575
7576 addr_t offset_addr;
7577 addr_t address;
7578
7579 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7580 if (add)
7581 offset_addr = Rn + offset;
7582 else
7583 offset_addr = Rn - offset;
7584
7585 // address = if index then offset_addr else R[n];
7586 if (index)
7587 address = offset_addr;
7588 else
7589 address = Rn;
7590
7591 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007592 RegisterInfo base_reg;
7593 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007594
Greg Claytonc07d4512011-04-26 23:48:45 +00007595 RegisterInfo offset_reg;
7596 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007597
7598 EmulateInstruction::Context context;
7599 context.type = eContextRegisterLoad;
7600 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7601
7602 uint64_t data = MemURead (context, address, 2, 0, &success);
7603 if (!success)
7604 return false;
7605
7606 // if wback then R[n] = offset_addr;
7607 if (wback)
7608 {
7609 context.type = eContextAdjustBaseRegister;
7610 context.SetAddress (offset_addr);
7611 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7612 return false;
7613 }
7614
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007615 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007616 if (UnalignedSupport() || BitIsClear (address, 0))
7617 {
7618 // R[t] = SignExtend(data, 32);
7619 context.type = eContextRegisterLoad;
7620 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7621
7622 int64_t signed_data = llvm::SignExtend64<16>(data);
7623 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7624 return false;
7625 }
7626 else // Can only apply before ARMv7
7627 {
7628 // R[t] = bits(32) UNKNOWN;
7629 WriteBits32Unknown (t);
7630 }
7631 }
7632 return true;
7633}
Caroline Tice6bf65162011-03-03 17:42:58 +00007634
7635// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7636// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7637bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007638EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007639{
7640#if 0
7641 if ConditionPassed() then
7642 EncodingSpecificOperations();
7643 rotated = ROR(R[m], rotation);
7644 R[d] = SignExtend(rotated<7:0>, 32);
7645#endif
7646
7647 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007648
Greg Clayton7bc39082011-03-24 23:53:38 +00007649 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007650 {
7651 uint32_t d;
7652 uint32_t m;
7653 uint32_t rotation;
7654
7655 // EncodingSpecificOperations();
7656 switch (encoding)
7657 {
7658 case eEncodingT1:
7659 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7660 d = Bits32 (opcode, 2, 0);
7661 m = Bits32 (opcode, 5, 3);
7662 rotation = 0;
7663
7664 break;
7665
7666 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007667 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007668 d = Bits32 (opcode, 11, 8);
7669 m = Bits32 (opcode, 3, 0);
7670 rotation = Bits32 (opcode, 5, 4) << 3;
7671
7672 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7673 if (BadReg (d) || BadReg (m))
7674 return false;
7675
7676 break;
7677
7678 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007679 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007680 d = Bits32 (opcode, 15, 12);
7681 m = Bits32 (opcode, 3, 0);
7682 rotation = Bits32 (opcode, 11, 10) << 3;
7683
7684 // if d == 15 || m == 15 then UNPREDICTABLE;
7685 if ((d == 15) || (m == 15))
7686 return false;
7687
7688 break;
7689
7690 default:
7691 return false;
7692 }
7693
Caroline Tice868198b2011-03-03 18:04:49 +00007694 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7695 if (!success)
7696 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007697
7698 // rotated = ROR(R[m], rotation);
7699 uint64_t rotated = ROR (Rm, rotation);
7700
7701 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007702 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007703
Greg Claytonc07d4512011-04-26 23:48:45 +00007704 RegisterInfo source_reg;
7705 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice6bf65162011-03-03 17:42:58 +00007706
7707 EmulateInstruction::Context context;
7708 context.type = eContextRegisterLoad;
7709 context.SetRegister (source_reg);
7710
Caroline Tice8ce96d92011-03-03 18:27:17 +00007711 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007712 return false;
7713 }
7714 return true;
7715}
Caroline Tice291a3e92011-03-02 21:13:44 +00007716
Caroline Tice868198b2011-03-03 18:04:49 +00007717// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7718// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7719bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007720EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007721{
7722#if 0
7723 if ConditionPassed() then
7724 EncodingSpecificOperations();
7725 rotated = ROR(R[m], rotation);
7726 R[d] = SignExtend(rotated<15:0>, 32);
7727#endif
7728
7729 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007730
Greg Clayton7bc39082011-03-24 23:53:38 +00007731 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007732 {
7733 uint32_t d;
7734 uint32_t m;
7735 uint32_t rotation;
7736
7737 // EncodingSpecificOperations();
7738 switch (encoding)
7739 {
7740 case eEncodingT1:
7741 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7742 d = Bits32 (opcode, 2, 0);
7743 m = Bits32 (opcode, 5, 3);
7744 rotation = 0;
7745
7746 break;
7747
7748 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007749 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007750 d = Bits32 (opcode, 11, 8);
7751 m = Bits32 (opcode, 3, 0);
7752 rotation = Bits32 (opcode, 5, 4) << 3;
7753
7754 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7755 if (BadReg (d) || BadReg (m))
7756 return false;
7757
7758 break;
7759
7760 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007761 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007762 d = Bits32 (opcode, 15, 12);
7763 m = Bits32 (opcode, 3, 0);
7764 rotation = Bits32 (opcode, 11, 10) << 3;
7765
7766 // if d == 15 || m == 15 then UNPREDICTABLE;
7767 if ((d == 15) || (m == 15))
7768 return false;
7769
7770 break;
7771
7772 default:
7773 return false;
7774 }
7775
7776 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7777 if (!success)
7778 return false;
7779
7780 // rotated = ROR(R[m], rotation);
7781 uint64_t rotated = ROR (Rm, rotation);
7782
7783 // R[d] = SignExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007784 RegisterInfo source_reg;
7785 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice868198b2011-03-03 18:04:49 +00007786
7787 EmulateInstruction::Context context;
7788 context.type = eContextRegisterLoad;
7789 context.SetRegister (source_reg);
7790
Caroline Tice8ce96d92011-03-03 18:27:17 +00007791 int64_t data = llvm::SignExtend64<16> (rotated);
7792 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007793 return false;
7794 }
7795
7796 return true;
7797}
7798
Caroline Tice8ce96d92011-03-03 18:27:17 +00007799// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7800// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7801bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007802EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007803{
7804#if 0
7805 if ConditionPassed() then
7806 EncodingSpecificOperations();
7807 rotated = ROR(R[m], rotation);
7808 R[d] = ZeroExtend(rotated<7:0>, 32);
7809#endif
7810
7811 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007812
Greg Clayton7bc39082011-03-24 23:53:38 +00007813 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007814 {
7815 uint32_t d;
7816 uint32_t m;
7817 uint32_t rotation;
7818
7819 // EncodingSpecificOperations();
7820 switch (encoding)
7821 {
7822 case eEncodingT1:
7823 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7824 d = Bits32 (opcode, 2, 0);
7825 m = Bits32 (opcode, 5, 3);
7826 rotation = 0;
7827
7828 break;
7829
7830 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007831 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007832 d = Bits32 (opcode, 11, 8);
7833 m = Bits32 (opcode, 3, 0);
7834 rotation = Bits32 (opcode, 5, 4) << 3;
7835
7836 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7837 if (BadReg (d) || BadReg (m))
7838 return false;
7839
7840 break;
7841
7842 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007843 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007844 d = Bits32 (opcode, 15, 12);
7845 m = Bits32 (opcode, 3, 0);
7846 rotation = Bits32 (opcode, 11, 10) << 3;
7847
7848 // if d == 15 || m == 15 then UNPREDICTABLE;
7849 if ((d == 15) || (m == 15))
7850 return false;
7851
7852 break;
7853
7854 default:
7855 return false;
7856 }
7857
7858 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7859 if (!success)
7860 return false;
7861
7862 // rotated = ROR(R[m], rotation);
7863 uint64_t rotated = ROR (Rm, rotation);
7864
7865 // R[d] = ZeroExtend(rotated<7:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007866 RegisterInfo source_reg;
7867 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007868
7869 EmulateInstruction::Context context;
7870 context.type = eContextRegisterLoad;
7871 context.SetRegister (source_reg);
7872
7873 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7874 return false;
7875 }
7876 return true;
7877}
7878
Caroline Tice11555f22011-03-03 18:48:58 +00007879// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7880// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7881bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007882EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007883{
7884#if 0
7885 if ConditionPassed() then
7886 EncodingSpecificOperations();
7887 rotated = ROR(R[m], rotation);
7888 R[d] = ZeroExtend(rotated<15:0>, 32);
7889#endif
7890
7891 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007892
Greg Clayton7bc39082011-03-24 23:53:38 +00007893 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007894 {
7895 uint32_t d;
7896 uint32_t m;
7897 uint32_t rotation;
7898
7899 switch (encoding)
7900 {
7901 case eEncodingT1:
7902 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7903 d = Bits32 (opcode, 2, 0);
7904 m = Bits32 (opcode, 5, 3);
7905 rotation = 0;
7906
7907 break;
7908
7909 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007910 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007911 d = Bits32 (opcode, 11, 8);
7912 m = Bits32 (opcode, 3, 0);
7913 rotation = Bits32 (opcode, 5, 4) << 3;
7914
7915 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7916 if (BadReg (d) || BadReg (m))
7917 return false;
7918
7919 break;
7920
7921 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007922 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007923 d = Bits32 (opcode, 15, 12);
7924 m = Bits32 (opcode, 3, 0);
7925 rotation = Bits32 (opcode, 11, 10) << 3;
7926
7927 // if d == 15 || m == 15 then UNPREDICTABLE;
7928 if ((d == 15) || (m == 15))
7929 return false;
7930
7931 break;
7932
7933 default:
7934 return false;
7935 }
7936
7937 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7938 if (!success)
7939 return false;
7940
7941 // rotated = ROR(R[m], rotation);
7942 uint64_t rotated = ROR (Rm, rotation);
7943
7944 // R[d] = ZeroExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007945 RegisterInfo source_reg;
7946 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice11555f22011-03-03 18:48:58 +00007947
7948 EmulateInstruction::Context context;
7949 context.type = eContextRegisterLoad;
7950 context.SetRegister (source_reg);
7951
7952 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7953 return false;
7954 }
7955 return true;
7956}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007957
7958// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7959// word respectively.
7960bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007961EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007962{
7963#if 0
7964 if ConditionPassed() then
7965 EncodingSpecificOperations();
7966 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7967 UNPREDICTABLE;
7968 else
7969 address = if increment then R[n] else R[n]-8;
7970 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007971 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007972 BranchWritePC(MemA[address,4]);
7973 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7974#endif
7975
7976 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007977
Greg Clayton7bc39082011-03-24 23:53:38 +00007978 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007979 {
7980 uint32_t n;
7981 bool wback;
7982 bool increment;
7983 bool wordhigher;
7984
7985 // EncodingSpecificOperations();
7986 switch (encoding)
7987 {
7988 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007989 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007990 n = Bits32 (opcode, 19, 16);
7991 wback = BitIsSet (opcode, 21);
7992 increment = false;
7993 wordhigher = false;
7994
7995 // if n == 15 then UNPREDICTABLE;
7996 if (n == 15)
7997 return false;
7998
7999 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8000 if (InITBlock() && !LastInITBlock())
8001 return false;
8002
8003 break;
8004
8005 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008006 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008007 n = Bits32 (opcode, 19, 16);
8008 wback = BitIsSet (opcode, 21);
8009 increment = true;
8010 wordhigher = false;
8011
8012 // if n == 15 then UNPREDICTABLE;
8013 if (n == 15)
8014 return false;
8015
8016 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8017 if (InITBlock() && !LastInITBlock())
8018 return false;
8019
8020 break;
8021
8022 case eEncodingA1:
8023 // n = UInt(Rn);
8024 n = Bits32 (opcode, 19, 16);
8025
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008026 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008027 wback = BitIsSet (opcode, 21);
8028 increment = BitIsSet (opcode, 23);
8029 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8030
8031 // if n == 15 then UNPREDICTABLE;
8032 if (n == 15)
8033 return false;
8034
8035 break;
8036
8037 default:
8038 return false;
8039 }
8040
8041 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8042 if (!CurrentModeIsPrivileged ())
8043 // UNPREDICTABLE;
8044 return false;
8045 else
8046 {
8047 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8048 if (!success)
8049 return false;
8050
8051 addr_t address;
8052 // address = if increment then R[n] else R[n]-8;
8053 if (increment)
8054 address = Rn;
8055 else
8056 address = Rn - 8;
8057
8058 // if wordhigher then address = address+4;
8059 if (wordhigher)
8060 address = address + 4;
8061
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008062 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Greg Claytonc07d4512011-04-26 23:48:45 +00008063 RegisterInfo base_reg;
8064 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008065
8066 EmulateInstruction::Context context;
8067 context.type = eContextReturnFromException;
8068 context.SetRegisterPlusOffset (base_reg, address - Rn);
8069
8070 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8071 if (!success)
8072 return false;
8073
8074 CPSRWriteByInstr (data, 15, true);
8075
8076 // BranchWritePC(MemA[address,4]);
8077 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8078 if (!success)
8079 return false;
8080
8081 BranchWritePC (context, data2);
8082
8083 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8084 if (wback)
8085 {
8086 context.type = eContextAdjustBaseRegister;
8087 if (increment)
8088 {
8089 context.SetOffset (8);
8090 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8091 return false;
8092 }
8093 else
8094 {
8095 context.SetOffset (-8);
8096 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8097 return false;
8098 }
8099 } // if wback
8100 }
8101 } // if ConditionPassed()
8102 return true;
8103}
Caroline Tice11555f22011-03-03 18:48:58 +00008104
Johnny Chen2115b412011-02-21 23:42:44 +00008105// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8106// and writes the result to the destination register. It can optionally update the condition flags based on
8107// the result.
8108bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008109EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008110{
8111#if 0
8112 // ARM pseudo code...
8113 if ConditionPassed() then
8114 EncodingSpecificOperations();
8115 result = R[n] EOR imm32;
8116 if d == 15 then // Can only occur for ARM encoding
8117 ALUWritePC(result); // setflags is always FALSE here
8118 else
8119 R[d] = result;
8120 if setflags then
8121 APSR.N = result<31>;
8122 APSR.Z = IsZeroBit(result);
8123 APSR.C = carry;
8124 // APSR.V unchanged
8125#endif
8126
8127 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008128
Greg Clayton7bc39082011-03-24 23:53:38 +00008129 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008130 {
8131 uint32_t Rd, Rn;
8132 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8133 bool setflags;
8134 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8135 switch (encoding)
8136 {
8137 case eEncodingT1:
8138 Rd = Bits32(opcode, 11, 8);
8139 Rn = Bits32(opcode, 19, 16);
8140 setflags = BitIsSet(opcode, 20);
8141 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8142 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8143 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008144 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008145 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8146 return false;
8147 break;
8148 case eEncodingA1:
8149 Rd = Bits32(opcode, 15, 12);
8150 Rn = Bits32(opcode, 19, 16);
8151 setflags = BitIsSet(opcode, 20);
8152 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008153
Johnny Chen2115b412011-02-21 23:42:44 +00008154 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008155 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008156 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008157 break;
8158 default:
8159 return false;
8160 }
8161
8162 // Read the first operand.
8163 uint32_t val1 = ReadCoreReg(Rn, &success);
8164 if (!success)
8165 return false;
8166
8167 uint32_t result = val1 ^ imm32;
8168
8169 EmulateInstruction::Context context;
8170 context.type = EmulateInstruction::eContextImmediate;
8171 context.SetNoArgs ();
8172
8173 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8174 return false;
8175 }
8176 return true;
8177}
8178
8179// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8180// optionally-shifted register value, and writes the result to the destination register.
8181// It can optionally update the condition flags based on the result.
8182bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008183EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008184{
8185#if 0
8186 // ARM pseudo code...
8187 if ConditionPassed() then
8188 EncodingSpecificOperations();
8189 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8190 result = R[n] EOR shifted;
8191 if d == 15 then // Can only occur for ARM encoding
8192 ALUWritePC(result); // setflags is always FALSE here
8193 else
8194 R[d] = result;
8195 if setflags then
8196 APSR.N = result<31>;
8197 APSR.Z = IsZeroBit(result);
8198 APSR.C = carry;
8199 // APSR.V unchanged
8200#endif
8201
8202 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008203
Greg Clayton7bc39082011-03-24 23:53:38 +00008204 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008205 {
8206 uint32_t Rd, Rn, Rm;
8207 ARM_ShifterType shift_t;
8208 uint32_t shift_n; // the shift applied to the value read from Rm
8209 bool setflags;
8210 uint32_t carry;
8211 switch (encoding)
8212 {
8213 case eEncodingT1:
8214 Rd = Rn = Bits32(opcode, 2, 0);
8215 Rm = Bits32(opcode, 5, 3);
8216 setflags = !InITBlock();
8217 shift_t = SRType_LSL;
8218 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008219 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008220 case eEncodingT2:
8221 Rd = Bits32(opcode, 11, 8);
8222 Rn = Bits32(opcode, 19, 16);
8223 Rm = Bits32(opcode, 3, 0);
8224 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008225 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8226 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008227 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008228 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008229 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8230 return false;
8231 break;
8232 case eEncodingA1:
8233 Rd = Bits32(opcode, 15, 12);
8234 Rn = Bits32(opcode, 19, 16);
8235 Rm = Bits32(opcode, 3, 0);
8236 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008237 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008238
Johnny Chen2115b412011-02-21 23:42:44 +00008239 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008240 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008241 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008242 break;
8243 default:
8244 return false;
8245 }
8246
8247 // Read the first operand.
8248 uint32_t val1 = ReadCoreReg(Rn, &success);
8249 if (!success)
8250 return false;
8251
8252 // Read the second operand.
8253 uint32_t val2 = ReadCoreReg(Rm, &success);
8254 if (!success)
8255 return false;
8256
8257 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8258 uint32_t result = val1 ^ shifted;
8259
8260 EmulateInstruction::Context context;
8261 context.type = EmulateInstruction::eContextImmediate;
8262 context.SetNoArgs ();
8263
8264 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8265 return false;
8266 }
8267 return true;
8268}
8269
Johnny Chen7c5234d2011-02-18 23:41:11 +00008270// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8271// writes the result to the destination register. It can optionally update the condition flags based
8272// on the result.
8273bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008274EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008275{
8276#if 0
8277 // ARM pseudo code...
8278 if ConditionPassed() then
8279 EncodingSpecificOperations();
8280 result = R[n] OR imm32;
8281 if d == 15 then // Can only occur for ARM encoding
8282 ALUWritePC(result); // setflags is always FALSE here
8283 else
8284 R[d] = result;
8285 if setflags then
8286 APSR.N = result<31>;
8287 APSR.Z = IsZeroBit(result);
8288 APSR.C = carry;
8289 // APSR.V unchanged
8290#endif
8291
8292 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008293
Greg Clayton7bc39082011-03-24 23:53:38 +00008294 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008295 {
8296 uint32_t Rd, Rn;
8297 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8298 bool setflags;
8299 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8300 switch (encoding)
8301 {
8302 case eEncodingT1:
8303 Rd = Bits32(opcode, 11, 8);
8304 Rn = Bits32(opcode, 19, 16);
8305 setflags = BitIsSet(opcode, 20);
8306 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008307 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008308 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008309 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008310 if (BadReg(Rd) || Rn == 13)
8311 return false;
8312 break;
8313 case eEncodingA1:
8314 Rd = Bits32(opcode, 15, 12);
8315 Rn = Bits32(opcode, 19, 16);
8316 setflags = BitIsSet(opcode, 20);
8317 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008318
Johnny Chen7c5234d2011-02-18 23:41:11 +00008319 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008320 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008321 break;
8322 default:
8323 return false;
8324 }
8325
8326 // Read the first operand.
8327 uint32_t val1 = ReadCoreReg(Rn, &success);
8328 if (!success)
8329 return false;
8330
8331 uint32_t result = val1 | imm32;
8332
8333 EmulateInstruction::Context context;
8334 context.type = EmulateInstruction::eContextImmediate;
8335 context.SetNoArgs ();
8336
8337 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8338 return false;
8339 }
8340 return true;
8341}
8342
8343// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8344// value, and writes the result to the destination register. It can optionally update the condition flags based
8345// on the result.
8346bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008347EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008348{
8349#if 0
8350 // ARM pseudo code...
8351 if ConditionPassed() then
8352 EncodingSpecificOperations();
8353 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8354 result = R[n] OR shifted;
8355 if d == 15 then // Can only occur for ARM encoding
8356 ALUWritePC(result); // setflags is always FALSE here
8357 else
8358 R[d] = result;
8359 if setflags then
8360 APSR.N = result<31>;
8361 APSR.Z = IsZeroBit(result);
8362 APSR.C = carry;
8363 // APSR.V unchanged
8364#endif
8365
8366 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008367
Greg Clayton7bc39082011-03-24 23:53:38 +00008368 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008369 {
8370 uint32_t Rd, Rn, Rm;
8371 ARM_ShifterType shift_t;
8372 uint32_t shift_n; // the shift applied to the value read from Rm
8373 bool setflags;
8374 uint32_t carry;
8375 switch (encoding)
8376 {
8377 case eEncodingT1:
8378 Rd = Rn = Bits32(opcode, 2, 0);
8379 Rm = Bits32(opcode, 5, 3);
8380 setflags = !InITBlock();
8381 shift_t = SRType_LSL;
8382 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008383 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008384 case eEncodingT2:
8385 Rd = Bits32(opcode, 11, 8);
8386 Rn = Bits32(opcode, 19, 16);
8387 Rm = Bits32(opcode, 3, 0);
8388 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008389 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8390 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008391 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008392 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008393 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8394 return false;
8395 break;
8396 case eEncodingA1:
8397 Rd = Bits32(opcode, 15, 12);
8398 Rn = Bits32(opcode, 19, 16);
8399 Rm = Bits32(opcode, 3, 0);
8400 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008401 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008402
Johnny Chen7c5234d2011-02-18 23:41:11 +00008403 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008404 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008405 break;
8406 default:
8407 return false;
8408 }
8409
8410 // Read the first operand.
8411 uint32_t val1 = ReadCoreReg(Rn, &success);
8412 if (!success)
8413 return false;
8414
8415 // Read the second operand.
8416 uint32_t val2 = ReadCoreReg(Rm, &success);
8417 if (!success)
8418 return false;
8419
8420 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008421 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008422
8423 EmulateInstruction::Context context;
8424 context.type = EmulateInstruction::eContextImmediate;
8425 context.SetNoArgs ();
8426
8427 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8428 return false;
8429 }
8430 return true;
8431}
8432
Johnny Chened32e7c2011-02-22 23:42:58 +00008433// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8434// the destination register. It can optionally update the condition flags based on the result.
8435bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008436EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008437{
8438#if 0
8439 // ARM pseudo code...
8440 if ConditionPassed() then
8441 EncodingSpecificOperations();
8442 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8443 if d == 15 then // Can only occur for ARM encoding
8444 ALUWritePC(result); // setflags is always FALSE here
8445 else
8446 R[d] = result;
8447 if setflags then
8448 APSR.N = result<31>;
8449 APSR.Z = IsZeroBit(result);
8450 APSR.C = carry;
8451 APSR.V = overflow;
8452#endif
8453
8454 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008455
8456 uint32_t Rd; // the destination register
8457 uint32_t Rn; // the first operand
8458 bool setflags;
8459 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8460 switch (encoding) {
8461 case eEncodingT1:
8462 Rd = Bits32(opcode, 2, 0);
8463 Rn = Bits32(opcode, 5, 3);
8464 setflags = !InITBlock();
8465 imm32 = 0;
8466 break;
8467 case eEncodingT2:
8468 Rd = Bits32(opcode, 11, 8);
8469 Rn = Bits32(opcode, 19, 16);
8470 setflags = BitIsSet(opcode, 20);
8471 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8472 if (BadReg(Rd) || BadReg(Rn))
8473 return false;
8474 break;
8475 case eEncodingA1:
8476 Rd = Bits32(opcode, 15, 12);
8477 Rn = Bits32(opcode, 19, 16);
8478 setflags = BitIsSet(opcode, 20);
8479 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008480
Johnny Chened32e7c2011-02-22 23:42:58 +00008481 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008482 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008483 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008484 break;
8485 default:
8486 return false;
8487 }
8488 // Read the register value from the operand register Rn.
8489 uint32_t reg_val = ReadCoreReg(Rn, &success);
8490 if (!success)
8491 return false;
8492
8493 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8494
8495 EmulateInstruction::Context context;
8496 context.type = EmulateInstruction::eContextImmediate;
8497 context.SetNoArgs ();
8498
8499 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8500 return false;
8501
8502 return true;
8503}
8504
8505// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8506// result to the destination register. It can optionally update the condition flags based on the result.
8507bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008508EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008509{
8510#if 0
8511 // ARM pseudo code...
8512 if ConditionPassed() then
8513 EncodingSpecificOperations();
8514 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8515 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8516 if d == 15 then // Can only occur for ARM encoding
8517 ALUWritePC(result); // setflags is always FALSE here
8518 else
8519 R[d] = result;
8520 if setflags then
8521 APSR.N = result<31>;
8522 APSR.Z = IsZeroBit(result);
8523 APSR.C = carry;
8524 APSR.V = overflow;
8525#endif
8526
8527 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008528
8529 uint32_t Rd; // the destination register
8530 uint32_t Rn; // the first operand
8531 uint32_t Rm; // the second operand
8532 bool setflags;
8533 ARM_ShifterType shift_t;
8534 uint32_t shift_n; // the shift applied to the value read from Rm
8535 switch (encoding) {
8536 case eEncodingT1:
8537 Rd = Bits32(opcode, 11, 8);
8538 Rn = Bits32(opcode, 19, 16);
8539 Rm = Bits32(opcode, 3, 0);
8540 setflags = BitIsSet(opcode, 20);
8541 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8542 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8543 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8544 return false;
8545 break;
8546 case eEncodingA1:
8547 Rd = Bits32(opcode, 15, 12);
8548 Rn = Bits32(opcode, 19, 16);
8549 Rm = Bits32(opcode, 3, 0);
8550 setflags = BitIsSet(opcode, 20);
8551 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008552
Johnny Chened32e7c2011-02-22 23:42:58 +00008553 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008554 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008555 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008556 break;
8557 default:
8558 return false;
8559 }
8560 // Read the register value from register Rn.
8561 uint32_t val1 = ReadCoreReg(Rn, &success);
8562 if (!success)
8563 return false;
8564
8565 // Read the register value from register Rm.
8566 uint32_t val2 = ReadCoreReg(Rm, &success);
8567 if (!success)
8568 return false;
8569
8570 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8571 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8572
8573 EmulateInstruction::Context context;
8574 context.type = EmulateInstruction::eContextImmediate;
8575 context.SetNoArgs();
8576 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8577 return false;
8578
8579 return true;
8580}
8581
Johnny Chen90e607b2011-02-23 00:07:09 +00008582// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8583// an immediate value, and writes the result to the destination register. It can optionally update the condition
8584// flags based on the result.
8585bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008586EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008587{
8588#if 0
8589 // ARM pseudo code...
8590 if ConditionPassed() then
8591 EncodingSpecificOperations();
8592 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8593 if d == 15 then
8594 ALUWritePC(result); // setflags is always FALSE here
8595 else
8596 R[d] = result;
8597 if setflags then
8598 APSR.N = result<31>;
8599 APSR.Z = IsZeroBit(result);
8600 APSR.C = carry;
8601 APSR.V = overflow;
8602#endif
8603
8604 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008605
8606 uint32_t Rd; // the destination register
8607 uint32_t Rn; // the first operand
8608 bool setflags;
8609 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8610 switch (encoding) {
8611 case eEncodingA1:
8612 Rd = Bits32(opcode, 15, 12);
8613 Rn = Bits32(opcode, 19, 16);
8614 setflags = BitIsSet(opcode, 20);
8615 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008616
Johnny Chen90e607b2011-02-23 00:07:09 +00008617 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008618 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008619 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008620 break;
8621 default:
8622 return false;
8623 }
8624 // Read the register value from the operand register Rn.
8625 uint32_t reg_val = ReadCoreReg(Rn, &success);
8626 if (!success)
8627 return false;
8628
8629 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8630
8631 EmulateInstruction::Context context;
8632 context.type = EmulateInstruction::eContextImmediate;
8633 context.SetNoArgs ();
8634
8635 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8636 return false;
8637
8638 return true;
8639}
8640
8641// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8642// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8643// condition flags based on the result.
8644bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008645EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008646{
8647#if 0
8648 // ARM pseudo code...
8649 if ConditionPassed() then
8650 EncodingSpecificOperations();
8651 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8652 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8653 if d == 15 then
8654 ALUWritePC(result); // setflags is always FALSE here
8655 else
8656 R[d] = result;
8657 if setflags then
8658 APSR.N = result<31>;
8659 APSR.Z = IsZeroBit(result);
8660 APSR.C = carry;
8661 APSR.V = overflow;
8662#endif
8663
8664 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008665
8666 uint32_t Rd; // the destination register
8667 uint32_t Rn; // the first operand
8668 uint32_t Rm; // the second operand
8669 bool setflags;
8670 ARM_ShifterType shift_t;
8671 uint32_t shift_n; // the shift applied to the value read from Rm
8672 switch (encoding) {
8673 case eEncodingA1:
8674 Rd = Bits32(opcode, 15, 12);
8675 Rn = Bits32(opcode, 19, 16);
8676 Rm = Bits32(opcode, 3, 0);
8677 setflags = BitIsSet(opcode, 20);
8678 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008679
Johnny Chen90e607b2011-02-23 00:07:09 +00008680 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008681 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008682 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008683 break;
8684 default:
8685 return false;
8686 }
8687 // Read the register value from register Rn.
8688 uint32_t val1 = ReadCoreReg(Rn, &success);
8689 if (!success)
8690 return false;
8691
8692 // Read the register value from register Rm.
8693 uint32_t val2 = ReadCoreReg(Rm, &success);
8694 if (!success)
8695 return false;
8696
8697 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8698 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8699
8700 EmulateInstruction::Context context;
8701 context.type = EmulateInstruction::eContextImmediate;
8702 context.SetNoArgs();
8703 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8704 return false;
8705
8706 return true;
8707}
8708
Johnny Chen9b381772011-02-23 01:01:21 +00008709// Subtract with Carry (immediate) subtracts an immediate value and the value of
8710// NOT (Carry flag) from a register value, and writes the result to the destination register.
8711// It can optionally update the condition flags based on the result.
8712bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008713EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008714{
8715#if 0
8716 // ARM pseudo code...
8717 if ConditionPassed() then
8718 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008719 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008720 if d == 15 then // Can only occur for ARM encoding
8721 ALUWritePC(result); // setflags is always FALSE here
8722 else
8723 R[d] = result;
8724 if setflags then
8725 APSR.N = result<31>;
8726 APSR.Z = IsZeroBit(result);
8727 APSR.C = carry;
8728 APSR.V = overflow;
8729#endif
8730
8731 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008732
8733 uint32_t Rd; // the destination register
8734 uint32_t Rn; // the first operand
8735 bool setflags;
8736 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8737 switch (encoding) {
8738 case eEncodingT1:
8739 Rd = Bits32(opcode, 11, 8);
8740 Rn = Bits32(opcode, 19, 16);
8741 setflags = BitIsSet(opcode, 20);
8742 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8743 if (BadReg(Rd) || BadReg(Rn))
8744 return false;
8745 break;
8746 case eEncodingA1:
8747 Rd = Bits32(opcode, 15, 12);
8748 Rn = Bits32(opcode, 19, 16);
8749 setflags = BitIsSet(opcode, 20);
8750 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008751
Johnny Chen9b381772011-02-23 01:01:21 +00008752 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008753 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008754 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008755 break;
8756 default:
8757 return false;
8758 }
8759 // Read the register value from the operand register Rn.
8760 uint32_t reg_val = ReadCoreReg(Rn, &success);
8761 if (!success)
8762 return false;
8763
8764 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8765
8766 EmulateInstruction::Context context;
8767 context.type = EmulateInstruction::eContextImmediate;
8768 context.SetNoArgs ();
8769
8770 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8771 return false;
8772
8773 return true;
8774}
8775
8776// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8777// NOT (Carry flag) from a register value, and writes the result to the destination register.
8778// It can optionally update the condition flags based on the result.
8779bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008780EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008781{
8782#if 0
8783 // ARM pseudo code...
8784 if ConditionPassed() then
8785 EncodingSpecificOperations();
8786 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8787 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8788 if d == 15 then // Can only occur for ARM encoding
8789 ALUWritePC(result); // setflags is always FALSE here
8790 else
8791 R[d] = result;
8792 if setflags then
8793 APSR.N = result<31>;
8794 APSR.Z = IsZeroBit(result);
8795 APSR.C = carry;
8796 APSR.V = overflow;
8797#endif
8798
8799 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008800
8801 uint32_t Rd; // the destination register
8802 uint32_t Rn; // the first operand
8803 uint32_t Rm; // the second operand
8804 bool setflags;
8805 ARM_ShifterType shift_t;
8806 uint32_t shift_n; // the shift applied to the value read from Rm
8807 switch (encoding) {
8808 case eEncodingT1:
8809 Rd = Rn = Bits32(opcode, 2, 0);
8810 Rm = Bits32(opcode, 5, 3);
8811 setflags = !InITBlock();
8812 shift_t = SRType_LSL;
8813 shift_n = 0;
8814 break;
8815 case eEncodingT2:
8816 Rd = Bits32(opcode, 11, 8);
8817 Rn = Bits32(opcode, 19, 16);
8818 Rm = Bits32(opcode, 3, 0);
8819 setflags = BitIsSet(opcode, 20);
8820 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8821 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8822 return false;
8823 break;
8824 case eEncodingA1:
8825 Rd = Bits32(opcode, 15, 12);
8826 Rn = Bits32(opcode, 19, 16);
8827 Rm = Bits32(opcode, 3, 0);
8828 setflags = BitIsSet(opcode, 20);
8829 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008830
Johnny Chen9b381772011-02-23 01:01:21 +00008831 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008832 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008833 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008834 break;
8835 default:
8836 return false;
8837 }
8838 // Read the register value from register Rn.
8839 uint32_t val1 = ReadCoreReg(Rn, &success);
8840 if (!success)
8841 return false;
8842
8843 // Read the register value from register Rm.
8844 uint32_t val2 = ReadCoreReg(Rm, &success);
8845 if (!success)
8846 return false;
8847
8848 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8849 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8850
8851 EmulateInstruction::Context context;
8852 context.type = EmulateInstruction::eContextImmediate;
8853 context.SetNoArgs();
8854 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8855 return false;
8856
8857 return true;
8858}
8859
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008860// This instruction subtracts an immediate value from a register value, and writes the result
8861// to the destination register. It can optionally update the condition flags based on the result.
8862bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008863EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008864{
8865#if 0
8866 // ARM pseudo code...
8867 if ConditionPassed() then
8868 EncodingSpecificOperations();
8869 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8870 R[d] = result;
8871 if setflags then
8872 APSR.N = result<31>;
8873 APSR.Z = IsZeroBit(result);
8874 APSR.C = carry;
8875 APSR.V = overflow;
8876#endif
8877
8878 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008879
8880 uint32_t Rd; // the destination register
8881 uint32_t Rn; // the first operand
8882 bool setflags;
8883 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8884 switch (encoding) {
8885 case eEncodingT1:
8886 Rd = Bits32(opcode, 2, 0);
8887 Rn = Bits32(opcode, 5, 3);
8888 setflags = !InITBlock();
8889 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8890 break;
8891 case eEncodingT2:
8892 Rd = Rn = Bits32(opcode, 10, 8);
8893 setflags = !InITBlock();
8894 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8895 break;
8896 case eEncodingT3:
8897 Rd = Bits32(opcode, 11, 8);
8898 Rn = Bits32(opcode, 19, 16);
8899 setflags = BitIsSet(opcode, 20);
8900 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8901
8902 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8903 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008904 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008905
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008906 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008907 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008908 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008909
8910 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8911 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8912 return false;
8913 break;
8914 case eEncodingT4:
8915 Rd = Bits32(opcode, 11, 8);
8916 Rn = Bits32(opcode, 19, 16);
8917 setflags = BitIsSet(opcode, 20);
8918 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8919
8920 // if Rn == '1111' then SEE ADR;
8921 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008922 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008923
8924 // if Rn == '1101' then SEE SUB (SP minus immediate);
8925 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008926 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008927
8928 if (BadReg(Rd))
8929 return false;
8930 break;
8931 default:
8932 return false;
8933 }
8934 // Read the register value from the operand register Rn.
8935 uint32_t reg_val = ReadCoreReg(Rn, &success);
8936 if (!success)
8937 return false;
8938
8939 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8940
8941 EmulateInstruction::Context context;
8942 context.type = EmulateInstruction::eContextImmediate;
8943 context.SetNoArgs ();
8944
8945 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8946 return false;
8947
8948 return true;
8949}
8950
8951// This instruction subtracts an immediate value from a register value, and writes the result
8952// to the destination register. It can optionally update the condition flags based on the result.
8953bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008954EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008955{
8956#if 0
8957 // ARM pseudo code...
8958 if ConditionPassed() then
8959 EncodingSpecificOperations();
8960 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8961 if d == 15 then
8962 ALUWritePC(result); // setflags is always FALSE here
8963 else
8964 R[d] = result;
8965 if setflags then
8966 APSR.N = result<31>;
8967 APSR.Z = IsZeroBit(result);
8968 APSR.C = carry;
8969 APSR.V = overflow;
8970#endif
8971
8972 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008973
8974 uint32_t Rd; // the destination register
8975 uint32_t Rn; // the first operand
8976 bool setflags;
8977 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8978 switch (encoding) {
8979 case eEncodingA1:
8980 Rd = Bits32(opcode, 15, 12);
8981 Rn = Bits32(opcode, 19, 16);
8982 setflags = BitIsSet(opcode, 20);
8983 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8984
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008985 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008986 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008987 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008988
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008989 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008990 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008991 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008992
8993 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008994 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008995 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008996 break;
8997 default:
8998 return false;
8999 }
9000 // Read the register value from the operand register Rn.
9001 uint32_t reg_val = ReadCoreReg(Rn, &success);
9002 if (!success)
9003 return false;
9004
9005 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9006
9007 EmulateInstruction::Context context;
9008 context.type = EmulateInstruction::eContextImmediate;
9009 context.SetNoArgs ();
9010
9011 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9012 return false;
9013
9014 return true;
9015}
9016
Johnny Chen2115b412011-02-21 23:42:44 +00009017// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9018// immediate value. It updates the condition flags based on the result, and discards the result.
9019bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009020EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009021{
9022#if 0
9023 // ARM pseudo code...
9024 if ConditionPassed() then
9025 EncodingSpecificOperations();
9026 result = R[n] EOR imm32;
9027 APSR.N = result<31>;
9028 APSR.Z = IsZeroBit(result);
9029 APSR.C = carry;
9030 // APSR.V unchanged
9031#endif
9032
9033 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009034
Greg Clayton7bc39082011-03-24 23:53:38 +00009035 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009036 {
9037 uint32_t Rn;
9038 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9039 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9040 switch (encoding)
9041 {
9042 case eEncodingT1:
9043 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009044 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009045 if (BadReg(Rn))
9046 return false;
9047 break;
9048 case eEncodingA1:
9049 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009050 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009051 break;
9052 default:
9053 return false;
9054 }
9055
9056 // Read the first operand.
9057 uint32_t val1 = ReadCoreReg(Rn, &success);
9058 if (!success)
9059 return false;
9060
9061 uint32_t result = val1 ^ imm32;
9062
9063 EmulateInstruction::Context context;
9064 context.type = EmulateInstruction::eContextImmediate;
9065 context.SetNoArgs ();
9066
9067 if (!WriteFlags(context, result, carry))
9068 return false;
9069 }
9070 return true;
9071}
9072
9073// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9074// optionally-shifted register value. It updates the condition flags based on the result, and discards
9075// the result.
9076bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009077EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009078{
9079#if 0
9080 // ARM pseudo code...
9081 if ConditionPassed() then
9082 EncodingSpecificOperations();
9083 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9084 result = R[n] EOR shifted;
9085 APSR.N = result<31>;
9086 APSR.Z = IsZeroBit(result);
9087 APSR.C = carry;
9088 // APSR.V unchanged
9089#endif
9090
9091 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009092
Greg Clayton7bc39082011-03-24 23:53:38 +00009093 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009094 {
9095 uint32_t Rn, Rm;
9096 ARM_ShifterType shift_t;
9097 uint32_t shift_n; // the shift applied to the value read from Rm
9098 uint32_t carry;
9099 switch (encoding)
9100 {
9101 case eEncodingT1:
9102 Rn = Bits32(opcode, 19, 16);
9103 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009104 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009105 if (BadReg(Rn) || BadReg(Rm))
9106 return false;
9107 break;
9108 case eEncodingA1:
9109 Rn = Bits32(opcode, 19, 16);
9110 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009111 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009112 break;
9113 default:
9114 return false;
9115 }
9116
9117 // Read the first operand.
9118 uint32_t val1 = ReadCoreReg(Rn, &success);
9119 if (!success)
9120 return false;
9121
9122 // Read the second operand.
9123 uint32_t val2 = ReadCoreReg(Rm, &success);
9124 if (!success)
9125 return false;
9126
9127 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9128 uint32_t result = val1 ^ shifted;
9129
9130 EmulateInstruction::Context context;
9131 context.type = EmulateInstruction::eContextImmediate;
9132 context.SetNoArgs ();
9133
9134 if (!WriteFlags(context, result, carry))
9135 return false;
9136 }
9137 return true;
9138}
9139
Johnny Chende3cce32011-02-21 21:24:49 +00009140// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9141// It updates the condition flags based on the result, and discards the result.
9142bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009143EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009144{
9145#if 0
9146 // ARM pseudo code...
9147 if ConditionPassed() then
9148 EncodingSpecificOperations();
9149 result = R[n] AND imm32;
9150 APSR.N = result<31>;
9151 APSR.Z = IsZeroBit(result);
9152 APSR.C = carry;
9153 // APSR.V unchanged
9154#endif
9155
9156 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009157
Greg Clayton7bc39082011-03-24 23:53:38 +00009158 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009159 {
9160 uint32_t Rn;
9161 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9162 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9163 switch (encoding)
9164 {
9165 case eEncodingT1:
9166 Rn = Bits32(opcode, 19, 16);
9167 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9168 if (BadReg(Rn))
9169 return false;
9170 break;
9171 case eEncodingA1:
9172 Rn = Bits32(opcode, 19, 16);
9173 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9174 break;
9175 default:
9176 return false;
9177 }
9178
9179 // Read the first operand.
9180 uint32_t val1 = ReadCoreReg(Rn, &success);
9181 if (!success)
9182 return false;
9183
9184 uint32_t result = val1 & imm32;
9185
9186 EmulateInstruction::Context context;
9187 context.type = EmulateInstruction::eContextImmediate;
9188 context.SetNoArgs ();
9189
9190 if (!WriteFlags(context, result, carry))
9191 return false;
9192 }
9193 return true;
9194}
9195
9196// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9197// It updates the condition flags based on the result, and discards the result.
9198bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009199EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009200{
9201#if 0
9202 // ARM pseudo code...
9203 if ConditionPassed() then
9204 EncodingSpecificOperations();
9205 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9206 result = R[n] AND shifted;
9207 APSR.N = result<31>;
9208 APSR.Z = IsZeroBit(result);
9209 APSR.C = carry;
9210 // APSR.V unchanged
9211#endif
9212
9213 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009214
Greg Clayton7bc39082011-03-24 23:53:38 +00009215 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009216 {
9217 uint32_t Rn, Rm;
9218 ARM_ShifterType shift_t;
9219 uint32_t shift_n; // the shift applied to the value read from Rm
9220 uint32_t carry;
9221 switch (encoding)
9222 {
9223 case eEncodingT1:
9224 Rn = Bits32(opcode, 2, 0);
9225 Rm = Bits32(opcode, 5, 3);
9226 shift_t = SRType_LSL;
9227 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009228 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009229 case eEncodingT2:
9230 Rn = Bits32(opcode, 19, 16);
9231 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009232 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009233 if (BadReg(Rn) || BadReg(Rm))
9234 return false;
9235 break;
9236 case eEncodingA1:
9237 Rn = Bits32(opcode, 19, 16);
9238 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009239 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009240 break;
9241 default:
9242 return false;
9243 }
9244
9245 // Read the first operand.
9246 uint32_t val1 = ReadCoreReg(Rn, &success);
9247 if (!success)
9248 return false;
9249
9250 // Read the second operand.
9251 uint32_t val2 = ReadCoreReg(Rm, &success);
9252 if (!success)
9253 return false;
9254
9255 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9256 uint32_t result = val1 & shifted;
9257
9258 EmulateInstruction::Context context;
9259 context.type = EmulateInstruction::eContextImmediate;
9260 context.SetNoArgs ();
9261
9262 if (!WriteFlags(context, result, carry))
9263 return false;
9264 }
9265 return true;
9266}
Caroline Ticed05b4902011-03-29 21:24:06 +00009267
9268// A8.6.216 SUB (SP minus register)
9269bool
9270EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9271{
9272#if 0
9273 if ConditionPassed() then
9274 EncodingSpecificOperations();
9275 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009276 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009277 if d == 15 then // Can only occur for ARM encoding
9278 ALUWritePC(result); // setflags is always FALSE here
9279 else
9280 R[d] = result;
9281 if setflags then
9282 APSR.N = result<31>;
9283 APSR.Z = IsZeroBit(result);
9284 APSR.C = carry;
9285 APSR.V = overflow;
9286#endif
9287
9288 bool success = false;
9289
9290 if (ConditionPassed(opcode))
9291 {
9292 uint32_t d;
9293 uint32_t m;
9294 bool setflags;
9295 ARM_ShifterType shift_t;
9296 uint32_t shift_n;
9297
9298 switch (encoding)
9299 {
9300 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009301 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009302 d = Bits32 (opcode, 11, 8);
9303 m = Bits32 (opcode, 3, 0);
9304 setflags = BitIsSet (opcode, 20);
9305
9306 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9307 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9308
9309 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9310 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9311 return false;
9312
9313 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9314 if ((d == 15) || BadReg (m))
9315 return false;
9316 break;
9317
9318 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009319 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009320 d = Bits32 (opcode, 15, 12);
9321 m = Bits32 (opcode, 3, 0);
9322 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009323
Greg Clayton061b79d2011-05-09 20:18:18 +00009324 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009325 if (d == 15 && setflags)
9326 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009327
9328 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9329 shift_n = DecodeImmShiftARM (opcode, shift_t);
9330 break;
9331
9332 default:
9333 return false;
9334 }
9335
9336 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9337 uint32_t Rm = ReadCoreReg (m, &success);
9338 if (!success)
9339 return false;
9340
9341 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9342
Greg Clayton061b79d2011-05-09 20:18:18 +00009343 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009344 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9345 if (!success)
9346 return false;
9347
9348 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9349
9350 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009351 context.type = eContextArithmetic;
9352 RegisterInfo sp_reg;
9353 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9354 RegisterInfo dwarf_reg;
9355 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +00009356 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9357
Caroline Ticeef440002011-03-30 05:40:56 +00009358 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009359 return false;
9360 }
9361 return true;
9362}
9363
9364
9365// A8.6.7 ADD (register-shifted register)
9366bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009367EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009368{
9369#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009370 if ConditionPassed() then
9371 EncodingSpecificOperations();
9372 shift_n = UInt(R[s]<7:0>);
9373 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009374 (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009375 R[d] = result;
9376 if setflags then
9377 APSR.N = result<31>;
9378 APSR.Z = IsZeroBit(result);
9379 APSR.C = carry;
9380 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009381#endif
9382
Caroline Ticec08ed382011-03-29 23:03:16 +00009383 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009384
9385 if (ConditionPassed(opcode))
9386 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009387 uint32_t d;
9388 uint32_t n;
9389 uint32_t m;
9390 uint32_t s;
9391 bool setflags;
9392 ARM_ShifterType shift_t;
9393
Caroline Ticed05b4902011-03-29 21:24:06 +00009394 switch (encoding)
9395 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009396 case eEncodingA1:
9397 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9398 d = Bits32 (opcode, 15, 12);
9399 n = Bits32 (opcode, 19, 16);
9400 m = Bits32 (opcode, 3, 0);
9401 s = Bits32 (opcode, 11, 8);
9402
Greg Clayton061b79d2011-05-09 20:18:18 +00009403 // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
Caroline Ticec08ed382011-03-29 23:03:16 +00009404 setflags = BitIsSet (opcode, 20);
9405 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9406
9407 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9408 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9409 return false;
9410 break;
9411
9412 default:
9413 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009414 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009415
9416 // shift_n = UInt(R[s]<7:0>);
9417 uint32_t Rs = ReadCoreReg (s, &success);
9418 if (!success)
9419 return false;
9420
9421 uint32_t shift_n = Bits32 (Rs, 7, 0);
9422
9423 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9424 uint32_t Rm = ReadCoreReg (m, &success);
9425 if (!success)
9426 return false;
9427
9428 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9429
Greg Clayton061b79d2011-05-09 20:18:18 +00009430 // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009431 uint32_t Rn = ReadCoreReg (n, &success);
9432 if (!success)
9433 return false;
9434
9435 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9436
9437 // R[d] = result;
9438 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009439 context.type = eContextArithmetic;
9440 RegisterInfo reg_n;
9441 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9442 RegisterInfo reg_m;
9443 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009444
9445 context.SetRegisterRegisterOperands (reg_n, reg_m);
9446
9447 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9448 return false;
9449
9450 // if setflags then
9451 // APSR.N = result<31>;
9452 // APSR.Z = IsZeroBit(result);
9453 // APSR.C = carry;
9454 // APSR.V = overflow;
9455 if (setflags)
9456 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009457 }
9458 return true;
9459}
9460
9461// A8.6.213 SUB (register)
9462bool
9463EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9464{
9465#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009466 if ConditionPassed() then
9467 EncodingSpecificOperations();
9468 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009469 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009470 if d == 15 then // Can only occur for ARM encoding
9471 ALUWritePC(result); // setflags is always FALSE here
9472 else
9473 R[d] = result;
9474 if setflags then
9475 APSR.N = result<31>;
9476 APSR.Z = IsZeroBit(result);
9477 APSR.C = carry;
9478 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009479#endif
9480
Caroline Tice4cccd532011-03-29 23:44:20 +00009481 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009482
9483 if (ConditionPassed(opcode))
9484 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009485 uint32_t d;
9486 uint32_t n;
9487 uint32_t m;
9488 bool setflags;
9489 ARM_ShifterType shift_t;
9490 uint32_t shift_n;
9491
Caroline Ticed05b4902011-03-29 21:24:06 +00009492 switch (encoding)
9493 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009494 case eEncodingT1:
9495 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9496 d = Bits32 (opcode, 2, 0);
9497 n = Bits32 (opcode, 5, 3);
9498 m = Bits32 (opcode, 8, 6);
9499 setflags = !InITBlock();
9500
9501 // (shift_t, shift_n) = (SRType_LSL, 0);
9502 shift_t = SRType_LSL;
9503 shift_n = 0;
9504
9505 break;
9506
9507 case eEncodingT2:
Greg Clayton061b79d2011-05-09 20:18:18 +00009508 // if Rd == Ô1111Õ && S == Ô1Õ then SEE CMP (register);
9509 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9510 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009511 d = Bits32 (opcode, 11, 8);
9512 n = Bits32 (opcode, 19, 16);
9513 m = Bits32 (opcode, 3, 0);
9514 setflags = BitIsSet (opcode, 20);
9515
9516 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9517 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9518
9519 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9520 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9521 return false;
9522
9523 break;
9524
9525 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009526 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9527 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009528 d = Bits32 (opcode, 15, 12);
9529 n = Bits32 (opcode, 19, 16);
9530 m = Bits32 (opcode, 3, 0);
9531 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009532
Greg Clayton061b79d2011-05-09 20:18:18 +00009533 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009534 if ((d == 15) && setflags)
9535 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009536
9537 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9538 shift_n = DecodeImmShiftARM (opcode, shift_t);
9539
9540 break;
9541
9542 default:
9543 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009544 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009545
9546 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9547 uint32_t Rm = ReadCoreReg (m, &success);
9548 if (!success)
9549 return false;
9550
9551 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9552
Greg Clayton061b79d2011-05-09 20:18:18 +00009553 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009554 uint32_t Rn = ReadCoreReg (n, &success);
9555 if (!success)
9556 return false;
9557
9558 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9559
9560 // if d == 15 then // Can only occur for ARM encoding
9561 // ALUWritePC(result); // setflags is always FALSE here
9562 // else
9563 // R[d] = result;
9564 // if setflags then
9565 // APSR.N = result<31>;
9566 // APSR.Z = IsZeroBit(result);
9567 // APSR.C = carry;
9568 // APSR.V = overflow;
9569
9570 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009571 context.type = eContextArithmetic;
9572 RegisterInfo reg_n;
9573 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9574 RegisterInfo reg_m;
9575 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009576 context.SetRegisterRegisterOperands (reg_n, reg_m);
9577
Caroline Ticeef440002011-03-30 05:40:56 +00009578 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009579 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009580 }
9581 return true;
9582}
Caroline Tice4cccd532011-03-29 23:44:20 +00009583
Caroline Ticed05b4902011-03-29 21:24:06 +00009584// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009585// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9586// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009587bool
9588EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9589{
9590#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009591 if ConditionPassed() then
9592 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9593 address = R[n] + imm32;
9594 if ExclusiveMonitorsPass(address,4) then
9595 MemA[address,4] = R[t];
9596 R[d] = 0;
9597 else
9598 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009599#endif
9600
Caroline Tice5168b6c2011-03-30 05:15:46 +00009601 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009602
9603 if (ConditionPassed(opcode))
9604 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009605 uint32_t d;
9606 uint32_t t;
9607 uint32_t n;
9608 uint32_t imm32;
9609 const uint32_t addr_byte_size = GetAddressByteSize();
9610
Caroline Ticed05b4902011-03-29 21:24:06 +00009611 switch (encoding)
9612 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009613 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009614 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009615 d = Bits32 (opcode, 11, 8);
9616 t = Bits32 (opcode, 15, 12);
9617 n = Bits32 (opcode, 19, 16);
9618 imm32 = Bits32 (opcode, 7, 0) << 2;
9619
9620 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9621 if (BadReg (d) || BadReg (t) || (n == 15))
9622 return false;
9623
9624 // if d == n || d == t then UNPREDICTABLE;
9625 if ((d == n) || (d == t))
9626 return false;
9627
9628 break;
9629
9630 case eEncodingA1:
9631 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9632 d = Bits32 (opcode, 15, 12);
9633 t = Bits32 (opcode, 3, 0);
9634 n = Bits32 (opcode, 19, 16);
9635 imm32 = 0;
9636
9637 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9638 if ((d == 15) || (t == 15) || (n == 15))
9639 return false;
9640
9641 // if d == n || d == t then UNPREDICTABLE;
9642 if ((d == n) || (d == t))
9643 return false;
9644
9645 break;
9646
9647 default:
9648 return false;
9649 }
9650
9651 // address = R[n] + imm32;
9652 uint32_t Rn = ReadCoreReg (n, &success);
9653 if (!success)
9654 return false;
9655
9656 addr_t address = Rn + imm32;
9657
Greg Claytonc07d4512011-04-26 23:48:45 +00009658 RegisterInfo base_reg;
9659 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9660 RegisterInfo data_reg;
9661 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009662 EmulateInstruction::Context context;
9663 context.type = eContextRegisterStore;
9664 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9665
9666 // if ExclusiveMonitorsPass(address,4) then
9667 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9668 // always return true.
9669 if (true)
9670 {
9671 // MemA[address,4] = R[t];
9672 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9673 if (!success)
9674 return false;
9675
9676 if (!MemAWrite (context, address, Rt, addr_byte_size))
9677 return false;
9678
9679 // R[d] = 0;
9680 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9681 return false;
9682 }
9683 else
9684 {
9685 // R[d] = 1;
9686 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9687 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009688 }
9689 }
9690 return true;
9691}
9692
9693// A8.6.197 STRB (immediate, ARM)
9694bool
9695EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9696{
9697#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009698 if ConditionPassed() then
9699 EncodingSpecificOperations();
9700 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9701 address = if index then offset_addr else R[n];
9702 MemU[address,1] = R[t]<7:0>;
9703 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009704#endif
9705
Caroline Ticeef440002011-03-30 05:40:56 +00009706 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009707
9708 if (ConditionPassed(opcode))
9709 {
Caroline Ticeef440002011-03-30 05:40:56 +00009710 uint32_t t;
9711 uint32_t n;
9712 uint32_t imm32;
9713 bool index;
9714 bool add;
9715 bool wback;
9716
Caroline Ticed05b4902011-03-29 21:24:06 +00009717 switch (encoding)
9718 {
Caroline Ticeef440002011-03-30 05:40:56 +00009719 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009720 // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
Caroline Ticeef440002011-03-30 05:40:56 +00009721 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9722 t = Bits32 (opcode, 15, 12);
9723 n = Bits32 (opcode, 19, 16);
9724 imm32 = Bits32 (opcode, 11, 0);
9725
Greg Clayton061b79d2011-05-09 20:18:18 +00009726 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeef440002011-03-30 05:40:56 +00009727 index = BitIsSet (opcode, 24);
9728 add = BitIsSet (opcode, 23);
9729 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9730
9731 // if t == 15 then UNPREDICTABLE;
9732 if (t == 15)
9733 return false;
9734
9735 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9736 if (wback && ((n == 15) || (n == t)))
9737 return false;
9738
9739 break;
9740
9741 default:
9742 return false;
9743 }
9744
9745 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9746 uint32_t Rn = ReadCoreReg (n, &success);
9747 if (!success)
9748 return false;
9749
9750 addr_t offset_addr;
9751 if (add)
9752 offset_addr = Rn + imm32;
9753 else
9754 offset_addr = Rn - imm32;
9755
9756 // address = if index then offset_addr else R[n];
9757 addr_t address;
9758 if (index)
9759 address = offset_addr;
9760 else
9761 address = Rn;
9762
9763 // MemU[address,1] = R[t]<7:0>;
9764 uint32_t Rt = ReadCoreReg (t, &success);
9765 if (!success)
9766 return false;
9767
Greg Claytonc07d4512011-04-26 23:48:45 +00009768 RegisterInfo base_reg;
9769 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9770 RegisterInfo data_reg;
9771 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticeef440002011-03-30 05:40:56 +00009772 EmulateInstruction::Context context;
9773 context.type = eContextRegisterStore;
9774 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9775
9776 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9777 return false;
9778
9779 // if wback then R[n] = offset_addr;
9780 if (wback)
9781 {
Caroline Tice523c5542011-04-13 00:42:12 +00009782 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009783 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009784 }
9785 }
9786 return true;
9787}
9788
9789// A8.6.194 STR (immediate, ARM)
9790bool
9791EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9792{
9793#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009794 if ConditionPassed() then
9795 EncodingSpecificOperations();
9796 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9797 address = if index then offset_addr else R[n];
9798 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9799 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009800#endif
9801
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009802 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009803
9804 if (ConditionPassed(opcode))
9805 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009806 uint32_t t;
9807 uint32_t n;
9808 uint32_t imm32;
9809 bool index;
9810 bool add;
9811 bool wback;
9812
9813 const uint32_t addr_byte_size = GetAddressByteSize();
9814
Caroline Ticed05b4902011-03-29 21:24:06 +00009815 switch (encoding)
9816 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009817 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009818 // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
9819 // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009820 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9821 t = Bits32 (opcode, 15, 12);
9822 n = Bits32 (opcode, 19, 16);
9823 imm32 = Bits32 (opcode, 11, 0);
9824
Greg Clayton061b79d2011-05-09 20:18:18 +00009825 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009826 index = BitIsSet (opcode, 24);
9827 add = BitIsSet (opcode, 23);
9828 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9829
9830 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9831 if (wback && ((n == 15) || (n == t)))
9832 return false;
9833
9834 break;
9835
9836 default:
9837 return false;
9838 }
9839
9840 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9841 uint32_t Rn = ReadCoreReg (n, &success);
9842 if (!success)
9843 return false;
9844
9845 addr_t offset_addr;
9846 if (add)
9847 offset_addr = Rn + imm32;
9848 else
9849 offset_addr = Rn - imm32;
9850
9851 // address = if index then offset_addr else R[n];
9852 addr_t address;
9853 if (index)
9854 address = offset_addr;
9855 else
9856 address = Rn;
9857
Greg Claytonc07d4512011-04-26 23:48:45 +00009858 RegisterInfo base_reg;
9859 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9860 RegisterInfo data_reg;
9861 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009862 EmulateInstruction::Context context;
9863 context.type = eContextRegisterStore;
9864 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9865
9866 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9867 uint32_t Rt = ReadCoreReg (t, &success);
9868 if (!success)
9869 return false;
9870
9871 if (t == 15)
9872 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009873 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009874 if (!success)
9875 return false;
9876
9877 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9878 return false;
9879 }
9880 else
9881 {
9882 if (!MemUWrite (context, address, Rt, addr_byte_size))
9883 return false;
9884 }
9885
9886 // if wback then R[n] = offset_addr;
9887 if (wback)
9888 {
9889 context.type = eContextAdjustBaseRegister;
9890 context.SetImmediate (offset_addr);
9891
9892 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9893 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009894 }
9895 }
9896 return true;
9897}
9898
Caroline Ticed05b4902011-03-29 21:24:06 +00009899// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009900// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9901// 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 +00009902bool
9903EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9904{
9905#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009906 if ConditionPassed() then
9907 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9908 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9909 address = if index then offset_addr else R[n];
9910 R[t] = MemA[address,4];
9911 R[t2] = MemA[address+4,4];
9912 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009913#endif
9914
Caroline Tice1697dd72011-03-30 17:11:45 +00009915 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009916
9917 if (ConditionPassed(opcode))
9918 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009919 uint32_t t;
9920 uint32_t t2;
9921 uint32_t n;
9922 uint32_t imm32;
9923 bool index;
9924 bool add;
9925 bool wback;
9926
Caroline Ticed05b4902011-03-29 21:24:06 +00009927 switch (encoding)
9928 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009929 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009930 //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
9931 //if Rn == Ô1111Õ then SEE LDRD (literal);
9932 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice1697dd72011-03-30 17:11:45 +00009933 t = Bits32 (opcode, 15, 12);
9934 t2 = Bits32 (opcode, 11, 8);
9935 n = Bits32 (opcode, 19, 16);
9936 imm32 = Bits32 (opcode, 7, 0) << 2;
9937
Greg Clayton061b79d2011-05-09 20:18:18 +00009938 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +00009939 index = BitIsSet (opcode, 24);
9940 add = BitIsSet (opcode, 23);
9941 wback = BitIsSet (opcode, 21);
9942
9943 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9944 if (wback && ((n == t) || (n == t2)))
9945 return false;
9946
9947 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9948 if (BadReg (t) || BadReg (t2) || (t == t2))
9949 return false;
9950
9951 break;
9952
9953 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009954 //if Rn == Ô1111Õ then SEE LDRD (literal);
9955 //if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +00009956 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9957 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009958 if (BitIsSet (t, 0))
9959 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009960 t2 = t + 1;
9961 n = Bits32 (opcode, 19, 16);
9962 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9963
Greg Clayton061b79d2011-05-09 20:18:18 +00009964 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +00009965 index = BitIsSet (opcode, 24);
9966 add = BitIsSet (opcode, 23);
9967 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9968
Greg Clayton061b79d2011-05-09 20:18:18 +00009969 //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +00009970 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9971 return false;
9972
9973 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9974 if (wback && ((n == t) || (n == t2)))
9975 return false;
9976
9977 //if t2 == 15 then UNPREDICTABLE;
9978 if (t2 == 15)
9979 return false;
9980
9981 break;
9982
9983 default:
9984 return false;
9985 }
9986
9987 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9988 uint32_t Rn = ReadCoreReg (n, &success);
9989 if (!success)
9990 return false;
9991
9992 addr_t offset_addr;
9993 if (add)
9994 offset_addr = Rn + imm32;
9995 else
9996 offset_addr = Rn - imm32;
9997
9998 //address = if index then offset_addr else R[n];
9999 addr_t address;
10000 if (index)
10001 address = offset_addr;
10002 else
10003 address = Rn;
10004
10005 //R[t] = MemA[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +000010006 RegisterInfo base_reg;
10007 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1697dd72011-03-30 17:11:45 +000010008
10009 EmulateInstruction::Context context;
10010 context.type = eContextRegisterLoad;
10011 context.SetRegisterPlusOffset (base_reg, address - Rn);
10012
10013 const uint32_t addr_byte_size = GetAddressByteSize();
10014 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10015 if (!success)
10016 return false;
10017
10018 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10019 return false;
10020
10021 //R[t2] = MemA[address+4,4];
10022
10023 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10024 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10025 if (!success)
10026 return false;
10027
10028 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10029 return false;
10030
10031 //if wback then R[n] = offset_addr;
10032 if (wback)
10033 {
10034 context.type = eContextAdjustBaseRegister;
10035 context.SetAddress (offset_addr);
10036
10037 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10038 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010039 }
10040 }
10041 return true;
10042}
10043
Caroline Ticed05b4902011-03-29 21:24:06 +000010044// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010045// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10046// 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 +000010047bool
10048EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10049{
10050#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010051 if ConditionPassed() then
10052 EncodingSpecificOperations();
10053 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10054 address = if index then offset_addr else R[n];
10055 R[t] = MemA[address,4];
10056 R[t2] = MemA[address+4,4];
10057 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010058#endif
10059
Caroline Ticeeab301f2011-03-30 17:54:52 +000010060 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010061
10062 if (ConditionPassed(opcode))
10063 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010064 uint32_t t;
10065 uint32_t t2;
10066 uint32_t n;
10067 uint32_t m;
10068 bool index;
10069 bool add;
10070 bool wback;
10071
Caroline Ticed05b4902011-03-29 21:24:06 +000010072 switch (encoding)
10073 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010074 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010075 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010076 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10077 t = Bits32 (opcode, 15, 12);
10078 if (BitIsSet (t, 0))
10079 return false;
10080 t2 = t + 1;
10081 n = Bits32 (opcode, 19, 16);
10082 m = Bits32 (opcode, 3, 0);
10083
Greg Clayton061b79d2011-05-09 20:18:18 +000010084 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010085 index = BitIsSet (opcode, 24);
10086 add = BitIsSet (opcode, 23);
10087 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10088
Greg Clayton061b79d2011-05-09 20:18:18 +000010089 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010090 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10091 return false;
10092
10093 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10094 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10095 return false;
10096
10097 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10098 if (wback && ((n == 15) || (n == t) || (n == t2)))
10099 return false;
10100
10101 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10102 if ((ArchVersion() < 6) && wback && (m == n))
10103 return false;
10104 break;
10105
10106 default:
10107 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010108 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010109
Caroline Ticeeab301f2011-03-30 17:54:52 +000010110 uint32_t Rn = ReadCoreReg (n, &success);
10111 if (!success)
10112 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010113 RegisterInfo base_reg;
10114 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010115
Caroline Ticeeab301f2011-03-30 17:54:52 +000010116 uint32_t Rm = ReadCoreReg (m, &success);
10117 if (!success)
10118 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010119 RegisterInfo offset_reg;
10120 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010121
Caroline Ticeeab301f2011-03-30 17:54:52 +000010122 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10123 addr_t offset_addr;
10124 if (add)
10125 offset_addr = Rn + Rm;
10126 else
10127 offset_addr = Rn - Rm;
10128
10129 // address = if index then offset_addr else R[n];
10130 addr_t address;
10131 if (index)
10132 address = offset_addr;
10133 else
10134 address = Rn;
10135
10136 EmulateInstruction::Context context;
10137 context.type = eContextRegisterLoad;
10138 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10139
10140 // R[t] = MemA[address,4];
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 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10152 if (!success)
10153 return false;
10154
10155 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10156 return false;
10157
10158 // if wback then R[n] = offset_addr;
10159 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010160 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010161 context.type = eContextAdjustBaseRegister;
10162 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010163
Caroline Ticeeab301f2011-03-30 17:54:52 +000010164 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10165 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010166 }
10167 }
10168 return true;
10169}
Caroline Ticed05b4902011-03-29 21:24:06 +000010170
10171// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010172// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10173// 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 +000010174bool
10175EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10176{
10177#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010178 if ConditionPassed() then
10179 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10180 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10181 address = if index then offset_addr else R[n];
10182 MemA[address,4] = R[t];
10183 MemA[address+4,4] = R[t2];
10184 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010185#endif
10186
Caroline Tice74467fe2011-03-30 19:02:56 +000010187 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010188
Caroline Tice74467fe2011-03-30 19:02:56 +000010189 if (ConditionPassed(opcode))
10190 {
10191 uint32_t t;
10192 uint32_t t2;
10193 uint32_t n;
10194 uint32_t imm32;
10195 bool index;
10196 bool add;
10197 bool wback;
10198
10199 switch (encoding)
10200 {
10201 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010202 // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10203 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice74467fe2011-03-30 19:02:56 +000010204 t = Bits32 (opcode, 15, 12);
10205 t2 = Bits32 (opcode, 11, 8);
10206 n = Bits32 (opcode, 19, 16);
10207 imm32 = Bits32 (opcode, 7, 0) << 2;
10208
Greg Clayton061b79d2011-05-09 20:18:18 +000010209 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010210 index = BitIsSet (opcode, 24);
10211 add = BitIsSet (opcode, 23);
10212 wback = BitIsSet (opcode, 21);
10213
10214 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10215 if (wback && ((n == t) || (n == t2)))
10216 return false;
10217
10218 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10219 if ((n == 15) || BadReg (t) || BadReg (t2))
10220 return false;
10221
10222 break;
10223
10224 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010225 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010226 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10227 t = Bits32 (opcode, 15, 12);
10228 if (BitIsSet (t, 0))
10229 return false;
10230
10231 t2 = t + 1;
10232 n = Bits32 (opcode, 19, 16);
10233 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10234
Greg Clayton061b79d2011-05-09 20:18:18 +000010235 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010236 index = BitIsSet (opcode, 24);
10237 add = BitIsSet (opcode, 23);
10238 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10239
Greg Clayton061b79d2011-05-09 20:18:18 +000010240 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010241 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10242 return false;
10243
10244 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10245 if (wback && ((n == 15) || (n == t) || (n == t2)))
10246 return false;
10247
10248 // if t2 == 15 then UNPREDICTABLE;
10249 if (t2 == 15)
10250 return false;
10251
10252 break;
10253
10254 default:
10255 return false;
10256 }
10257
Greg Claytonc07d4512011-04-26 23:48:45 +000010258 RegisterInfo base_reg;
10259 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010260
10261 uint32_t Rn = ReadCoreReg (n, &success);
10262 if (!success)
10263 return false;
10264
10265 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10266 addr_t offset_addr;
10267 if (add)
10268 offset_addr = Rn + imm32;
10269 else
10270 offset_addr = Rn - imm32;
10271
10272 //address = if index then offset_addr else R[n];
10273 addr_t address;
10274 if (index)
10275 address = offset_addr;
10276 else
10277 address = Rn;
10278
10279 //MemA[address,4] = R[t];
Greg Claytonc07d4512011-04-26 23:48:45 +000010280 RegisterInfo data_reg;
10281 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010282
10283 uint32_t data = ReadCoreReg (t, &success);
10284 if (!success)
10285 return false;
10286
10287 EmulateInstruction::Context context;
10288 context.type = eContextRegisterStore;
10289 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10290
10291 const uint32_t addr_byte_size = GetAddressByteSize();
10292
10293 if (!MemAWrite (context, address, data, addr_byte_size))
10294 return false;
10295
10296 //MemA[address+4,4] = R[t2];
Greg Claytonc07d4512011-04-26 23:48:45 +000010297 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010298 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10299
10300 data = ReadCoreReg (t2, &success);
10301 if (!success)
10302 return false;
10303
10304 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10305 return false;
10306
10307 //if wback then R[n] = offset_addr;
10308 if (wback)
10309 {
10310 context.type = eContextAdjustBaseRegister;
10311 context.SetAddress (offset_addr);
10312
10313 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10314 return false;
10315 }
10316 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010317 return true;
10318}
10319
10320
10321// A8.6.201 STRD (register)
10322bool
10323EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10324{
10325#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010326 if ConditionPassed() then
10327 EncodingSpecificOperations();
10328 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10329 address = if index then offset_addr else R[n];
10330 MemA[address,4] = R[t];
10331 MemA[address+4,4] = R[t2];
10332 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010333#endif
10334
Caroline Tice74467fe2011-03-30 19:02:56 +000010335 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010336
Caroline Tice74467fe2011-03-30 19:02:56 +000010337 if (ConditionPassed(opcode))
10338 {
10339 uint32_t t;
10340 uint32_t t2;
10341 uint32_t n;
10342 uint32_t m;
10343 bool index;
10344 bool add;
10345 bool wback;
10346
10347 switch (encoding)
10348 {
10349 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010350 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010351 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10352 t = Bits32 (opcode, 15, 12);
10353 if (BitIsSet (t, 0))
10354 return false;
10355
10356 t2 = t+1;
10357 n = Bits32 (opcode, 19, 16);
10358 m = Bits32 (opcode, 3, 0);
10359
Greg Clayton061b79d2011-05-09 20:18:18 +000010360 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010361 index = BitIsSet (opcode, 24);
10362 add = BitIsSet (opcode, 23);
10363 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10364
Greg Clayton061b79d2011-05-09 20:18:18 +000010365 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010366 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10367 return false;
10368
10369 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10370 if ((t2 == 15) || (m == 15))
10371 return false;
10372
10373 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10374 if (wback && ((n == 15) || (n == t) || (n == t2)))
10375 return false;
10376
10377 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010378 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010379 return false;
10380
10381 break;
10382
10383 default:
10384 return false;
10385 }
10386
Greg Claytonc07d4512011-04-26 23:48:45 +000010387 RegisterInfo base_reg;
10388 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10389 RegisterInfo offset_reg;
10390 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10391 RegisterInfo data_reg;
Caroline Tice74467fe2011-03-30 19:02:56 +000010392
10393 uint32_t Rn = ReadCoreReg (n, &success);
10394 if (!success)
10395 return false;
10396
10397 uint32_t Rm = ReadCoreReg (m, &success);
10398 if (!success)
10399 return false;
10400
10401 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10402 addr_t offset_addr;
10403 if (add)
10404 offset_addr = Rn + Rm;
10405 else
10406 offset_addr = Rn - Rm;
10407
10408 // address = if index then offset_addr else R[n];
10409 addr_t address;
10410 if (index)
10411 address = offset_addr;
10412 else
10413 address = Rn;
10414 // MemA[address,4] = R[t];
10415 uint32_t Rt = ReadCoreReg (t, &success);
10416 if (!success)
10417 return false;
10418
10419 EmulateInstruction::Context context;
10420 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +000010421 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010422 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10423
10424 const uint32_t addr_byte_size = GetAddressByteSize();
10425
10426 if (!MemAWrite (context, address, Rt, addr_byte_size))
10427 return false;
10428
10429 // MemA[address+4,4] = R[t2];
10430 uint32_t Rt2 = ReadCoreReg (t2, &success);
10431 if (!success)
10432 return false;
10433
Greg Claytonc07d4512011-04-26 23:48:45 +000010434 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010435
10436 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10437
10438 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10439 return false;
10440
10441 // if wback then R[n] = offset_addr;
10442 if (wback)
10443 {
10444 context.type = eContextAdjustBaseRegister;
10445 context.SetAddress (offset_addr);
10446
10447 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10448 return false;
10449
10450 }
10451 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010452 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010453}
10454
Caroline Tice4f605582011-03-31 00:02:51 +000010455// A8.6.319 VLDM
10456// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10457// an ARM core register.
10458bool
10459EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10460{
10461#if 0
10462 if ConditionPassed() then
10463 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10464 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010465 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010466 for r = 0 to regs-1
10467 if single_regs then
10468 S[d+r] = MemA[address,4]; address = address+4;
10469 else
10470 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10471 // Combine the word-aligned words in the correct order for current endianness.
10472 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10473#endif
10474
10475 bool success = false;
10476
10477 if (ConditionPassed(opcode))
10478 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010479 bool single_regs;
10480 bool add;
10481 bool wback;
10482 uint32_t d;
10483 uint32_t n;
10484 uint32_t imm32;
10485 uint32_t regs;
10486
Caroline Tice4f605582011-03-31 00:02:51 +000010487 switch (encoding)
10488 {
10489 case eEncodingT1:
10490 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010491 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10492 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10493 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10494 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010495 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10496 return false;
10497
10498 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010499 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice4f605582011-03-31 00:02:51 +000010500 single_regs = false;
10501 add = BitIsSet (opcode, 23);
10502 wback = BitIsSet (opcode, 21);
10503
Greg Clayton061b79d2011-05-09 20:18:18 +000010504 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice4f605582011-03-31 00:02:51 +000010505 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10506 n = Bits32 (opcode, 19, 16);
10507 imm32 = Bits32 (opcode, 7, 0) << 2;
10508
Greg Clayton061b79d2011-05-09 20:18:18 +000010509 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
Caroline Tice4f605582011-03-31 00:02:51 +000010510 regs = Bits32 (opcode, 7, 0) / 2;
10511
10512 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10513 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10514 return false;
10515
10516 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10517 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10518 return false;
10519
10520 break;
10521
10522 case eEncodingT2:
10523 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010524 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10525 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10526 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10527 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010528 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10529 return false;
10530
10531 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010532 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Tice4f605582011-03-31 00:02:51 +000010533 single_regs = true;
10534 add = BitIsSet (opcode, 23);
10535 wback = BitIsSet (opcode, 21);
10536 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10537 n = Bits32 (opcode, 19, 16);
10538
Greg Clayton061b79d2011-05-09 20:18:18 +000010539 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Tice4f605582011-03-31 00:02:51 +000010540 imm32 = Bits32 (opcode, 7, 0) << 2;
10541 regs = Bits32 (opcode, 7, 0);
10542
10543 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10544 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10545 return false;
10546
10547 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10548 if ((regs == 0) || ((d + regs) > 32))
10549 return false;
10550 break;
10551
10552 default:
10553 return false;
10554 }
10555
Greg Claytonc07d4512011-04-26 23:48:45 +000010556 RegisterInfo base_reg;
10557 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4f605582011-03-31 00:02:51 +000010558
10559 uint32_t Rn = ReadCoreReg (n, &success);
10560 if (!success)
10561 return false;
10562
10563 // address = if add then R[n] else R[n]-imm32;
10564 addr_t address;
10565 if (add)
10566 address = Rn;
10567 else
10568 address = Rn - imm32;
10569
Greg Claytonc07d4512011-04-26 23:48:45 +000010570 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010571 EmulateInstruction::Context context;
10572
10573 if (wback)
10574 {
10575 uint32_t value;
10576 if (add)
10577 value = Rn + imm32;
10578 else
10579 value = Rn - imm32;
10580
10581 context.type = eContextAdjustBaseRegister;
10582 context.SetImmediateSigned (value - Rn);
10583 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10584 return false;
10585
10586 }
10587
10588 const uint32_t addr_byte_size = GetAddressByteSize();
10589 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10590
10591 context.type = eContextRegisterLoad;
10592
10593 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010594 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010595 {
10596 if (single_regs)
10597 {
10598 // S[d+r] = MemA[address,4]; address = address+4;
10599 context.SetRegisterPlusOffset (base_reg, address - Rn);
10600
10601 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10602 if (!success)
10603 return false;
10604
10605 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10606 return false;
10607
10608 address = address + 4;
10609 }
10610 else
10611 {
10612 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10613 context.SetRegisterPlusOffset (base_reg, address - Rn);
10614 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10615 if (!success)
10616 return false;
10617
10618 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10619 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10620 if (!success)
10621 return false;
10622
10623 address = address + 8;
10624 // // Combine the word-aligned words in the correct order for current endianness.
10625 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10626 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010627 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010628 {
10629 data = word1;
10630 data = (data << 32) | word2;
10631 }
10632 else
10633 {
10634 data = word2;
10635 data = (data << 32) | word1;
10636 }
10637
10638 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10639 return false;
10640 }
10641 }
10642 }
10643 return true;
10644}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010645
10646// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010647// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10648// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010649bool
10650EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10651{
10652#if 0
10653 if ConditionPassed() then
10654 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10655 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010656 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010657 for r = 0 to regs-1
10658 if single_regs then
10659 MemA[address,4] = S[d+r]; address = address+4;
10660 else
10661 // Store as two word-aligned words in the correct order for current endianness.
10662 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10663 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10664 address = address+8;
10665#endif
10666
10667 bool success = false;
10668
10669 if (ConditionPassed (opcode))
10670 {
10671 bool single_regs;
10672 bool add;
10673 bool wback;
10674 uint32_t d;
10675 uint32_t n;
10676 uint32_t imm32;
10677 uint32_t regs;
10678
10679 switch (encoding)
10680 {
10681 case eEncodingT1:
10682 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010683 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10684 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10685 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10686 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010687 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10688 return false;
10689
10690 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010691 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010692 single_regs = false;
10693 add = BitIsSet (opcode, 23);
10694 wback = BitIsSet (opcode, 21);
10695
Greg Clayton061b79d2011-05-09 20:18:18 +000010696 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010697 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10698 n = Bits32 (opcode, 19, 16);
10699 imm32 = Bits32 (opcode, 7, 0) << 2;
10700
Greg Clayton061b79d2011-05-09 20:18:18 +000010701 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010702 regs = Bits32 (opcode, 7, 0) / 2;
10703
10704 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10705 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10706 return false;
10707
10708 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10709 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10710 return false;
10711
10712 break;
10713
10714 case eEncodingT2:
10715 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010716 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10717 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10718 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10719 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010720 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10721 return false;
10722
10723 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010724 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010725 single_regs = true;
10726 add = BitIsSet (opcode, 23);
10727 wback = BitIsSet (opcode, 21);
10728 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10729 n = Bits32 (opcode, 19, 16);
10730
Greg Clayton061b79d2011-05-09 20:18:18 +000010731 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010732 imm32 = Bits32 (opcode, 7, 0) << 2;
10733 regs = Bits32 (opcode, 7, 0);
10734
10735 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10736 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10737 return false;
10738
10739 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10740 if ((regs == 0) || ((d + regs) > 32))
10741 return false;
10742
10743 break;
10744
10745 default:
10746 return false;
10747 }
10748
Greg Claytonc07d4512011-04-26 23:48:45 +000010749 RegisterInfo base_reg;
10750 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010751
10752 uint32_t Rn = ReadCoreReg (n, &success);
10753 if (!success)
10754 return false;
10755
10756 // address = if add then R[n] else R[n]-imm32;
10757 addr_t address;
10758 if (add)
10759 address = Rn;
10760 else
10761 address = Rn - imm32;
10762
10763 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +000010764 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010765 if (wback)
10766 {
10767 uint32_t value;
10768 if (add)
10769 value = Rn + imm32;
10770 else
10771 value = Rn - imm32;
10772
10773 context.type = eContextAdjustBaseRegister;
10774 context.SetRegisterPlusOffset (base_reg, value - Rn);
10775
10776 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10777 return false;
10778 }
10779
10780 const uint32_t addr_byte_size = GetAddressByteSize();
10781 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10782
10783 context.type = eContextRegisterStore;
10784 // for r = 0 to regs-1
10785 for (int r = 0; r < regs; ++r)
10786 {
Greg Claytonc07d4512011-04-26 23:48:45 +000010787
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010788 if (single_regs)
10789 {
10790 // MemA[address,4] = S[d+r]; address = address+4;
10791 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10792 if (!success)
10793 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010794
10795 RegisterInfo data_reg;
10796 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010797 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10798 if (!MemAWrite (context, address, data, addr_byte_size))
10799 return false;
10800
10801 address = address + 4;
10802 }
10803 else
10804 {
10805 // // Store as two word-aligned words in the correct order for current endianness.
10806 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10807 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10808 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10809 if (!success)
10810 return false;
10811
Greg Claytonc07d4512011-04-26 23:48:45 +000010812 RegisterInfo data_reg;
10813 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010814
Greg Clayton888a7332011-04-26 04:39:08 +000010815 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010816 {
10817 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10818 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10819 return false;
10820
10821 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10822 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10823 return false;
10824 }
10825 else
10826 {
10827 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10828 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10829 return false;
10830
10831 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10832 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10833 return false;
10834 }
10835 // address = address+8;
10836 address = address + 8;
10837 }
10838 }
10839 }
10840 return true;
10841}
10842
Caroline Tice917ad352011-03-31 05:05:30 +000010843// A8.6.320
10844// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10845// an optional offset.
10846bool
10847EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10848{
10849#if 0
10850 if ConditionPassed() then
10851 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10852 base = if n == 15 then Align(PC,4) else R[n];
10853 address = if add then (base + imm32) else (base - imm32);
10854 if single_reg then
10855 S[d] = MemA[address,4];
10856 else
10857 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10858 // Combine the word-aligned words in the correct order for current endianness.
10859 D[d] = if BigEndian() then word1:word2 else word2:word1;
10860#endif
10861
10862 bool success = false;
10863
10864 if (ConditionPassed (opcode))
10865 {
10866 bool single_reg;
10867 bool add;
10868 uint32_t imm32;
10869 uint32_t d;
10870 uint32_t n;
10871
10872 switch (encoding)
10873 {
10874 case eEncodingT1:
10875 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010876 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010877 single_reg = false;
10878 add = BitIsSet (opcode, 23);
10879 imm32 = Bits32 (opcode, 7, 0) << 2;
10880
10881 // d = UInt(D:Vd); n = UInt(Rn);
10882 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10883 n = Bits32 (opcode, 19, 16);
10884
10885 break;
10886
10887 case eEncodingT2:
10888 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010889 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010890 single_reg = true;
10891 add = BitIsSet (opcode, 23);
10892 imm32 = Bits32 (opcode, 7, 0) << 2;
10893
10894 // d = UInt(Vd:D); n = UInt(Rn);
10895 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10896 n = Bits32 (opcode, 19, 16);
10897
10898 break;
10899
10900 default:
10901 return false;
10902 }
Greg Claytonc07d4512011-04-26 23:48:45 +000010903 RegisterInfo base_reg;
10904 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice917ad352011-03-31 05:05:30 +000010905
10906 uint32_t Rn = ReadCoreReg (n, &success);
10907 if (!success)
10908 return false;
10909
10910 // base = if n == 15 then Align(PC,4) else R[n];
10911 uint32_t base;
10912 if (n == 15)
10913 base = AlignPC (Rn);
10914 else
10915 base = Rn;
10916
10917 // address = if add then (base + imm32) else (base - imm32);
10918 addr_t address;
10919 if (add)
10920 address = base + imm32;
10921 else
10922 address = base - imm32;
10923
10924 const uint32_t addr_byte_size = GetAddressByteSize();
10925 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
10926
10927 EmulateInstruction::Context context;
10928 context.type = eContextRegisterLoad;
10929 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010930
Caroline Tice917ad352011-03-31 05:05:30 +000010931 if (single_reg)
10932 {
10933 // S[d] = MemA[address,4];
10934 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10935 if (!success)
10936 return false;
10937
10938 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
10939 return false;
10940 }
10941 else
10942 {
10943 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
10944 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10945 if (!success)
10946 return false;
10947
10948 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
10949 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10950 if (!success)
10951 return false;
10952 // // Combine the word-aligned words in the correct order for current endianness.
10953 // D[d] = if BigEndian() then word1:word2 else word2:word1;
10954 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000010955 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000010956 {
10957 data64 = word1;
10958 data64 = (data64 << 32) | word2;
10959 }
10960 else
10961 {
10962 data64 = word2;
10963 data64 = (data64 << 32) | word1;
10964 }
10965
10966 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
10967 return false;
10968 }
10969 }
10970 return true;
10971}
Caroline Tice424652f2011-03-31 05:38:36 +000010972
10973// A8.6.400 VSTR
10974// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
10975// optional offset.
10976bool
10977EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
10978{
10979#if 0
10980 if ConditionPassed() then
10981 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10982 address = if add then (R[n] + imm32) else (R[n] - imm32);
10983 if single_reg then
10984 MemA[address,4] = S[d];
10985 else
10986 // Store as two word-aligned words in the correct order for current endianness.
10987 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
10988 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
10989#endif
10990
10991 bool success = false;
10992
10993 if (ConditionPassed (opcode))
10994 {
10995 bool single_reg;
10996 bool add;
10997 uint32_t imm32;
10998 uint32_t d;
10999 uint32_t n;
11000
11001 switch (encoding)
11002 {
11003 case eEncodingT1:
11004 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011005 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011006 single_reg = false;
11007 add = BitIsSet (opcode, 23);
11008 imm32 = Bits32 (opcode, 7, 0) << 2;
11009
11010 // d = UInt(D:Vd); n = UInt(Rn);
11011 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11012 n = Bits32 (opcode, 19, 16);
11013
11014 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11015 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11016 return false;
11017
11018 break;
11019
11020 case eEncodingT2:
11021 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011022 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011023 single_reg = true;
11024 add = BitIsSet (opcode, 23);
11025 imm32 = Bits32 (opcode, 7, 0) << 2;
11026
11027 // d = UInt(Vd:D); n = UInt(Rn);
11028 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11029 n = Bits32 (opcode, 19, 16);
11030
11031 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11032 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11033 return false;
11034
11035 break;
11036
11037 default:
11038 return false;
11039 }
11040
Greg Claytonc07d4512011-04-26 23:48:45 +000011041 RegisterInfo base_reg;
11042 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011043
11044 uint32_t Rn = ReadCoreReg (n, &success);
11045 if (!success)
11046 return false;
11047
11048 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11049 addr_t address;
11050 if (add)
11051 address = Rn + imm32;
11052 else
11053 address = Rn - imm32;
11054
11055 const uint32_t addr_byte_size = GetAddressByteSize();
11056 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11057
Greg Claytonc07d4512011-04-26 23:48:45 +000011058 RegisterInfo data_reg;
11059 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011060 EmulateInstruction::Context context;
11061 context.type = eContextRegisterStore;
11062 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11063
11064 if (single_reg)
11065 {
11066 // MemA[address,4] = S[d];
11067 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11068 if (!success)
11069 return false;
11070
11071 if (!MemAWrite (context, address, data, addr_byte_size))
11072 return false;
11073 }
11074 else
11075 {
11076 // // Store as two word-aligned words in the correct order for current endianness.
11077 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11078 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11079 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11080 if (!success)
11081 return false;
11082
Greg Clayton888a7332011-04-26 04:39:08 +000011083 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011084 {
11085 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11086 return false;
11087
11088 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11089 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11090 return false;
11091 }
11092 else
11093 {
11094 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11095 return false;
11096
11097 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11098 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11099 return false;
11100 }
11101 }
11102 }
11103 return true;
11104}
Caroline Tice9121b352011-03-31 16:41:19 +000011105
11106// A8.6.307 VLDI1 (multiple single elements)
11107// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11108// element of each register is loaded.
11109bool
11110EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11111{
11112#if 0
11113 if ConditionPassed() then
11114 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11115 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11116 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11117 for r = 0 to regs-1
11118 for e = 0 to elements-1
11119 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11120 address = address + ebytes;
11121#endif
11122
11123 bool success = false;
11124
11125 if (ConditionPassed (opcode))
11126 {
11127 uint32_t regs;
11128 uint32_t alignment;
11129 uint32_t ebytes;
11130 uint32_t esize;
11131 uint32_t elements;
11132 uint32_t d;
11133 uint32_t n;
11134 uint32_t m;
11135 bool wback;
11136 bool register_index;
11137
11138 switch (encoding)
11139 {
11140 case eEncodingT1:
11141 case eEncodingA1:
11142 {
11143 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011144 // when Ô0111Õ
11145 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
11146 // when Ô1010Õ
11147 // regs = 2; if align == Ô11Õ then UNDEFINED;
11148 // when Ô0110Õ
11149 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
11150 // when Ô0010Õ
Caroline Tice9121b352011-03-31 16:41:19 +000011151 // regs = 4;
11152 // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011153 // SEE ÒRelated encodingsÓ;
Caroline Tice9121b352011-03-31 16:41:19 +000011154 uint32_t type = Bits32 (opcode, 11, 8);
11155 uint32_t align = Bits32 (opcode, 5, 4);
11156 if (type == 7) // '0111'
11157 {
11158 regs = 1;
11159 if (BitIsSet (align, 1))
11160 return false;
11161 }
11162 else if (type == 10) // '1010'
11163 {
11164 regs = 2;
11165 if (align == 3)
11166 return false;
11167
11168 }
11169 else if (type == 6) // '0110'
11170 {
11171 regs = 3;
11172 if (BitIsSet (align, 1))
11173 return false;
11174 }
11175 else if (type == 2) // '0010'
11176 {
11177 regs = 4;
11178 }
11179 else
11180 return false;
11181
Greg Clayton061b79d2011-05-09 20:18:18 +000011182 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice9121b352011-03-31 16:41:19 +000011183 if (align == 0)
11184 alignment = 1;
11185 else
11186 alignment = 4 << align;
11187
11188 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11189 ebytes = 1 << Bits32 (opcode, 7, 6);
11190 esize = 8 * ebytes;
11191 elements = 8 / ebytes;
11192
11193 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11194 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11195 n = Bits32 (opcode, 19, 15);
11196 m = Bits32 (opcode, 3, 0);
11197
11198 // wback = (m != 15); register_index = (m != 15 && m != 13);
11199 wback = (m != 15);
11200 register_index = ((m != 15) && (m != 13));
11201
11202 // if d+regs > 32 then UNPREDICTABLE;
11203 if ((d + regs) > 32)
11204 return false;
11205 }
11206 break;
11207
11208 default:
11209 return false;
11210 }
11211
Greg Claytonc07d4512011-04-26 23:48:45 +000011212 RegisterInfo base_reg;
11213 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice9121b352011-03-31 16:41:19 +000011214
11215 uint32_t Rn = ReadCoreReg (n, &success);
11216 if (!success)
11217 return false;
11218
11219 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11220 addr_t address = Rn;
11221 if ((address % alignment) != 0)
11222 return false;
11223
11224 EmulateInstruction::Context context;
11225 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11226 if (wback)
11227 {
11228 uint32_t Rm = ReadCoreReg (m, &success);
11229 if (!success)
11230 return false;
11231
11232 uint32_t offset;
11233 if (register_index)
11234 offset = Rm;
11235 else
11236 offset = 8 * regs;
11237
11238 uint32_t value = Rn + offset;
11239 context.type = eContextAdjustBaseRegister;
11240 context.SetRegisterPlusOffset (base_reg, offset);
11241
11242 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11243 return false;
11244
11245 }
11246
11247 // for r = 0 to regs-1
11248 for (int r = 0; r < regs; ++r)
11249 {
11250 // for e = 0 to elements-1
11251 uint64_t assembled_data = 0;
11252 for (int e = 0; e < elements; ++e)
11253 {
11254 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11255 context.type = eContextRegisterLoad;
11256 context.SetRegisterPlusOffset (base_reg, address - Rn);
11257 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11258 if (!success)
11259 return false;
11260
11261 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11262
11263 // address = address + ebytes;
11264 address = address + ebytes;
11265 }
11266 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11267 return false;
11268 }
11269 }
11270 return true;
11271}
11272
Caroline Ticeb6281b12011-03-31 17:58:23 +000011273// A8.6.308 VLD1 (single element to one lane)
11274//
11275bool
11276EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11277{
11278#if 0
11279 if ConditionPassed() then
11280 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11281 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11282 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11283 Elem[D[d],index,esize] = MemU[address,ebytes];
11284#endif
11285
11286 bool success = false;
11287
11288 if (ConditionPassed (opcode))
11289 {
11290 uint32_t ebytes;
11291 uint32_t esize;
11292 uint32_t index;
11293 uint32_t alignment;
11294 uint32_t d;
11295 uint32_t n;
11296 uint32_t m;
11297 bool wback;
11298 bool register_index;
11299
11300 switch (encoding)
11301 {
11302 case eEncodingT1:
11303 case eEncodingA1:
11304 {
11305 uint32_t size = Bits32 (opcode, 11, 10);
11306 uint32_t index_align = Bits32 (opcode, 7, 4);
Greg Clayton061b79d2011-05-09 20:18:18 +000011307 // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011308 if (size == 3)
11309 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011310 // case size of
11311 if (size == 0) // when '00'
11312 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011313 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011314 if (BitIsClear (index_align, 0))
11315 return false;
11316
11317 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11318 ebytes = 1;
11319 esize = 8;
11320 index = Bits32 (index_align, 3, 1);
11321 alignment = 1;
11322 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011323 else if (size == 1) // when Ô01Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011324 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011325 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011326 if (BitIsClear (index_align, 1))
11327 return false;
11328
11329 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11330 ebytes = 2;
11331 esize = 16;
11332 index = Bits32 (index_align, 3, 2);
11333
Greg Clayton061b79d2011-05-09 20:18:18 +000011334 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011335 if (BitIsClear (index_align, 0))
11336 alignment = 1;
11337 else
11338 alignment = 2;
11339 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011340 else if (size == 2) // when Ô10Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011341 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011342 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011343 if (BitIsClear (index_align, 2))
11344 return false;
11345
Greg Clayton061b79d2011-05-09 20:18:18 +000011346 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011347 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11348 return false;
11349
11350 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11351 ebytes = 4;
11352 esize = 32;
11353 index = Bit32 (index_align, 3);
11354
Greg Clayton061b79d2011-05-09 20:18:18 +000011355 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011356 if (Bits32 (index_align, 1, 0) == 0)
11357 alignment = 1;
11358 else
11359 alignment = 4;
11360 }
11361 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11362 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11363 n = Bits32 (opcode, 19, 16);
11364 m = Bits32 (opcode, 3, 0);
11365
11366 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11367 wback = (m != 15);
11368 register_index = ((m != 15) && (m != 13));
11369
11370 if (n == 15)
11371 return false;
11372
11373 }
11374 break;
11375
11376 default:
11377 return false;
11378 }
11379
Greg Claytonc07d4512011-04-26 23:48:45 +000011380 RegisterInfo base_reg;
11381 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011382
11383 uint32_t Rn = ReadCoreReg (n, &success);
11384 if (!success)
11385 return false;
11386
11387 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11388 addr_t address = Rn;
11389 if ((address % alignment) != 0)
11390 return false;
11391
11392 EmulateInstruction::Context context;
11393 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11394 if (wback)
11395 {
11396 uint32_t Rm = ReadCoreReg (m, &success);
11397 if (!success)
11398 return false;
11399
11400 uint32_t offset;
11401 if (register_index)
11402 offset = Rm;
11403 else
11404 offset = ebytes;
11405
11406 uint32_t value = Rn + offset;
11407
11408 context.type = eContextAdjustBaseRegister;
11409 context.SetRegisterPlusOffset (base_reg, offset);
11410
11411 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11412 return false;
11413 }
11414
11415 // Elem[D[d],index,esize] = MemU[address,ebytes];
11416 uint32_t element = MemURead (context, address, esize, 0, &success);
11417 if (!success)
11418 return false;
11419
11420 element = element << (index * esize);
11421
11422 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11423 if (!success)
11424 return false;
11425
11426 uint64_t all_ones = -1;
11427 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11428 // at element & to the right of element.
11429 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011430 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 +000011431 // now mask should be 0's where element goes & 1's
11432 // everywhere else.
11433
11434 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11435 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11436
11437 context.type = eContextRegisterLoad;
11438 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11439 return false;
11440 }
11441 return true;
11442}
11443
Caroline Tice1e542e32011-03-31 18:44:04 +000011444// A8.6.391 VST1 (multiple single elements)
11445// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11446// interleaving. Every element of each register is stored.
11447bool
11448EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11449{
11450#if 0
11451 if ConditionPassed() then
11452 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11453 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11454 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11455 for r = 0 to regs-1
11456 for e = 0 to elements-1
11457 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11458 address = address + ebytes;
11459#endif
11460
11461 bool success = false;
11462
11463 if (ConditionPassed (opcode))
11464 {
11465 uint32_t regs;
11466 uint32_t alignment;
11467 uint32_t ebytes;
11468 uint32_t esize;
11469 uint32_t elements;
11470 uint32_t d;
11471 uint32_t n;
11472 uint32_t m;
11473 bool wback;
11474 bool register_index;
11475
11476 switch (encoding)
11477 {
11478 case eEncodingT1:
11479 case eEncodingA1:
11480 {
11481 uint32_t type = Bits32 (opcode, 11, 8);
11482 uint32_t align = Bits32 (opcode, 5, 4);
11483
11484 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011485 if (type == 7) // when Ô0111Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011486 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011487 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011488 regs = 1;
11489 if (BitIsSet (align, 1))
11490 return false;
11491 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011492 else if (type == 10) // when Ô1010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011493 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011494 // regs = 2; if align == Ô11Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011495 regs = 2;
11496 if (align == 3)
11497 return false;
11498 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011499 else if (type == 6) // when Ô0110Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011500 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011501 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011502 regs = 3;
11503 if (BitIsSet (align, 1))
11504 return false;
11505 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011506 else if (type == 2) // when Ô0010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011507 // regs = 4;
11508 regs = 4;
11509 else // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011510 // SEE ÒRelated encodingsÓ;
Caroline Tice1e542e32011-03-31 18:44:04 +000011511 return false;
11512
Greg Clayton061b79d2011-05-09 20:18:18 +000011513 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice1e542e32011-03-31 18:44:04 +000011514 if (align == 0)
11515 alignment = 0;
11516 else
11517 alignment = 4 << align;
11518
11519 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11520 ebytes = 1 << Bits32 (opcode,7, 6);
11521 esize = 8 * ebytes;
11522 elements = 8 / ebytes;
11523
11524 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11525 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11526 n = Bits32 (opcode, 19, 16);
11527 m = Bits32 (opcode, 3, 0);
11528
11529 // wback = (m != 15); register_index = (m != 15 && m != 13);
11530 wback = (m != 15);
11531 register_index = ((m != 15) && (m != 13));
11532
11533 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11534 if ((d + regs) > 32)
11535 return false;
11536
11537 if (n == 15)
11538 return false;
11539
11540 }
11541 break;
11542
11543 default:
11544 return false;
11545 }
11546
Greg Claytonc07d4512011-04-26 23:48:45 +000011547 RegisterInfo base_reg;
11548 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011549
11550 uint32_t Rn = ReadCoreReg (n, &success);
11551 if (!success)
11552 return false;
11553
11554 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11555 addr_t address = Rn;
11556 if ((address % alignment) != 0)
11557 return false;
11558
11559 EmulateInstruction::Context context;
11560 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11561 if (wback)
11562 {
11563 uint32_t Rm = ReadCoreReg (m, &success);
11564 if (!success)
11565 return false;
11566
11567 uint32_t offset;
11568 if (register_index)
11569 offset = Rm;
11570 else
11571 offset = 8 * regs;
11572
11573 context.type = eContextAdjustBaseRegister;
11574 context.SetRegisterPlusOffset (base_reg, offset);
11575
11576 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11577 return false;
11578 }
11579
Greg Claytonc07d4512011-04-26 23:48:45 +000011580 RegisterInfo data_reg;
Caroline Tice1e542e32011-03-31 18:44:04 +000011581 context.type = eContextRegisterStore;
Caroline Tice1e542e32011-03-31 18:44:04 +000011582 // for r = 0 to regs-1
11583 for (int r = 0; r < regs; ++r)
11584 {
Greg Claytonc07d4512011-04-26 23:48:45 +000011585 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011586 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11587 if (!success)
11588 return false;
11589
11590 // for e = 0 to elements-1
11591 for (int e = 0; e < elements; ++e)
11592 {
11593 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011594 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011595
11596 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11597 if (!MemUWrite (context, address, word, ebytes))
11598 return false;
11599
11600 // address = address + ebytes;
11601 address = address + ebytes;
11602 }
11603 }
11604 }
11605 return true;
11606}
11607
Caroline Tice7b880942011-03-31 19:17:12 +000011608// A8.6.392 VST1 (single element from one lane)
11609// This instruction stores one element to memory from one element of a register.
11610bool
11611EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11612{
11613#if 0
11614 if ConditionPassed() then
11615 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11616 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11617 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11618 MemU[address,ebytes] = Elem[D[d],index,esize];
11619#endif
11620
11621 bool success = false;
11622
11623 if (ConditionPassed (opcode))
11624 {
11625 uint32_t ebytes;
11626 uint32_t esize;
11627 uint32_t index;
11628 uint32_t alignment;
11629 uint32_t d;
11630 uint32_t n;
11631 uint32_t m;
11632 bool wback;
11633 bool register_index;
11634
11635 switch (encoding)
11636 {
11637 case eEncodingT1:
11638 case eEncodingA1:
11639 {
11640 uint32_t size = Bits32 (opcode, 11, 10);
11641 uint32_t index_align = Bits32 (opcode, 7, 4);
11642
Greg Clayton061b79d2011-05-09 20:18:18 +000011643 // if size == Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011644 if (size == 3)
11645 return false;
11646
11647 // case size of
Greg Clayton061b79d2011-05-09 20:18:18 +000011648 if (size == 0) // when Ô00Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011649 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011650 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011651 if (BitIsClear (index_align, 0))
11652 return false;
11653 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11654 ebytes = 1;
11655 esize = 8;
11656 index = Bits32 (index_align, 3, 1);
11657 alignment = 1;
11658 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011659 else if (size == 1) // when Ô01Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011660 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011661 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011662 if (BitIsClear (index_align, 1))
11663 return false;
11664
11665 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11666 ebytes = 2;
11667 esize = 16;
11668 index = Bits32 (index_align, 3, 2);
11669
Greg Clayton061b79d2011-05-09 20:18:18 +000011670 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Tice7b880942011-03-31 19:17:12 +000011671 if (BitIsClear (index_align, 0))
11672 alignment = 1;
11673 else
11674 alignment = 2;
11675 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011676 else if (size == 2) // when Ô10Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011677 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011678 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011679 if (BitIsClear (index_align, 2))
11680 return false;
11681
Greg Clayton061b79d2011-05-09 20:18:18 +000011682 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011683 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11684 return false;
11685
11686 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11687 ebytes = 4;
11688 esize = 32;
11689 index = Bit32 (index_align, 3);
11690
Greg Clayton061b79d2011-05-09 20:18:18 +000011691 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Tice7b880942011-03-31 19:17:12 +000011692 if (Bits32 (index_align, 1, 0) == 0)
11693 alignment = 1;
11694 else
11695 alignment = 4;
11696 }
11697 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11698 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11699 n = Bits32 (opcode, 19, 16);
11700 m = Bits32 (opcode, 3, 0);
11701
11702 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11703 wback = (m != 15);
11704 register_index = ((m != 15) && (m != 13));
11705
11706 if (n == 15)
11707 return false;
11708 }
11709 break;
11710
11711 default:
11712 return false;
11713 }
11714
Greg Claytonc07d4512011-04-26 23:48:45 +000011715 RegisterInfo base_reg;
11716 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011717
11718 uint32_t Rn = ReadCoreReg (n, &success);
11719 if (!success)
11720 return false;
11721
11722 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11723 addr_t address = Rn;
11724 if ((address % alignment) != 0)
11725 return false;
11726
11727 EmulateInstruction::Context context;
11728 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11729 if (wback)
11730 {
11731 uint32_t Rm = ReadCoreReg (m, &success);
11732 if (!success)
11733 return false;
11734
11735 uint32_t offset;
11736 if (register_index)
11737 offset = Rm;
11738 else
11739 offset = ebytes;
11740
11741 context.type = eContextAdjustBaseRegister;
11742 context.SetRegisterPlusOffset (base_reg, offset);
11743
11744 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11745 return false;
11746 }
11747
11748 // MemU[address,ebytes] = Elem[D[d],index,esize];
11749 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11750 if (!success)
11751 return false;
11752
11753 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11754
Greg Claytonc07d4512011-04-26 23:48:45 +000011755 RegisterInfo data_reg;
11756 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011757 context.type = eContextRegisterStore;
11758 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11759
11760 if (!MemUWrite (context, address, word, ebytes))
11761 return false;
11762 }
11763 return true;
11764}
11765
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011766// A8.6.309 VLD1 (single element to all lanes)
11767// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011768bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011769EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011770{
11771#if 0
11772 if ConditionPassed() then
11773 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11774 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11775 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11776 replicated_element = Replicate(MemU[address,ebytes], elements);
11777 for r = 0 to regs-1
11778 D[d+r] = replicated_element;
11779#endif
11780
11781 bool success = false;
11782
11783 if (ConditionPassed (opcode))
11784 {
11785 uint32_t ebytes;
11786 uint32_t elements;
11787 uint32_t regs;
11788 uint32_t alignment;
11789 uint32_t d;
11790 uint32_t n;
11791 uint32_t m;
11792 bool wback;
11793 bool register_index;
11794
11795 switch (encoding)
11796 {
11797 case eEncodingT1:
11798 case eEncodingA1:
11799 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011800 //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
Caroline Tice93767b82011-03-31 21:15:29 +000011801 uint32_t size = Bits32 (opcode, 7, 6);
11802 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11803 return false;
11804
Greg Clayton061b79d2011-05-09 20:18:18 +000011805 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
Caroline Tice93767b82011-03-31 21:15:29 +000011806 ebytes = 1 << size;
11807 elements = 8 / ebytes;
11808 if (BitIsClear (opcode, 5))
11809 regs = 1;
11810 else
11811 regs = 2;
11812
Greg Clayton061b79d2011-05-09 20:18:18 +000011813 //alignment = if a == Ô0Õ then 1 else ebytes;
Caroline Tice93767b82011-03-31 21:15:29 +000011814 if (BitIsClear (opcode, 4))
11815 alignment = 1;
11816 else
11817 alignment = ebytes;
11818
11819 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11820 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11821 n = Bits32 (opcode, 19, 16);
11822 m = Bits32 (opcode, 3, 0);
11823
11824 //wback = (m != 15); register_index = (m != 15 && m != 13);
11825 wback = (m != 15);
11826 register_index = ((m != 15) && (m != 13));
11827
11828 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11829 if ((d + regs) > 32)
11830 return false;
11831
11832 if (n == 15)
11833 return false;
11834 }
11835 break;
11836
11837 default:
11838 break;
11839 }
11840
Greg Claytonc07d4512011-04-26 23:48:45 +000011841 RegisterInfo base_reg;
11842 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice93767b82011-03-31 21:15:29 +000011843
11844 uint32_t Rn = ReadCoreReg (n, &success);
11845 if (!success)
11846 return false;
11847
11848 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11849 addr_t address = Rn;
11850 if ((address % alignment) != 0)
11851 return false;
11852
11853 EmulateInstruction::Context context;
11854 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11855 if (wback)
11856 {
11857 uint32_t Rm = ReadCoreReg (m, &success);
11858 if (!success)
11859 return false;
11860
11861 uint32_t offset;
11862 if (register_index)
11863 offset = Rm;
11864 else
11865 offset = ebytes;
11866
11867 context.type = eContextAdjustBaseRegister;
11868 context.SetRegisterPlusOffset (base_reg, offset);
11869
11870 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11871 return false;
11872 }
11873
11874 // replicated_element = Replicate(MemU[address,ebytes], elements);
11875
11876 context.type = eContextRegisterLoad;
11877 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11878 if (!success)
11879 return false;
11880
11881 uint64_t replicated_element;
11882 uint32_t esize = ebytes * 8;
11883 for (int e = 0; e < elements; ++e)
11884 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11885
11886 // for r = 0 to regs-1
11887 for (int r = 0; r < regs; ++r)
11888 {
11889 // D[d+r] = replicated_element;
11890 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11891 return false;
11892 }
11893 }
11894 return true;
11895}
11896
Caroline Tice1f954f52011-04-11 15:51:10 +000011897// B6.2.13 SUBS PC, LR and related instructions
11898//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
11899// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
11900bool
11901EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
11902{
11903#if 0
11904 if ConditionPassed() then
11905 EncodingSpecificOperations();
11906 if CurrentInstrSet() == InstrSet_ThumbEE then
11907 UNPREDICTABLE;
11908 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11909 case opcode of
Greg Clayton061b79d2011-05-09 20:18:18 +000011910 when Ô0000Õ result = R[n] AND operand2; // AND
11911 when Ô0001Õ result = R[n] EOR operand2; // EOR
11912 when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
11913 when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
11914 when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
11915 when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
11916 when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
11917 when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
11918 when Ô1100Õ result = R[n] OR operand2; // ORR
11919 when Ô1101Õ result = operand2; // MOV
11920 when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
11921 when Ô1111Õ result = NOT(operand2); // MVN
11922 CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000011923 BranchWritePC(result);
11924#endif
11925
11926 bool success = false;
11927
11928 if (ConditionPassed (opcode))
11929 {
11930 uint32_t n;
11931 uint32_t m;
11932 uint32_t imm32;
11933 bool register_form;
11934 ARM_ShifterType shift_t;
11935 uint32_t shift_n;
11936 uint32_t code;
11937
11938 switch (encoding)
11939 {
11940 case eEncodingT1:
11941 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
Greg Clayton061b79d2011-05-09 20:18:18 +000011942 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000011943 n = 14;
11944 imm32 = Bits32 (opcode, 7, 0);
11945 register_form = false;
11946 code = 2;
11947
11948 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
11949 if (InITBlock() && !LastInITBlock())
11950 return false;
11951
11952 break;
11953
11954 case eEncodingA1:
11955 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
11956 n = Bits32 (opcode, 19, 16);
11957 imm32 = ARMExpandImm (opcode);
11958 register_form = false;
11959 code = Bits32 (opcode, 24, 21);
11960
11961 break;
11962
11963 case eEncodingA2:
11964 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
11965 n = Bits32 (opcode, 19, 16);
11966 m = Bits32 (opcode, 3, 0);
11967 register_form = true;
11968
11969 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
11970 shift_n = DecodeImmShiftARM (opcode, shift_t);
11971
11972 break;
11973
11974 default:
11975 return false;
11976 }
11977
11978 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11979 uint32_t operand2;
11980 if (register_form)
11981 {
11982 uint32_t Rm = ReadCoreReg (m, &success);
11983 if (!success)
11984 return false;
11985
11986 operand2 = Shift (Rm, shift_t, shift_n, APSR_C);
11987
11988 }
11989 else
11990 {
11991 operand2 = imm32;
11992 }
11993
11994 uint32_t Rn = ReadCoreReg (n, &success);
11995 if (!success)
11996 return false;
11997
11998 AddWithCarryResult result;
11999
12000 // case opcode of
12001 switch (code)
12002 {
Greg Clayton061b79d2011-05-09 20:18:18 +000012003 case 0: // when Ô0000Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012004 // result = R[n] AND operand2; // AND
12005 result.result = Rn & operand2;
12006 break;
12007
Greg Clayton061b79d2011-05-09 20:18:18 +000012008 case 1: // when Ô0001Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012009 // result = R[n] EOR operand2; // EOR
12010 result.result = Rn ^ operand2;
12011 break;
12012
Greg Clayton061b79d2011-05-09 20:18:18 +000012013 case 2: // when Ô0010Õ
12014 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012015 result = AddWithCarry (Rn, ~(operand2), 1);
12016 break;
12017
Greg Clayton061b79d2011-05-09 20:18:18 +000012018 case 3: // when Ô0011Õ
12019 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
Caroline Tice1f954f52011-04-11 15:51:10 +000012020 result = AddWithCarry (~(Rn), operand2, 1);
12021 break;
12022
Greg Clayton061b79d2011-05-09 20:18:18 +000012023 case 4: // when Ô0100Õ
12024 // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
Caroline Tice1f954f52011-04-11 15:51:10 +000012025 result = AddWithCarry (Rn, operand2, 0);
12026 break;
12027
Greg Clayton061b79d2011-05-09 20:18:18 +000012028 case 5: // when Ô0101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012029 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12030 result = AddWithCarry (Rn, operand2, APSR_C);
12031 break;
12032
Greg Clayton061b79d2011-05-09 20:18:18 +000012033 case 6: // when Ô0110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012034 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12035 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12036 break;
12037
Greg Clayton061b79d2011-05-09 20:18:18 +000012038 case 7: // when Ô0111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012039 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12040 result = AddWithCarry (~(Rn), operand2, APSR_C);
12041 break;
12042
Greg Clayton061b79d2011-05-09 20:18:18 +000012043 case 10: // when Ô1100Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012044 // result = R[n] OR operand2; // ORR
12045 result.result = Rn | operand2;
12046 break;
12047
Greg Clayton061b79d2011-05-09 20:18:18 +000012048 case 11: // when Ô1101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012049 // result = operand2; // MOV
12050 result.result = operand2;
12051 break;
12052
Greg Clayton061b79d2011-05-09 20:18:18 +000012053 case 12: // when Ô1110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012054 // result = R[n] AND NOT(operand2); // BIC
12055 result.result = Rn & ~(operand2);
12056 break;
12057
Greg Clayton061b79d2011-05-09 20:18:18 +000012058 case 15: // when Ô1111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012059 // result = NOT(operand2); // MVN
12060 result.result = ~(operand2);
12061 break;
12062
12063 default:
12064 return false;
12065 }
Greg Clayton061b79d2011-05-09 20:18:18 +000012066 // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012067
12068 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12069 // the best.
12070 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12071 if (!success)
12072 return false;
12073
12074 CPSRWriteByInstr (spsr, 15, true);
12075
12076 // BranchWritePC(result);
12077 EmulateInstruction::Context context;
12078 context.type = eContextAdjustPC;
12079 context.SetImmediate (result.result);
12080
12081 BranchWritePC (context, result.result);
12082 }
12083 return true;
12084}
12085
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012086EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012087EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012088{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012089 static ARMOpcode
12090 g_arm_opcodes[] =
12091 {
12092 //----------------------------------------------------------------------
12093 // Prologue instructions
12094 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012095
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012096 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012097 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12098 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012099
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012100 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012101 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12102 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012103 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012104 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12105 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12106 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012107
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012108 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012109 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12110 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012111
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012112 // push one register
12113 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012114 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012115
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012116 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012117 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12118 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012119
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012120 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012121 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012122 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012123
Caroline Tice4f605582011-03-31 00:02:51 +000012124 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12125 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12126 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12127 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012128
12129 //----------------------------------------------------------------------
12130 // Supervisor Call (previously Software Interrupt)
12131 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012132 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012133
12134 //----------------------------------------------------------------------
12135 // Branch instructions
12136 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012137 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012138 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012139 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12140 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12141 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012142 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012143 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012144 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012145 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012146
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012147 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012148 // Data-processing instructions
12149 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012150 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012151 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012152 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012153 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012154 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012155 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012156 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012157 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012158 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012159 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012160 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012161 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12162 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012163 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012164 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012165 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012166 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012167 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012168 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012169 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012170 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012171 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012172 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012173 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012174 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012175 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012176 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012177 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012178 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012179 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012180 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012181 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012182 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012183 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012184 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012185 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012186 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012187 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012188 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012189 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012190 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012191 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012192 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012193 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012194 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012195 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012196 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012197 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012198 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012199 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012200 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012201 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012202 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012203 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012204 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012205
Caroline Tice89c6d582011-03-29 19:53:44 +000012206 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012207 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12208 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012209 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012210 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012211 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012212 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012213 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012214 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012215 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012216 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012217 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012218 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012219 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012220 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012221 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012222 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012223 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012224 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012225 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012226 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012227 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012228 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012229 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012230 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012231 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012232 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012233 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012234 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012235 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012236 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012237 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012238 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012239 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012240 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012241 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012242 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012243
12244 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012245 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12246 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012247
12248 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012249 // Load instructions
12250 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012251 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12252 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12253 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12254 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12255 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12256 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12257 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12258 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12259 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12260 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12261 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12262 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12263 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12264 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12265 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12266 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12267 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12268 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012269 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12270 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12271 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12272 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012273 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12274 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012275 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012276
12277 //----------------------------------------------------------------------
12278 // Store instructions
12279 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012280 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12281 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12282 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12283 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12284 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12285 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12286 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12287 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12288 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012289 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012290 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012291 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12292 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12293 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12294 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12295 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012296 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012297
Caroline Tice6bf65162011-03-03 17:42:58 +000012298 //----------------------------------------------------------------------
12299 // Other instructions
12300 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012301 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12302 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12303 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12304 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12305 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012306
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012307 };
12308 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12309
12310 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12311 {
Greg Clayton888a7332011-04-26 04:39:08 +000012312 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12313 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012314 return &g_arm_opcodes[i];
12315 }
12316 return NULL;
12317}
Greg Clayton64c84432011-01-21 22:02:52 +000012318
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012319
12320EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012321EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012322{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012323
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012324 static ARMOpcode
12325 g_thumb_opcodes[] =
12326 {
12327 //----------------------------------------------------------------------
12328 // Prologue instructions
12329 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012330
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012331 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012332 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12333 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12334 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012335
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012336 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012337 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012338 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012339 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012340 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012341 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012342
Johnny Chen864a8e82011-02-18 00:07:39 +000012343 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012344 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012345
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012346 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012347 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12348 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12349 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12350 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12351 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012352
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012353 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012354 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12355 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012356
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012357 //----------------------------------------------------------------------
12358 // Epilogue instructions
12359 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012360
Caroline Tice4f605582011-03-31 00:02:51 +000012361 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12362 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12363 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12364 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12365 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12366 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12367 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012368
12369 //----------------------------------------------------------------------
12370 // Supervisor Call (previously Software Interrupt)
12371 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012372 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012373
12374 //----------------------------------------------------------------------
12375 // If Then makes up to four following instructions conditional.
12376 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012377 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012378
12379 //----------------------------------------------------------------------
12380 // Branch instructions
12381 //----------------------------------------------------------------------
12382 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012383 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12384 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12385 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12386 { 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 +000012387 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012388 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012389 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012390 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12391 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012392 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012393 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012394 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012395 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012396 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012397 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012398 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012399 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012400 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012401 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012402
12403 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012404 // Data-processing instructions
12405 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012406 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012407 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012408 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012409 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12410 { 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 +000012411 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012412 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012413 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012414 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012415 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012416 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12417 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12418 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012419 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012420 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012421 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012422 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12423 { 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 +000012424 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012425 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012426 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012427 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12428 { 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 +000012429 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012430 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012431 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012432 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12433 { 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 +000012434 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012435 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012436 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012437 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12438 { 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 +000012439 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012440 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12441 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012442 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012443 { 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 +000012444 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012445 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012446 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012447 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12448 { 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 +000012449 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012450 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12451 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12452 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12453 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012454 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012455 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12456 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12457 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12458 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012459 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012460 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12461 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012462 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012463 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12464 { 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 +000012465 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012466 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012467 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012468 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012469 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012470 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012471 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012472 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12473 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012474
Johnny Chen7c5234d2011-02-18 23:41:11 +000012475
Johnny Chen338bf542011-02-10 19:29:03 +000012476 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012477 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012478 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012479 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012480 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012481 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012482 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012483 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12484 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12485 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012486 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012487 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012488 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012489 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12490 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012491 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012492 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012493 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012494 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12495 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012496 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012497 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12498 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012499 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012500 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012501 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012502 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012503 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012504 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12505 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012506 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012507 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12508 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012509 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012510 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12511 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012512 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012513 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12514 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012515 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012516 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12517 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012518 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012519 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12520 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012521 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012522 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012523 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012524 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012525 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012526 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12527 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012528 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012529 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012530 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012531 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012532
12533 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012534 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012535
12536 //----------------------------------------------------------------------
12537 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12538 // otherwise the wrong instructions will be selected.
12539 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012540
Caroline Tice080bf612011-04-05 18:46:00 +000012541 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12542 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12543
Johnny Chen26863dc2011-02-09 23:43:29 +000012544 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012545 // Load instructions
12546 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012547 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12548 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12549 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12550 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12551 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12552 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12553 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012554 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012555 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12556 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12557 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12558 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12559 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012560 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012561 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12562 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12563 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12564 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12565 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12566 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12567 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12568 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12569 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12570 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12571 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12572 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12573 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12574 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12575 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12576 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12577 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12578 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12579 { 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 +000012580 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012581 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12582 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12583 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12584 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012585 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12586 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012587 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012588
12589 //----------------------------------------------------------------------
12590 // Store instructions
12591 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012592 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12593 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12594 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12595 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12596 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12597 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12598 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12599 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12600 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12601 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12602 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12603 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12604 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12605 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12606 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12607 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012608 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12609 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12610 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12611 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12612 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012613 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012614
12615 //----------------------------------------------------------------------
12616 // Other instructions
12617 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012618 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12619 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12620 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12621 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12622 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12623 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12624 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12625 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012626 };
12627
12628 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12629 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12630 {
Greg Clayton888a7332011-04-26 04:39:08 +000012631 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12632 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012633 return &g_thumb_opcodes[i];
12634 }
12635 return NULL;
12636}
Greg Clayton64c84432011-01-21 22:02:52 +000012637
Greg Clayton31e2a382011-01-30 20:03:56 +000012638bool
Greg Clayton395fc332011-02-15 21:59:32 +000012639EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012640{
Caroline Tice080bf612011-04-05 18:46:00 +000012641 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012642 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012643 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012644 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012645 {
Greg Clayton395fc332011-02-15 21:59:32 +000012646 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12647 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12648 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12649 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12650 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12651 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12652 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12653 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12654 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12655 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Johnny Chen1d29a852011-04-26 18:51:57 +000012656 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12657 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
Greg Clayton31e2a382011-01-30 20:03:56 +000012658 }
12659 return m_arm_isa != 0;
12660}
12661
Caroline Tice080bf612011-04-05 18:46:00 +000012662bool
Greg Clayton888a7332011-04-26 04:39:08 +000012663EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012664{
Greg Clayton888a7332011-04-26 04:39:08 +000012665 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12666 {
12667 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12668 m_opcode_mode = eModeThumb;
12669 else
12670 {
12671 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012672
Greg Clayton888a7332011-04-26 04:39:08 +000012673 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12674 m_opcode_mode = eModeARM;
12675 else if (addr_class == eAddressClassCodeAlternateISA)
12676 m_opcode_mode = eModeThumb;
12677 else
12678 return false;
12679 }
12680 if (m_opcode_mode == eModeThumb)
12681 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12682 else
12683 m_opcode_cpsr = CPSR_MODE_USR;
12684 return true;
12685 }
12686 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012687}
Greg Clayton31e2a382011-01-30 20:03:56 +000012688
Greg Clayton64c84432011-01-21 22:02:52 +000012689bool
12690EmulateInstructionARM::ReadInstruction ()
12691{
12692 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012693 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012694 if (success)
12695 {
12696 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12697 if (success)
12698 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012699 Context read_inst_context;
12700 read_inst_context.type = eContextReadOpcode;
12701 read_inst_context.SetNoArgs ();
12702
Greg Claytonb3448432011-03-24 21:19:54 +000012703 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012704 {
Greg Claytonb3448432011-03-24 21:19:54 +000012705 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012706 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012707
12708 if (success)
12709 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012710 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012711 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012712 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012713 }
12714 else
12715 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012716 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012717 }
12718 }
12719 }
12720 else
12721 {
Greg Claytonb3448432011-03-24 21:19:54 +000012722 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012723 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012724 }
12725 }
12726 }
12727 if (!success)
12728 {
Greg Claytonb3448432011-03-24 21:19:54 +000012729 m_opcode_mode = eModeInvalid;
Greg Clayton3063c952011-04-29 22:50:31 +000012730 m_addr = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012731 }
12732 return success;
12733}
12734
Johnny Chenee9b1f72011-02-09 01:00:31 +000012735uint32_t
12736EmulateInstructionARM::ArchVersion ()
12737{
12738 return m_arm_isa;
12739}
12740
Greg Clayton64c84432011-01-21 22:02:52 +000012741bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012742EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012743{
Greg Clayton888a7332011-04-26 04:39:08 +000012744 // If we are ignoring conditions, then always return true.
12745 // this allows us to iterate over disassembly code and still
12746 // emulate an instruction even if we don't have all the right
12747 // bits set in the CPSR register...
12748 if (m_ignore_conditions)
12749 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000012750
Greg Clayton7bc39082011-03-24 23:53:38 +000012751 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012752
12753 if (cond == UINT32_MAX)
12754 return false;
12755
12756 bool result = false;
12757 switch (UnsignedBits(cond, 3, 1))
12758 {
Caroline Tice080bf612011-04-05 18:46:00 +000012759 case 0:
12760 if (m_opcode_cpsr == 0)
12761 return true;
12762 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12763 break;
12764 case 1:
12765 if (m_opcode_cpsr == 0)
12766 return true;
12767 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12768 break;
12769 case 2:
12770 if (m_opcode_cpsr == 0)
12771 return true;
12772 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12773 break;
12774 case 3:
12775 if (m_opcode_cpsr == 0)
12776 return true;
12777 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12778 break;
12779 case 4:
12780 if (m_opcode_cpsr == 0)
12781 return true;
12782 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12783 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012784 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012785 if (m_opcode_cpsr == 0)
12786 return true;
12787 else
12788 {
Greg Claytonb3448432011-03-24 21:19:54 +000012789 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12790 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012791 result = n == v;
12792 }
12793 break;
12794 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012795 if (m_opcode_cpsr == 0)
12796 return true;
12797 else
12798 {
Greg Claytonb3448432011-03-24 21:19:54 +000012799 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12800 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12801 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012802 }
12803 break;
12804 case 7:
12805 result = true;
12806 break;
12807 }
12808
12809 if (cond & 1)
12810 result = !result;
12811 return result;
12812}
12813
Johnny Chen9ee056b2011-02-08 00:06:35 +000012814uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012815EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012816{
Greg Claytonb3448432011-03-24 21:19:54 +000012817 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012818 {
12819 default:
12820 case eModeInvalid:
12821 break;
12822
12823 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012824 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012825
12826 case eModeThumb:
12827 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12828 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012829 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012830 const uint32_t byte_size = m_opcode.GetByteSize();
12831 if (byte_size == 2)
12832 {
12833 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12834 return Bits32(opcode, 11, 7);
12835 }
12836 else
12837 {
12838 assert (byte_size == 4);
12839 if (Bits32(opcode, 31, 27) == 0x1e &&
12840 Bits32(opcode, 15, 14) == 0x02 &&
12841 Bits32(opcode, 12, 12) == 0x00 &&
12842 Bits32(opcode, 25, 22) <= 0x0d)
12843 {
12844 return Bits32(opcode, 25, 22);
12845 }
12846 }
12847
12848 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012849 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012850 }
12851 return UINT32_MAX; // Return invalid value
12852}
12853
Johnny Chen9ee056b2011-02-08 00:06:35 +000012854bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012855EmulateInstructionARM::InITBlock()
12856{
12857 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12858}
12859
12860bool
12861EmulateInstructionARM::LastInITBlock()
12862{
12863 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12864}
12865
Caroline Ticeb27771d2011-03-03 22:37:46 +000012866bool
12867EmulateInstructionARM::BadMode (uint32_t mode)
12868{
12869
12870 switch (mode)
12871 {
12872 case 16: return false; // '10000'
12873 case 17: return false; // '10001'
12874 case 18: return false; // '10010'
12875 case 19: return false; // '10011'
12876 case 22: return false; // '10110'
12877 case 23: return false; // '10111'
12878 case 27: return false; // '11011'
12879 case 31: return false; // '11111'
12880 default: return true;
12881 }
12882 return true;
12883}
12884
12885bool
12886EmulateInstructionARM::CurrentModeIsPrivileged ()
12887{
Greg Claytonb3448432011-03-24 21:19:54 +000012888 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012889
12890 if (BadMode (mode))
12891 return false;
12892
12893 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000012894 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012895
12896 return true;
12897}
12898
12899void
12900EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
12901{
12902 bool privileged = CurrentModeIsPrivileged();
12903
12904 uint32_t tmp_cpsr = 0;
12905
Greg Claytonb3448432011-03-24 21:19:54 +000012906 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012907
12908 if (BitIsSet (bytemask, 3))
12909 {
12910 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
12911 if (affect_execstate)
12912 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
12913 }
12914
12915 if (BitIsSet (bytemask, 2))
12916 {
12917 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
12918 }
12919
12920 if (BitIsSet (bytemask, 1))
12921 {
12922 if (affect_execstate)
12923 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
12924 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
12925 if (privileged)
12926 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
12927 }
12928
12929 if (BitIsSet (bytemask, 0))
12930 {
12931 if (privileged)
12932 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
12933 if (affect_execstate)
12934 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
12935 if (privileged)
12936 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
12937 }
12938
Greg Claytonb3448432011-03-24 21:19:54 +000012939 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012940}
12941
12942
Johnny Chen098ae2d2011-02-12 00:50:05 +000012943bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000012944EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
12945{
12946 addr_t target;
12947
Johnny Chenee9b1f72011-02-09 01:00:31 +000012948 // Check the current instruction set.
12949 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012950 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012951 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000012952 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012953
Johnny Chen9ee056b2011-02-08 00:06:35 +000012954 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012955 return false;
12956
12957 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012958}
12959
12960// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
12961bool
Johnny Chen668b4512011-02-15 21:08:58 +000012962EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012963{
12964 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000012965 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
12966 // we want to record it and issue a WriteRegister callback so the clients
12967 // can track the mode changes accordingly.
12968 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012969
12970 if (BitIsSet(addr, 0))
12971 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012972 if (CurrentInstrSet() != eModeThumb)
12973 {
12974 SelectInstrSet(eModeThumb);
12975 cpsr_changed = true;
12976 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012977 target = addr & 0xfffffffe;
Greg Claytonc07d4512011-04-26 23:48:45 +000012978 context.SetISA (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012979 }
12980 else if (BitIsClear(addr, 1))
12981 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012982 if (CurrentInstrSet() != eModeARM)
12983 {
12984 SelectInstrSet(eModeARM);
12985 cpsr_changed = true;
12986 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012987 target = addr & 0xfffffffc;
Greg Claytonc07d4512011-04-26 23:48:45 +000012988 context.SetISA (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012989 }
12990 else
12991 return false; // address<1:0> == '10' => UNPREDICTABLE
12992
Johnny Chen0f309db2011-02-09 19:11:32 +000012993 if (cpsr_changed)
12994 {
Johnny Chen558133b2011-02-09 23:59:17 +000012995 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000012996 return false;
12997 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012998 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012999 return false;
13000
13001 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013002}
Greg Clayton64c84432011-01-21 22:02:52 +000013003
Johnny Chenee9b1f72011-02-09 01:00:31 +000013004// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13005bool
Johnny Chen668b4512011-02-15 21:08:58 +000013006EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000013007{
13008 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000013009 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000013010 else
13011 return BranchWritePC((const Context)context, addr);
13012}
13013
Johnny Chen26863dc2011-02-09 23:43:29 +000013014// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13015bool
Johnny Chen668b4512011-02-15 21:08:58 +000013016EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000013017{
13018 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013019 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013020 else
13021 return BranchWritePC((const Context)context, addr);
13022}
13023
Johnny Chenee9b1f72011-02-09 01:00:31 +000013024EmulateInstructionARM::Mode
13025EmulateInstructionARM::CurrentInstrSet ()
13026{
Greg Claytonb3448432011-03-24 21:19:54 +000013027 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013028}
13029
Greg Claytonb3448432011-03-24 21:19:54 +000013030// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013031// ReadInstruction() is performed. This function has a side effect of updating
13032// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013033bool
13034EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13035{
Greg Claytonb3448432011-03-24 21:19:54 +000013036 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013037 switch (arm_or_thumb)
13038 {
13039 default:
13040 return false;
13041 eModeARM:
13042 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013043 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013044 break;
13045 eModeThumb:
13046 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013047 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013048 break;
13049 }
13050 return true;
13051}
13052
Johnny Chenef21b592011-02-10 01:52:38 +000013053// This function returns TRUE if the processor currently provides support for
13054// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13055// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13056bool
13057EmulateInstructionARM::UnalignedSupport()
13058{
13059 return (ArchVersion() >= ARMv7);
13060}
13061
Johnny Chenbf6ad172011-02-11 01:29:53 +000013062// The main addition and subtraction instructions can produce status information
13063// about both unsigned carry and signed overflow conditions. This status
13064// information can be used to synthesize multi-word additions and subtractions.
13065EmulateInstructionARM::AddWithCarryResult
13066EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13067{
13068 uint32_t result;
13069 uint8_t carry_out;
13070 uint8_t overflow;
13071
13072 uint64_t unsigned_sum = x + y + carry_in;
13073 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13074
13075 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013076// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013077 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013078
13079 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013080 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013081 else
13082 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013083
13084 AddWithCarryResult res = { result, carry_out, overflow };
13085 return res;
13086}
13087
Johnny Chen157b9592011-02-18 21:13:05 +000013088uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013089EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013090{
Johnny Chene39f22d2011-02-19 01:36:13 +000013091 uint32_t reg_kind, reg_num;
13092 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013093 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013094 case SP_REG:
13095 reg_kind = eRegisterKindGeneric;
13096 reg_num = LLDB_REGNUM_GENERIC_SP;
13097 break;
13098 case LR_REG:
13099 reg_kind = eRegisterKindGeneric;
13100 reg_num = LLDB_REGNUM_GENERIC_RA;
13101 break;
13102 case PC_REG:
13103 reg_kind = eRegisterKindGeneric;
13104 reg_num = LLDB_REGNUM_GENERIC_PC;
13105 break;
13106 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013107 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013108 {
13109 reg_kind = eRegisterKindDWARF;
13110 reg_num = dwarf_r0 + num;
13111 }
Johnny Chen157b9592011-02-18 21:13:05 +000013112 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013113 {
13114 assert(0 && "Invalid register number");
13115 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013116 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013117 }
13118 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013119 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013120
13121 // Read our register.
13122 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13123
13124 // When executing an ARM instruction , PC reads as the address of the current
13125 // instruction plus 8.
13126 // When executing a Thumb instruction , PC reads as the address of the current
13127 // instruction plus 4.
13128 if (num == 15)
13129 {
13130 if (CurrentInstrSet() == eModeARM)
13131 val += 8;
13132 else
13133 val += 4;
13134 }
Johnny Chen157b9592011-02-18 21:13:05 +000013135
13136 return val;
13137}
13138
Johnny Chenca67d1c2011-02-17 01:35:27 +000013139// Write the result to the ARM core register Rd, and optionally update the
13140// condition flags based on the result.
13141//
13142// This helper method tries to encapsulate the following pseudocode from the
13143// ARM Architecture Reference Manual:
13144//
13145// if d == 15 then // Can only occur for encoding A1
13146// ALUWritePC(result); // setflags is always FALSE here
13147// else
13148// R[d] = result;
13149// if setflags then
13150// APSR.N = result<31>;
13151// APSR.Z = IsZeroBit(result);
13152// APSR.C = carry;
13153// // APSR.V unchanged
13154//
13155// In the above case, the API client does not pass in the overflow arg, which
13156// defaults to ~0u.
13157bool
Johnny Chen10530c22011-02-17 22:37:12 +000013158EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13159 const uint32_t result,
13160 const uint32_t Rd,
13161 bool setflags,
13162 const uint32_t carry,
13163 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013164{
13165 if (Rd == 15)
13166 {
13167 if (!ALUWritePC (context, result))
13168 return false;
13169 }
13170 else
13171 {
Johnny Chena695f952011-02-23 21:24:25 +000013172 uint32_t reg_kind, reg_num;
13173 switch (Rd)
13174 {
13175 case SP_REG:
13176 reg_kind = eRegisterKindGeneric;
13177 reg_num = LLDB_REGNUM_GENERIC_SP;
13178 break;
13179 case LR_REG:
13180 reg_kind = eRegisterKindGeneric;
13181 reg_num = LLDB_REGNUM_GENERIC_RA;
13182 break;
13183 default:
13184 reg_kind = eRegisterKindDWARF;
13185 reg_num = dwarf_r0 + Rd;
13186 }
13187 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013188 return false;
13189 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013190 return WriteFlags (context, result, carry, overflow);
13191 }
13192 return true;
13193}
13194
13195// This helper method tries to encapsulate the following pseudocode from the
13196// ARM Architecture Reference Manual:
13197//
13198// APSR.N = result<31>;
13199// APSR.Z = IsZeroBit(result);
13200// APSR.C = carry;
13201// APSR.V = overflow
13202//
13203// Default arguments can be specified for carry and overflow parameters, which means
13204// not to update the respective flags.
13205bool
13206EmulateInstructionARM::WriteFlags (Context &context,
13207 const uint32_t result,
13208 const uint32_t carry,
13209 const uint32_t overflow)
13210{
Greg Claytonb3448432011-03-24 21:19:54 +000013211 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013212 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13213 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013214 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013215 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013216 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013217 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013218 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013219 {
13220 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13221 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013222 }
13223 return true;
13224}
13225
Greg Clayton64c84432011-01-21 22:02:52 +000013226bool
Greg Clayton888a7332011-04-26 04:39:08 +000013227EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013228{
Johnny Chenc315f862011-02-05 00:46:10 +000013229 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013230 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013231 m_it_session.ITAdvance();
13232
Greg Clayton888a7332011-04-26 04:39:08 +000013233 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013234
13235 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013236 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013237 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013238 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13239
13240 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013241 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013242
Greg Clayton888a7332011-04-26 04:39:08 +000013243 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13244 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013245
Greg Clayton888a7332011-04-26 04:39:08 +000013246 bool success = false;
13247 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013248 {
Greg Clayton888a7332011-04-26 04:39:08 +000013249 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
Greg Clayton061b79d2011-05-09 20:18:18 +000013250 dwarf_cpsr,
13251 0,
13252 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013253 }
13254
Greg Clayton888a7332011-04-26 04:39:08 +000013255 // Only return false if we are unable to read the CPSR if we care about conditions
13256 if (success == false && m_ignore_conditions == false)
13257 return false;
13258
13259 uint32_t orig_pc_value = 0;
13260 if (auto_advance_pc)
13261 {
13262 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13263 if (!success)
13264 return false;
13265 }
13266
13267 // Call the Emulate... function.
13268 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13269 if (!success)
13270 return false;
13271
13272 if (auto_advance_pc)
13273 {
13274 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13275 if (!success)
13276 return false;
13277
13278 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13279 {
13280 if (opcode_data->size == eSize32)
13281 after_pc_value += 4;
13282 else if (opcode_data->size == eSize16)
13283 after_pc_value += 2;
13284
13285 EmulateInstruction::Context context;
13286 context.type = eContextAdvancePC;
13287 context.SetNoArgs();
13288 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13289 return false;
13290
13291 }
13292 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013293 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013294}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013295
13296bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013297EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013298{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013299 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013300 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013301 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013302 return false;
13303 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013304
13305 static ConstString opcode_key ("opcode");
13306 static ConstString before_key ("before_state");
13307 static ConstString after_key ("after_state");
13308
13309 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013310
13311 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013312 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013313 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013314 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013315 return false;
13316 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013317 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013318
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013319 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13320 {
13321 m_opcode_mode = eModeARM;
13322 m_opcode.SetOpcode32 (test_opcode);
13323 }
13324 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13325 {
13326 m_opcode_mode = eModeThumb;
13327 if (test_opcode < 0x10000)
13328 m_opcode.SetOpcode16 (test_opcode);
13329 else
13330 m_opcode.SetOpcode32 (test_opcode);
13331
13332 }
13333 else
13334 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013335 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013336 return false;
13337 }
13338
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013339 EmulationStateARM before_state;
13340 EmulationStateARM after_state;
13341
Caroline Ticedfb2e202011-04-22 05:08:45 +000013342 value_sp = test_data->GetValueForKey (before_key);
13343 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013344 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013345 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013346 return false;
13347 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013348
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013349 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013350 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013351 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013352 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013353 return false;
13354 }
13355
Caroline Ticedfb2e202011-04-22 05:08:45 +000013356 value_sp = test_data->GetValueForKey (after_key);
13357 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013358 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013359 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013360 return false;
13361 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013362
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013363 state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013364 if (!after_state.LoadStateFromDictionary (state_dictionary))
13365 {
13366 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13367 return false;
13368 }
13369
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013370 SetBaton ((void *) &before_state);
13371 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13372 &EmulationStateARM::WritePseudoMemory,
13373 &EmulationStateARM::ReadPseudoRegister,
13374 &EmulationStateARM::WritePseudoRegister);
13375
Greg Clayton888a7332011-04-26 04:39:08 +000013376 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013377 if (!success)
13378 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013379 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013380 return false;
13381 }
13382
13383 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013384 if (!success)
13385 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13386
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013387 return success;
13388}
Greg Claytonc07d4512011-04-26 23:48:45 +000013389//
13390//
13391//const char *
13392//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13393//{
13394// if (reg_kind == eRegisterKindGeneric)
13395// {
13396// switch (reg_num)
13397// {
13398// case LLDB_REGNUM_GENERIC_PC: return "pc";
13399// case LLDB_REGNUM_GENERIC_SP: return "sp";
13400// case LLDB_REGNUM_GENERIC_FP: return "fp";
13401// case LLDB_REGNUM_GENERIC_RA: return "lr";
13402// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13403// default: return NULL;
13404// }
13405// }
13406// else if (reg_kind == eRegisterKindDWARF)
13407// {
13408// return GetARMDWARFRegisterName (reg_num);
13409// }
13410// return NULL;
13411//}
13412//
13413bool
13414EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
Greg Clayton888a7332011-04-26 04:39:08 +000013415{
Greg Clayton75906e42011-05-11 18:39:18 +000013416 unwind_plan.Clear();
Greg Claytonc07d4512011-04-26 23:48:45 +000013417 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13418
13419 UnwindPlan::Row row;
Greg Claytonc07d4512011-04-26 23:48:45 +000013420
13421 // Our previous Call Frame Address is the stack pointer
13422 row.SetCFARegister (dwarf_sp);
13423
13424 // Our previous PC is in the LR
Greg Clayton75906e42011-05-11 18:39:18 +000013425 row.SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
Greg Claytonc07d4512011-04-26 23:48:45 +000013426 unwind_plan.AppendRow (row);
13427
13428 // All other registers are the same.
13429
13430 unwind_plan.SetSourceName ("EmulateInstructionARM");
13431 return true;
Greg Clayton888a7332011-04-26 04:39:08 +000013432}
13433
Greg Claytonc07d4512011-04-26 23:48:45 +000013434
13435
13436