blob: ad6621dc8f5dbd4b9eee064b1492953379f42912 [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 Claytonc07d4512011-04-26 23:48:45 +0000504 RegisterInfo reg_info;
505 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
506 if (!WriteRegisterUnsigned(context, reg_info, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000507 return false;
508 addr += addr_byte_size;
509 }
510 }
511
Johnny Chen7c1bf922011-02-08 23:49:37 +0000512 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000513 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000514 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000515 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000516 if (!success)
517 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000518 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000519 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000520 return false;
521 addr += addr_byte_size;
522 }
523
524 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000525 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000526
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000527 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000528 return false;
529 }
530 return true;
531}
532
Johnny Chen5b442b72011-01-27 19:34:30 +0000533// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000534// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000535bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000536EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000537{
538#if 0
539 // ARM pseudo code...
540 if (ConditionPassed())
541 {
542 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000543 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000544 if d == 15 then
545 ALUWritePC(result); // setflags is always FALSE here
546 else
547 R[d] = result;
548 if setflags then
549 APSR.N = result<31>;
550 APSR.Z = IsZeroBit(result);
551 APSR.C = carry;
552 APSR.V = overflow;
553 }
554#endif
555
556 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000557
Greg Clayton7bc39082011-03-24 23:53:38 +0000558 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000559 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000560 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000561 if (!success)
562 return false;
563 uint32_t Rd; // the destination register
564 uint32_t imm32;
565 switch (encoding) {
566 case eEncodingT1:
567 Rd = 7;
568 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
569 break;
570 case eEncodingA1:
571 Rd = Bits32(opcode, 15, 12);
572 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
573 break;
574 default:
575 return false;
576 }
577 addr_t sp_offset = imm32;
578 addr_t addr = sp + sp_offset; // a pointer to the stack area
579
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000580 EmulateInstruction::Context context;
Caroline Tice080bf612011-04-05 18:46:00 +0000581 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +0000582 RegisterInfo sp_reg;
583 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000584 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000585
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000586 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000587 return false;
588 }
589 return true;
590}
591
Johnny Chen2ccad832011-01-28 19:57:25 +0000592// Set r7 or ip to the current stack pointer.
593// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000594bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000595EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000596{
597#if 0
598 // ARM pseudo code...
599 if (ConditionPassed())
600 {
601 EncodingSpecificOperations();
602 result = R[m];
603 if d == 15 then
604 ALUWritePC(result); // setflags is always FALSE here
605 else
606 R[d] = result;
607 if setflags then
608 APSR.N = result<31>;
609 APSR.Z = IsZeroBit(result);
610 // APSR.C unchanged
611 // APSR.V unchanged
612 }
613#endif
614
615 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000616
Greg Clayton7bc39082011-03-24 23:53:38 +0000617 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000618 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000619 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000620 if (!success)
621 return false;
622 uint32_t Rd; // the destination register
623 switch (encoding) {
624 case eEncodingT1:
625 Rd = 7;
626 break;
627 case eEncodingA1:
628 Rd = 12;
629 break;
630 default:
631 return false;
632 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000633
634 EmulateInstruction::Context context;
635 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +0000636 RegisterInfo sp_reg;
637 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000638 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000639
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000640 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000641 return false;
642 }
643 return true;
644}
645
Johnny Chen1c13b622011-01-29 00:11:15 +0000646// Move from high register (r8-r15) to low register (r0-r7).
647// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000648bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000649EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000650{
Greg Clayton7bc39082011-03-24 23:53:38 +0000651 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000652}
653
654// Move from register to register.
655// MOV (register)
656bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000657EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000658{
Johnny Chen1c13b622011-01-29 00:11:15 +0000659#if 0
660 // ARM pseudo code...
661 if (ConditionPassed())
662 {
663 EncodingSpecificOperations();
664 result = R[m];
665 if d == 15 then
666 ALUWritePC(result); // setflags is always FALSE here
667 else
668 R[d] = result;
669 if setflags then
670 APSR.N = result<31>;
671 APSR.Z = IsZeroBit(result);
672 // APSR.C unchanged
673 // APSR.V unchanged
674 }
675#endif
676
677 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000678
Greg Clayton7bc39082011-03-24 23:53:38 +0000679 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000680 {
681 uint32_t Rm; // the source register
682 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000683 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000684 switch (encoding) {
685 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000686 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000687 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000688 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000689 if (Rd == 15 && InITBlock() && !LastInITBlock())
690 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000691 break;
692 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000693 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000694 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000695 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000696 if (InITBlock())
697 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000698 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000699 case eEncodingT3:
700 Rd = Bits32(opcode, 11, 8);
701 Rm = Bits32(opcode, 3, 0);
702 setflags = BitIsSet(opcode, 20);
703 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
704 if (setflags && (BadReg(Rd) || BadReg(Rm)))
705 return false;
706 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
707 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
708 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000709 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000710 case eEncodingA1:
711 Rd = Bits32(opcode, 15, 12);
712 Rm = Bits32(opcode, 3, 0);
713 setflags = BitIsSet(opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +0000714
Johnny Chen01d61572011-02-25 00:23:25 +0000715 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000716 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000717 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000718 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000719 default:
720 return false;
721 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000722 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000723 if (!success)
724 return false;
725
726 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000727 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000728 context.type = EmulateInstruction::eContextRegisterLoad;
Greg Claytonc07d4512011-04-26 23:48:45 +0000729 RegisterInfo dwarf_reg;
730 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000731 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000732
Johnny Chen10530c22011-02-17 22:37:12 +0000733 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000734 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000735 }
736 return true;
737}
738
Johnny Chen357c30f2011-02-14 22:04:25 +0000739// Move (immediate) writes an immediate value to the destination register. It
740// can optionally update the condition flags based on the value.
741// MOV (immediate)
742bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000743EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000744{
745#if 0
746 // ARM pseudo code...
747 if (ConditionPassed())
748 {
749 EncodingSpecificOperations();
750 result = imm32;
751 if d == 15 then // Can only occur for ARM encoding
752 ALUWritePC(result); // setflags is always FALSE here
753 else
754 R[d] = result;
755 if setflags then
756 APSR.N = result<31>;
757 APSR.Z = IsZeroBit(result);
758 APSR.C = carry;
759 // APSR.V unchanged
760 }
761#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000762
Greg Clayton7bc39082011-03-24 23:53:38 +0000763 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000764 {
765 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000766 uint32_t imm32; // the immediate value to be written to Rd
767 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
768 bool setflags;
769 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000770 case eEncodingT1:
771 Rd = Bits32(opcode, 10, 8);
772 setflags = !InITBlock();
773 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
774 carry = APSR_C;
775
776 break;
777
778 case eEncodingT2:
779 Rd = Bits32(opcode, 11, 8);
780 setflags = BitIsSet(opcode, 20);
781 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
782 if (BadReg(Rd))
783 return false;
784
785 break;
786
787 case eEncodingT3:
788 {
789 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
790 Rd = Bits32 (opcode, 11, 8);
791 setflags = false;
792 uint32_t imm4 = Bits32 (opcode, 19, 16);
793 uint32_t imm3 = Bits32 (opcode, 14, 12);
794 uint32_t i = Bit32 (opcode, 26);
795 uint32_t imm8 = Bits32 (opcode, 7, 0);
796 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
797
798 // if BadReg(d) then UNPREDICTABLE;
799 if (BadReg (Rd))
800 return false;
801 }
802 break;
803
804 case eEncodingA1:
Caroline Tice89c6d582011-03-29 19:53:44 +0000805 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
806 Rd = Bits32 (opcode, 15, 12);
807 setflags = BitIsSet (opcode, 20);
808 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000809
810 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
811 if ((Rd == 15) && setflags)
812 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000813
814 break;
815
816 case eEncodingA2:
817 {
818 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
819 Rd = Bits32 (opcode, 15, 12);
820 setflags = false;
821 uint32_t imm4 = Bits32 (opcode, 19, 16);
822 uint32_t imm12 = Bits32 (opcode, 11, 0);
823 imm32 = (imm4 << 12) | imm12;
824
825 // if d == 15 then UNPREDICTABLE;
826 if (Rd == 15)
827 return false;
828 }
829 break;
830
831 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000832 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000833 }
834 uint32_t result = imm32;
835
836 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000837 EmulateInstruction::Context context;
838 context.type = EmulateInstruction::eContextImmediate;
839 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000840
Johnny Chen10530c22011-02-17 22:37:12 +0000841 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000842 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000843 }
844 return true;
845}
846
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000847// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
848// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
849// unsigned values.
850//
851// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
852// limited to only a few forms of the instruction.
853bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000854EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000855{
856#if 0
857 if ConditionPassed() then
858 EncodingSpecificOperations();
859 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
860 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
861 result = operand1 * operand2;
862 R[d] = result<31:0>;
863 if setflags then
864 APSR.N = result<31>;
865 APSR.Z = IsZeroBit(result);
866 if ArchVersion() == 4 then
867 APSR.C = bit UNKNOWN;
868 // else APSR.C unchanged
869 // APSR.V always unchanged
870#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000871
Greg Clayton7bc39082011-03-24 23:53:38 +0000872 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000873 {
874 uint32_t d;
875 uint32_t n;
876 uint32_t m;
877 bool setflags;
878
879 // EncodingSpecificOperations();
880 switch (encoding)
881 {
882 case eEncodingT1:
883 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
884 d = Bits32 (opcode, 2, 0);
885 n = Bits32 (opcode, 5, 3);
886 m = Bits32 (opcode, 2, 0);
887 setflags = !InITBlock();
888
889 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
890 if ((ArchVersion() < ARMv6) && (d == n))
891 return false;
892
893 break;
894
895 case eEncodingT2:
896 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
897 d = Bits32 (opcode, 11, 8);
898 n = Bits32 (opcode, 19, 16);
899 m = Bits32 (opcode, 3, 0);
900 setflags = false;
901
902 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
903 if (BadReg (d) || BadReg (n) || BadReg (m))
904 return false;
905
906 break;
907
908 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000909 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000910 d = Bits32 (opcode, 19, 16);
911 n = Bits32 (opcode, 3, 0);
912 m = Bits32 (opcode, 11, 8);
913 setflags = BitIsSet (opcode, 20);
914
915 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
916 if ((d == 15) || (n == 15) || (m == 15))
917 return false;
918
919 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
920 if ((ArchVersion() < ARMv6) && (d == n))
921 return false;
922
923 break;
924
925 default:
926 return false;
927 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000928
929 bool success = false;
930
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000931 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
932 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
933 if (!success)
934 return false;
935
936 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
937 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
938 if (!success)
939 return false;
940
941 // result = operand1 * operand2;
942 uint64_t result = operand1 * operand2;
943
944 // R[d] = result<31:0>;
Greg Claytonc07d4512011-04-26 23:48:45 +0000945 RegisterInfo op1_reg;
946 RegisterInfo op2_reg;
947 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
948 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000949
950 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +0000951 context.type = eContextArithmetic;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000952 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
953
954 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
955 return false;
956
957 // if setflags then
958 if (setflags)
959 {
960 // APSR.N = result<31>;
961 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000962 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000963 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
964 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000965 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000966 {
967 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
968 return false;
969 }
970
971 // if ArchVersion() == 4 then
972 // APSR.C = bit UNKNOWN;
973 }
974 }
975 return true;
976}
977
Johnny Chend642a6a2011-02-22 01:01:03 +0000978// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
979// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000980bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000981EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000982{
983#if 0
984 // ARM pseudo code...
985 if (ConditionPassed())
986 {
987 EncodingSpecificOperations();
988 result = NOT(imm32);
989 if d == 15 then // Can only occur for ARM encoding
990 ALUWritePC(result); // setflags is always FALSE here
991 else
992 R[d] = result;
993 if setflags then
994 APSR.N = result<31>;
995 APSR.Z = IsZeroBit(result);
996 APSR.C = carry;
997 // APSR.V unchanged
998 }
999#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001000
Greg Clayton7bc39082011-03-24 23:53:38 +00001001 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001002 {
1003 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +00001004 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1005 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001006 bool setflags;
1007 switch (encoding) {
1008 case eEncodingT1:
1009 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001010 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001011 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001012 break;
1013 case eEncodingA1:
1014 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001015 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001016 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +00001017
Johnny Chend642a6a2011-02-22 01:01:03 +00001018 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +00001019 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001020 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001021 break;
1022 default:
1023 return false;
1024 }
1025 uint32_t result = ~imm32;
1026
1027 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001028 EmulateInstruction::Context context;
1029 context.type = EmulateInstruction::eContextImmediate;
1030 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001031
Johnny Chen10530c22011-02-17 22:37:12 +00001032 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001033 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001034 }
1035 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001036}
1037
Johnny Chend642a6a2011-02-22 01:01:03 +00001038// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1039// It can optionally update the condition flags based on the result.
1040bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001041EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001042{
1043#if 0
1044 // ARM pseudo code...
1045 if (ConditionPassed())
1046 {
1047 EncodingSpecificOperations();
1048 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1049 result = NOT(shifted);
1050 if d == 15 then // Can only occur for ARM encoding
1051 ALUWritePC(result); // setflags is always FALSE here
1052 else
1053 R[d] = result;
1054 if setflags then
1055 APSR.N = result<31>;
1056 APSR.Z = IsZeroBit(result);
1057 APSR.C = carry;
1058 // APSR.V unchanged
1059 }
1060#endif
1061
Greg Clayton7bc39082011-03-24 23:53:38 +00001062 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001063 {
1064 uint32_t Rm; // the source register
1065 uint32_t Rd; // the destination register
1066 ARM_ShifterType shift_t;
1067 uint32_t shift_n; // the shift applied to the value read from Rm
1068 bool setflags;
1069 uint32_t carry; // the carry bit after the shift operation
1070 switch (encoding) {
1071 case eEncodingT1:
1072 Rd = Bits32(opcode, 2, 0);
1073 Rm = Bits32(opcode, 5, 3);
1074 setflags = !InITBlock();
1075 shift_t = SRType_LSL;
1076 shift_n = 0;
1077 if (InITBlock())
1078 return false;
1079 break;
1080 case eEncodingT2:
1081 Rd = Bits32(opcode, 11, 8);
1082 Rm = Bits32(opcode, 3, 0);
1083 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001084 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001085 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001086 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001087 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001088 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001089 case eEncodingA1:
1090 Rd = Bits32(opcode, 15, 12);
1091 Rm = Bits32(opcode, 3, 0);
1092 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001093 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001094 break;
1095 default:
1096 return false;
1097 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001098 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001099 uint32_t value = ReadCoreReg(Rm, &success);
1100 if (!success)
1101 return false;
1102
1103 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1104 uint32_t result = ~shifted;
1105
1106 // The context specifies that an immediate is to be moved into Rd.
1107 EmulateInstruction::Context context;
1108 context.type = EmulateInstruction::eContextImmediate;
1109 context.SetNoArgs ();
1110
1111 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1112 return false;
1113 }
1114 return true;
1115}
1116
Johnny Chen788e0552011-01-27 22:52:23 +00001117// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1118// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001119bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001120EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001121{
1122#if 0
1123 // ARM pseudo code...
1124 if (ConditionPassed())
1125 {
1126 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1127 base = Align(PC,4);
1128 address = if add then (base + imm32) else (base - imm32);
1129 data = MemU[address,4];
1130 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001131 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1132 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001133 R[t] = data;
1134 else // Can only apply before ARMv7
1135 if CurrentInstrSet() == InstrSet_ARM then
1136 R[t] = ROR(data, 8*UInt(address<1:0>));
1137 else
1138 R[t] = bits(32) UNKNOWN;
1139 }
1140#endif
1141
Greg Clayton7bc39082011-03-24 23:53:38 +00001142 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001143 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001144 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001145 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001146 if (!success)
1147 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001148
1149 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001150 EmulateInstruction::Context context;
1151 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001152 RegisterInfo pc_reg;
1153 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001154 context.SetRegisterPlusOffset (pc_reg, 0);
1155
Johnny Chenc9de9102011-02-11 19:12:30 +00001156 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001157 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001158 bool add; // +imm32 or -imm32?
1159 addr_t base; // the base address
1160 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001161 uint32_t data; // the literal data value from the PC relative load
1162 switch (encoding) {
1163 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001164 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001165 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001166 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001167 break;
1168 case eEncodingT2:
1169 Rt = Bits32(opcode, 15, 12);
1170 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1171 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001172 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001173 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001174 break;
1175 default:
1176 return false;
1177 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001178
Johnny Chene39f22d2011-02-19 01:36:13 +00001179 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001180 if (add)
1181 address = base + imm32;
1182 else
1183 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001184
1185 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001186 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001187 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001188 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001189
1190 if (Rt == 15)
1191 {
1192 if (Bits32(address, 1, 0) == 0)
1193 {
1194 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001195 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001196 return false;
1197 }
1198 else
1199 return false;
1200 }
1201 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1202 {
1203 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1204 return false;
1205 }
1206 else // We don't handle ARM for now.
1207 return false;
1208
Johnny Chen788e0552011-01-27 22:52:23 +00001209 }
1210 return true;
1211}
1212
Johnny Chen5b442b72011-01-27 19:34:30 +00001213// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001214// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001215bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001216EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001217{
1218#if 0
1219 // ARM pseudo code...
1220 if (ConditionPassed())
1221 {
1222 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001223 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001224 if d == 15 then // Can only occur for ARM encoding
1225 ALUWritePC(result); // setflags is always FALSE here
1226 else
1227 R[d] = result;
1228 if setflags then
1229 APSR.N = result<31>;
1230 APSR.Z = IsZeroBit(result);
1231 APSR.C = carry;
1232 APSR.V = overflow;
1233 }
1234#endif
1235
1236 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001237
Greg Clayton7bc39082011-03-24 23:53:38 +00001238 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001239 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001240 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001241 if (!success)
1242 return false;
1243 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001244 uint32_t d;
1245 bool setflags;
1246 switch (encoding)
1247 {
1248 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001249 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001250 d = Bits32 (opcode, 10, 8);
1251 setflags = false;
1252 imm32 = (Bits32 (opcode, 7, 0) << 2);
1253
1254 break;
1255
1256 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001257 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001258 d = 13;
1259 setflags = false;
1260 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1261
1262 break;
1263
1264 default:
1265 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001266 }
1267 addr_t sp_offset = imm32;
1268 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1269
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001270 EmulateInstruction::Context context;
1271 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +00001272 RegisterInfo sp_reg;
1273 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001274 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001275
Caroline Ticee2212882011-03-22 22:38:28 +00001276 if (d == 15)
1277 {
1278 if (!ALUWritePC (context, addr))
1279 return false;
1280 }
1281 else
1282 {
1283 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1284 return false;
1285 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001286 }
1287 return true;
1288}
1289
1290// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001291// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001292bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001293EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001294{
1295#if 0
1296 // ARM pseudo code...
1297 if (ConditionPassed())
1298 {
1299 EncodingSpecificOperations();
1300 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001301 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001302 if d == 15 then
1303 ALUWritePC(result); // setflags is always FALSE here
1304 else
1305 R[d] = result;
1306 if setflags then
1307 APSR.N = result<31>;
1308 APSR.Z = IsZeroBit(result);
1309 APSR.C = carry;
1310 APSR.V = overflow;
1311 }
1312#endif
1313
1314 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001315
Greg Clayton7bc39082011-03-24 23:53:38 +00001316 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001317 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001318 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001319 if (!success)
1320 return false;
1321 uint32_t Rm; // the second operand
1322 switch (encoding) {
1323 case eEncodingT2:
1324 Rm = Bits32(opcode, 6, 3);
1325 break;
1326 default:
1327 return false;
1328 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001329 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001330 if (!success)
1331 return false;
1332
1333 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1334
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001335 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00001336 context.type = eContextArithmetic;
1337 RegisterInfo sp_reg;
1338 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1339
1340 RegisterInfo other_reg;
1341 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001342 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001343
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001344 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001345 return false;
1346 }
1347 return true;
1348}
1349
Johnny Chen9b8d7832011-02-02 01:13:56 +00001350// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1351// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1352// from Thumb to ARM.
1353// BLX (immediate)
1354bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001355EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001356{
1357#if 0
1358 // ARM pseudo code...
1359 if (ConditionPassed())
1360 {
1361 EncodingSpecificOperations();
1362 if CurrentInstrSet() == InstrSet_ARM then
1363 LR = PC - 4;
1364 else
1365 LR = PC<31:1> : '1';
1366 if targetInstrSet == InstrSet_ARM then
1367 targetAddress = Align(PC,4) + imm32;
1368 else
1369 targetAddress = PC + imm32;
1370 SelectInstrSet(targetInstrSet);
1371 BranchWritePC(targetAddress);
1372 }
1373#endif
1374
Greg Clayton7bc39082011-03-24 23:53:38 +00001375 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001376
Greg Clayton7bc39082011-03-24 23:53:38 +00001377 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001378 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001379 EmulateInstruction::Context context;
1380 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001381 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001382 if (!success)
1383 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001384 addr_t lr; // next instruction address
1385 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001386 int32_t imm32; // PC-relative offset
1387 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001388 case eEncodingT1:
1389 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001390 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001391 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001392 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001393 uint32_t J1 = Bit32(opcode, 13);
1394 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001395 uint32_t imm11 = Bits32(opcode, 10, 0);
1396 uint32_t I1 = !(J1 ^ S);
1397 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001398 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001399 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001400 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001401 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001402 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001403 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001404 break;
1405 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001406 case eEncodingT2:
1407 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001408 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001409 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001410 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001411 uint32_t J1 = Bit32(opcode, 13);
1412 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001413 uint32_t imm10L = Bits32(opcode, 10, 1);
1414 uint32_t I1 = !(J1 ^ S);
1415 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001416 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001417 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001418 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001419 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001420 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001421 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001422 break;
1423 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001424 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001425 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001426 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001427 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001428 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001429 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001430 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001431 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001432 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001433 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001434 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001435 break;
1436 default:
1437 return false;
1438 }
1439 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1440 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001441 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001442 return false;
1443 }
1444 return true;
1445}
1446
1447// Branch with Link and Exchange (register) calls a subroutine at an address and
1448// instruction set specified by a register.
1449// BLX (register)
1450bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001451EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001452{
1453#if 0
1454 // ARM pseudo code...
1455 if (ConditionPassed())
1456 {
1457 EncodingSpecificOperations();
1458 target = R[m];
1459 if CurrentInstrSet() == InstrSet_ARM then
1460 next_instr_addr = PC - 4;
1461 LR = next_instr_addr;
1462 else
1463 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001464 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001465 BXWritePC(target);
1466 }
1467#endif
1468
1469 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001470
Greg Clayton7bc39082011-03-24 23:53:38 +00001471 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001472 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001473 EmulateInstruction::Context context;
1474 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001475 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001476 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001477 if (!success)
1478 return false;
1479 uint32_t Rm; // the register with the target address
1480 switch (encoding) {
1481 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001482 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001483 Rm = Bits32(opcode, 6, 3);
1484 // if m == 15 then UNPREDICTABLE;
1485 if (Rm == 15)
1486 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001487 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001488 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001489 break;
1490 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001491 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001492 Rm = Bits32(opcode, 3, 0);
1493 // if m == 15 then UNPREDICTABLE;
1494 if (Rm == 15)
1495 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001496 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001497 default:
1498 return false;
1499 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001500 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001501 if (!success)
1502 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001503 RegisterInfo dwarf_reg;
1504 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001505 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001506 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1507 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001508 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001509 return false;
1510 }
1511 return true;
1512}
1513
Johnny Chenab3b3512011-02-12 00:10:51 +00001514// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001515bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001516EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001517{
1518#if 0
1519 // ARM pseudo code...
1520 if (ConditionPassed())
1521 {
1522 EncodingSpecificOperations();
1523 BXWritePC(R[m]);
1524 }
1525#endif
1526
Greg Clayton7bc39082011-03-24 23:53:38 +00001527 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001528 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001529 EmulateInstruction::Context context;
1530 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001531 uint32_t Rm; // the register with the target address
1532 switch (encoding) {
1533 case eEncodingT1:
1534 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001535 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001536 return false;
1537 break;
1538 case eEncodingA1:
1539 Rm = Bits32(opcode, 3, 0);
1540 break;
1541 default:
1542 return false;
1543 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001544 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001545 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001546 if (!success)
1547 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001548
1549 RegisterInfo dwarf_reg;
1550 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen668b4512011-02-15 21:08:58 +00001551 context.SetRegister (dwarf_reg);
1552 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001553 return false;
1554 }
1555 return true;
1556}
1557
Johnny Chen59e6ab72011-02-24 21:01:20 +00001558// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1559// address and instruction set specified by a register as though it were a BX instruction.
1560//
1561// TODO: Emulate Jazelle architecture?
1562// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1563bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001564EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001565{
1566#if 0
1567 // ARM pseudo code...
1568 if (ConditionPassed())
1569 {
1570 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001571 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001572 BXWritePC(R[m]);
1573 else
1574 if JazelleAcceptsExecution() then
1575 SwitchToJazelleExecution();
1576 else
1577 SUBARCHITECTURE_DEFINED handler call;
1578 }
1579#endif
1580
Greg Clayton7bc39082011-03-24 23:53:38 +00001581 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001582 {
1583 EmulateInstruction::Context context;
1584 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1585 uint32_t Rm; // the register with the target address
1586 switch (encoding) {
1587 case eEncodingT1:
1588 Rm = Bits32(opcode, 19, 16);
1589 if (BadReg(Rm))
1590 return false;
1591 if (InITBlock() && !LastInITBlock())
1592 return false;
1593 break;
1594 case eEncodingA1:
1595 Rm = Bits32(opcode, 3, 0);
1596 if (Rm == 15)
1597 return false;
1598 break;
1599 default:
1600 return false;
1601 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001602 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001603 addr_t target = ReadCoreReg (Rm, &success);
1604 if (!success)
1605 return false;
1606
Greg Claytonc07d4512011-04-26 23:48:45 +00001607 RegisterInfo dwarf_reg;
1608 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen59e6ab72011-02-24 21:01:20 +00001609 context.SetRegister (dwarf_reg);
1610 if (!BXWritePC(context, target))
1611 return false;
1612 }
1613 return true;
1614}
1615
Johnny Chen0d0148e2011-01-28 02:26:08 +00001616// Set r7 to point to some ip offset.
1617// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001618bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001619EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001620{
1621#if 0
1622 // ARM pseudo code...
1623 if (ConditionPassed())
1624 {
1625 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001626 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001627 if d == 15 then // Can only occur for ARM encoding
1628 ALUWritePC(result); // setflags is always FALSE here
1629 else
1630 R[d] = result;
1631 if setflags then
1632 APSR.N = result<31>;
1633 APSR.Z = IsZeroBit(result);
1634 APSR.C = carry;
1635 APSR.V = overflow;
1636 }
1637#endif
1638
Greg Clayton7bc39082011-03-24 23:53:38 +00001639 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001640 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001641 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001642 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001643 if (!success)
1644 return false;
1645 uint32_t imm32;
1646 switch (encoding) {
1647 case eEncodingA1:
1648 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1649 break;
1650 default:
1651 return false;
1652 }
1653 addr_t ip_offset = imm32;
1654 addr_t addr = ip - ip_offset; // the adjusted ip value
1655
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001656 EmulateInstruction::Context context;
1657 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001658 RegisterInfo dwarf_reg;
1659 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001660 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001661
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001662 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001663 return false;
1664 }
1665 return true;
1666}
1667
1668// Set ip to point to some stack offset.
1669// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001670bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001671EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001672{
1673#if 0
1674 // ARM pseudo code...
1675 if (ConditionPassed())
1676 {
1677 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001678 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001679 if d == 15 then // Can only occur for ARM encoding
1680 ALUWritePC(result); // setflags is always FALSE here
1681 else
1682 R[d] = result;
1683 if setflags then
1684 APSR.N = result<31>;
1685 APSR.Z = IsZeroBit(result);
1686 APSR.C = carry;
1687 APSR.V = overflow;
1688 }
1689#endif
1690
Greg Clayton7bc39082011-03-24 23:53:38 +00001691 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001692 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001693 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001694 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001695 if (!success)
1696 return false;
1697 uint32_t imm32;
1698 switch (encoding) {
1699 case eEncodingA1:
1700 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1701 break;
1702 default:
1703 return false;
1704 }
1705 addr_t sp_offset = imm32;
1706 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1707
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001708 EmulateInstruction::Context context;
1709 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001710 RegisterInfo dwarf_reg;
1711 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001712 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001713
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001714 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001715 return false;
1716 }
1717 return true;
1718}
1719
Johnny Chenc9e747f2011-02-23 01:55:07 +00001720// This instruction subtracts an immediate value from the SP value, and writes
1721// the result to the destination register.
1722//
1723// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001724bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001725EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001726{
1727#if 0
1728 // ARM pseudo code...
1729 if (ConditionPassed())
1730 {
1731 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001732 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001733 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001734 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001735 else
1736 R[d] = result;
1737 if setflags then
1738 APSR.N = result<31>;
1739 APSR.Z = IsZeroBit(result);
1740 APSR.C = carry;
1741 APSR.V = overflow;
1742 }
1743#endif
1744
1745 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001746 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001747 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001748 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001749 if (!success)
1750 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001751
1752 uint32_t Rd;
1753 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001754 uint32_t imm32;
1755 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001756 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001757 Rd = 13;
1758 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001759 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001760 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001761 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001762 Rd = Bits32(opcode, 11, 8);
1763 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001764 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001765 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001766 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001767 if (Rd == 15 && !setflags)
1768 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001769 break;
1770 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001771 Rd = Bits32(opcode, 11, 8);
1772 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001773 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001774 if (Rd == 15)
1775 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001776 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001777 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001778 Rd = Bits32(opcode, 15, 12);
1779 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001780 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001781
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001782 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001783 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001784 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001785 break;
1786 default:
1787 return false;
1788 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001789 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1790
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001791 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001792 if (Rd == 13)
1793 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001794 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1795 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001796 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001797 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001798 }
1799 else
1800 {
1801 context.type = EmulateInstruction::eContextImmediate;
1802 context.SetNoArgs ();
1803 }
1804
1805 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001806 return false;
1807 }
1808 return true;
1809}
1810
Johnny Chen08c25e82011-01-31 18:02:28 +00001811// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001812bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001813EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001814{
1815#if 0
1816 // ARM pseudo code...
1817 if (ConditionPassed())
1818 {
1819 EncodingSpecificOperations();
1820 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1821 address = if index then offset_addr else R[n];
1822 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1823 if wback then R[n] = offset_addr;
1824 }
1825#endif
1826
1827 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001828
Greg Clayton7bc39082011-03-24 23:53:38 +00001829 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001830 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001831 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001832 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001833 if (!success)
1834 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001835 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001836 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001837 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1838
1839 bool index;
1840 bool add;
1841 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001842 switch (encoding) {
1843 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001844 Rt = Bits32(opcode, 15, 12);
1845 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001846 Rn = Bits32 (opcode, 19, 16);
1847
1848 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1849 return false;
1850
1851 index = BitIsSet (opcode, 24);
1852 add = BitIsSet (opcode, 23);
1853 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1854
1855 if (wback && ((Rn == 15) || (Rn == Rt)))
1856 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001857 break;
1858 default:
1859 return false;
1860 }
Caroline Tice3e407972011-03-18 19:41:00 +00001861 addr_t offset_addr;
1862 if (add)
1863 offset_addr = sp + imm12;
1864 else
1865 offset_addr = sp - imm12;
1866
1867 addr_t addr;
1868 if (index)
1869 addr = offset_addr;
1870 else
1871 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001872
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001873 EmulateInstruction::Context context;
1874 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001875 RegisterInfo sp_reg;
1876 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice3e407972011-03-18 19:41:00 +00001877 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001878 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001879 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001880 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001881 if (!success)
1882 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001883 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001884 return false;
1885 }
1886 else
1887 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001888 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001889 if (!success)
1890 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001891 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001892 return false;
1893 }
1894
Caroline Tice3e407972011-03-18 19:41:00 +00001895
1896 if (wback)
1897 {
1898 context.type = EmulateInstruction::eContextAdjustStackPointer;
1899 context.SetImmediateSigned (addr - sp);
1900 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1901 return false;
1902 }
Johnny Chence1ca772011-01-25 01:13:00 +00001903 }
1904 return true;
1905}
1906
Johnny Chen08c25e82011-01-31 18:02:28 +00001907// Vector Push stores multiple extension registers to the stack.
1908// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001909bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001910EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001911{
1912#if 0
1913 // ARM pseudo code...
1914 if (ConditionPassed())
1915 {
1916 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1917 address = SP - imm32;
1918 SP = SP - imm32;
1919 if single_regs then
1920 for r = 0 to regs-1
1921 MemA[address,4] = S[d+r]; address = address+4;
1922 else
1923 for r = 0 to regs-1
1924 // Store as two word-aligned words in the correct order for current endianness.
1925 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1926 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1927 address = address+8;
1928 }
1929#endif
1930
1931 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001932
Greg Clayton7bc39082011-03-24 23:53:38 +00001933 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001934 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001935 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001936 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001937 if (!success)
1938 return false;
1939 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001940 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001941 uint32_t imm32; // stack offset
1942 uint32_t regs; // number of registers
1943 switch (encoding) {
1944 case eEncodingT1:
1945 case eEncodingA1:
1946 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001947 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001948 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1949 // If UInt(imm8) is odd, see "FSTMX".
1950 regs = Bits32(opcode, 7, 0) / 2;
1951 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1952 if (regs == 0 || regs > 16 || (d + regs) > 32)
1953 return false;
1954 break;
1955 case eEncodingT2:
1956 case eEncodingA2:
1957 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001958 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001959 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1960 regs = Bits32(opcode, 7, 0);
1961 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1962 if (regs == 0 || regs > 16 || (d + regs) > 32)
1963 return false;
1964 break;
1965 default:
1966 return false;
1967 }
1968 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1969 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1970 addr_t sp_offset = imm32;
1971 addr_t addr = sp - sp_offset;
1972 uint32_t i;
1973
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001974 EmulateInstruction::Context context;
1975 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001976 RegisterInfo dwarf_reg;
1977 RegisterInfo sp_reg;
1978 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001979 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001980 {
Greg Claytonc07d4512011-04-26 23:48:45 +00001981 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001982 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001983 // uint64_t to accommodate 64-bit registers.
Greg Claytonc07d4512011-04-26 23:48:45 +00001984 uint64_t reg_value = ReadRegisterUnsigned(dwarf_reg, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001985 if (!success)
1986 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001987 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001988 return false;
1989 addr += reg_byte_size;
1990 }
1991
1992 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001993 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001994
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001995 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001996 return false;
1997 }
1998 return true;
1999}
2000
Johnny Chen587a0a42011-02-01 18:35:28 +00002001// Vector Pop loads multiple extension registers from the stack.
2002// It also updates SP to point just above the loaded data.
2003bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002004EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00002005{
2006#if 0
2007 // ARM pseudo code...
2008 if (ConditionPassed())
2009 {
2010 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2011 address = SP;
2012 SP = SP + imm32;
2013 if single_regs then
2014 for r = 0 to regs-1
2015 S[d+r] = MemA[address,4]; address = address+4;
2016 else
2017 for r = 0 to regs-1
2018 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2019 // Combine the word-aligned words in the correct order for current endianness.
2020 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2021 }
2022#endif
2023
2024 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002025
Greg Clayton7bc39082011-03-24 23:53:38 +00002026 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002027 {
2028 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002029 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002030 if (!success)
2031 return false;
2032 bool single_regs;
2033 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2034 uint32_t imm32; // stack offset
2035 uint32_t regs; // number of registers
2036 switch (encoding) {
2037 case eEncodingT1:
2038 case eEncodingA1:
2039 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002040 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002041 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2042 // If UInt(imm8) is odd, see "FLDMX".
2043 regs = Bits32(opcode, 7, 0) / 2;
2044 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2045 if (regs == 0 || regs > 16 || (d + regs) > 32)
2046 return false;
2047 break;
2048 case eEncodingT2:
2049 case eEncodingA2:
2050 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002051 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002052 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2053 regs = Bits32(opcode, 7, 0);
2054 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2055 if (regs == 0 || regs > 16 || (d + regs) > 32)
2056 return false;
2057 break;
2058 default:
2059 return false;
2060 }
2061 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2062 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2063 addr_t sp_offset = imm32;
2064 addr_t addr = sp;
2065 uint32_t i;
2066 uint64_t data; // uint64_t to accomodate 64-bit registers.
2067
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002068 EmulateInstruction::Context context;
2069 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002070 RegisterInfo dwarf_reg;
2071 RegisterInfo sp_reg;
2072 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002073 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002074 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002075 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002076 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002077 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002078 if (!success)
2079 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00002080 if (!WriteRegisterUnsigned(context, dwarf_reg, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002081 return false;
2082 addr += reg_byte_size;
2083 }
2084
2085 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002086 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002087
2088 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2089 return false;
2090 }
2091 return true;
2092}
2093
Johnny Chenb77be412011-02-04 00:40:18 +00002094// SVC (previously SWI)
2095bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002096EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002097{
2098#if 0
2099 // ARM pseudo code...
2100 if (ConditionPassed())
2101 {
2102 EncodingSpecificOperations();
2103 CallSupervisor();
2104 }
2105#endif
2106
2107 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002108
Greg Clayton7bc39082011-03-24 23:53:38 +00002109 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002110 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002111 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002112 addr_t lr; // next instruction address
2113 if (!success)
2114 return false;
2115 uint32_t imm32; // the immediate constant
2116 uint32_t mode; // ARM or Thumb mode
2117 switch (encoding) {
2118 case eEncodingT1:
2119 lr = (pc + 2) | 1u; // return address
2120 imm32 = Bits32(opcode, 7, 0);
2121 mode = eModeThumb;
2122 break;
2123 case eEncodingA1:
2124 lr = pc + 4; // return address
2125 imm32 = Bits32(opcode, 23, 0);
2126 mode = eModeARM;
2127 break;
2128 default:
2129 return false;
2130 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002131
2132 EmulateInstruction::Context context;
2133 context.type = EmulateInstruction::eContextSupervisorCall;
Greg Claytonc07d4512011-04-26 23:48:45 +00002134 context.SetISAAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002135 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2136 return false;
2137 }
2138 return true;
2139}
2140
Johnny Chenc315f862011-02-05 00:46:10 +00002141// If Then makes up to four following instructions (the IT block) conditional.
2142bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002143EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002144{
2145#if 0
2146 // ARM pseudo code...
2147 EncodingSpecificOperations();
2148 ITSTATE.IT<7:0> = firstcond:mask;
2149#endif
2150
Johnny Chenc315f862011-02-05 00:46:10 +00002151 m_it_session.InitIT(Bits32(opcode, 7, 0));
2152 return true;
2153}
2154
Johnny Chen3b620b32011-02-07 20:11:47 +00002155// Branch causes a branch to a target address.
2156bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002157EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002158{
2159#if 0
2160 // ARM pseudo code...
2161 if (ConditionPassed())
2162 {
2163 EncodingSpecificOperations();
2164 BranchWritePC(PC + imm32);
2165 }
2166#endif
2167
2168 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002169
Greg Clayton7bc39082011-03-24 23:53:38 +00002170 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002171 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002172 EmulateInstruction::Context context;
2173 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002174 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002175 if (!success)
2176 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002177 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002178 int32_t imm32; // PC-relative offset
2179 switch (encoding) {
2180 case eEncodingT1:
2181 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2182 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002183 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002184 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002185 break;
2186 case eEncodingT2:
2187 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002188 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002189 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002190 break;
2191 case eEncodingT3:
2192 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2193 {
Johnny Chenbd599902011-02-10 21:39:01 +00002194 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002195 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002196 uint32_t J1 = Bit32(opcode, 13);
2197 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002198 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002199 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002200 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002201 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002202 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002203 break;
2204 }
2205 case eEncodingT4:
2206 {
Johnny Chenbd599902011-02-10 21:39:01 +00002207 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002208 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002209 uint32_t J1 = Bit32(opcode, 13);
2210 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002211 uint32_t imm11 = Bits32(opcode, 10, 0);
2212 uint32_t I1 = !(J1 ^ S);
2213 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002214 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002215 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002216 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002217 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002218 break;
2219 }
2220 case eEncodingA1:
2221 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002222 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002223 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002224 break;
2225 default:
2226 return false;
2227 }
2228 if (!BranchWritePC(context, target))
2229 return false;
2230 }
2231 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002232}
2233
Johnny Chen53ebab72011-02-08 23:21:57 +00002234// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2235// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2236// CBNZ, CBZ
2237bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002238EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002239{
2240#if 0
2241 // ARM pseudo code...
2242 EncodingSpecificOperations();
2243 if nonzero ^ IsZero(R[n]) then
2244 BranchWritePC(PC + imm32);
2245#endif
2246
2247 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002248
2249 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002250 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002251 if (!success)
2252 return false;
2253
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002254 EmulateInstruction::Context context;
2255 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002256 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002257 if (!success)
2258 return false;
2259
2260 addr_t target; // target address
2261 uint32_t imm32; // PC-relative offset to branch forward
2262 bool nonzero;
2263 switch (encoding) {
2264 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002265 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002266 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002267 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002268 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002269 break;
2270 default:
2271 return false;
2272 }
2273 if (nonzero ^ (reg_val == 0))
2274 if (!BranchWritePC(context, target))
2275 return false;
2276
2277 return true;
2278}
2279
Johnny Chen60299ec2011-02-17 19:34:27 +00002280// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2281// A base register provides a pointer to the table, and a second register supplies an index into the table.
2282// The branch length is twice the value of the byte returned from the table.
2283//
2284// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2285// A base register provides a pointer to the table, and a second register supplies an index into the table.
2286// The branch length is twice the value of the halfword returned from the table.
2287// TBB, TBH
2288bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002289EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002290{
2291#if 0
2292 // ARM pseudo code...
2293 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2294 if is_tbh then
2295 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2296 else
2297 halfwords = UInt(MemU[R[n]+R[m], 1]);
2298 BranchWritePC(PC + 2*halfwords);
2299#endif
2300
2301 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002302
2303 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2304 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2305 bool is_tbh; // true if table branch halfword
2306 switch (encoding) {
2307 case eEncodingT1:
2308 Rn = Bits32(opcode, 19, 16);
2309 Rm = Bits32(opcode, 3, 0);
2310 is_tbh = BitIsSet(opcode, 4);
2311 if (Rn == 13 || BadReg(Rm))
2312 return false;
2313 if (InITBlock() && !LastInITBlock())
2314 return false;
2315 break;
2316 default:
2317 return false;
2318 }
2319
2320 // Read the address of the table from the operand register Rn.
2321 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002322 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002323 if (!success)
2324 return false;
2325
2326 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002327 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002328 if (!success)
2329 return false;
2330
2331 // the offsetted table address
2332 addr_t addr = base + (is_tbh ? index*2 : index);
2333
2334 // PC-relative offset to branch forward
2335 EmulateInstruction::Context context;
2336 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002337 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002338 if (!success)
2339 return false;
2340
Johnny Chene39f22d2011-02-19 01:36:13 +00002341 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002342 if (!success)
2343 return false;
2344
2345 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002346 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002347 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Greg Claytonc07d4512011-04-26 23:48:45 +00002348 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
Johnny Chen60299ec2011-02-17 19:34:27 +00002349
2350 if (!BranchWritePC(context, target))
2351 return false;
2352
2353 return true;
2354}
2355
Caroline Ticedcc11b32011-03-02 23:57:02 +00002356// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2357// It can optionally update the condition flags based on the result.
2358bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002359EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002360{
2361#if 0
2362 if ConditionPassed() then
2363 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002364 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002365 R[d] = result;
2366 if setflags then
2367 APSR.N = result<31>;
2368 APSR.Z = IsZeroBit(result);
2369 APSR.C = carry;
2370 APSR.V = overflow;
2371#endif
2372
2373 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002374
Greg Clayton7bc39082011-03-24 23:53:38 +00002375 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002376 {
2377 uint32_t d;
2378 uint32_t n;
2379 bool setflags;
2380 uint32_t imm32;
2381 uint32_t carry_out;
2382
2383 //EncodingSpecificOperations();
2384 switch (encoding)
2385 {
2386 case eEncodingT1:
2387 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2388 d = Bits32 (opcode, 2, 0);
2389 n = Bits32 (opcode, 5, 3);
2390 setflags = !InITBlock();
2391 imm32 = Bits32 (opcode, 8,6);
2392
2393 break;
2394
2395 case eEncodingT2:
2396 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2397 d = Bits32 (opcode, 10, 8);
2398 n = Bits32 (opcode, 10, 8);
2399 setflags = !InITBlock();
2400 imm32 = Bits32 (opcode, 7, 0);
2401
2402 break;
2403
2404 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002405 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2406 // if Rn == '1101' then SEE ADD (SP plus immediate);
2407 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002408 d = Bits32 (opcode, 11, 8);
2409 n = Bits32 (opcode, 19, 16);
2410 setflags = BitIsSet (opcode, 20);
2411 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2412
2413 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2414 if (BadReg (d) || (n == 15))
2415 return false;
2416
2417 break;
2418
2419 case eEncodingT4:
2420 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002421 // if Rn == '1111' then SEE ADR;
2422 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002423 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2424 d = Bits32 (opcode, 11, 8);
2425 n = Bits32 (opcode, 19, 16);
2426 setflags = false;
2427 uint32_t i = Bit32 (opcode, 26);
2428 uint32_t imm3 = Bits32 (opcode, 14, 12);
2429 uint32_t imm8 = Bits32 (opcode, 7, 0);
2430 imm32 = (i << 11) | (imm3 << 8) | imm8;
2431
2432 // if BadReg(d) then UNPREDICTABLE;
2433 if (BadReg (d))
2434 return false;
2435
2436 break;
2437 }
2438 default:
2439 return false;
2440 }
2441
2442 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2443 if (!success)
2444 return false;
2445
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002446 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002447 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2448
Greg Claytonc07d4512011-04-26 23:48:45 +00002449 RegisterInfo reg_n;
2450 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002451
2452 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002453 context.type = eContextArithmetic;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002454 context.SetRegisterPlusOffset (reg_n, imm32);
2455
2456 //R[d] = result;
2457 //if setflags then
2458 //APSR.N = result<31>;
2459 //APSR.Z = IsZeroBit(result);
2460 //APSR.C = carry;
2461 //APSR.V = overflow;
2462 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2463 return false;
2464
2465 }
2466 return true;
2467}
2468
Johnny Chen8fa20592011-02-18 01:22:22 +00002469// This instruction adds an immediate value to a register value, and writes the result to the destination
2470// register. It can optionally update the condition flags based on the result.
2471bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002472EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002473{
2474#if 0
2475 // ARM pseudo code...
2476 if ConditionPassed() then
2477 EncodingSpecificOperations();
2478 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2479 if d == 15 then
2480 ALUWritePC(result); // setflags is always FALSE here
2481 else
2482 R[d] = result;
2483 if setflags then
2484 APSR.N = result<31>;
2485 APSR.Z = IsZeroBit(result);
2486 APSR.C = carry;
2487 APSR.V = overflow;
2488#endif
2489
2490 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002491
Greg Clayton7bc39082011-03-24 23:53:38 +00002492 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002493 {
2494 uint32_t Rd, Rn;
2495 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2496 bool setflags;
2497 switch (encoding)
2498 {
2499 case eEncodingA1:
2500 Rd = Bits32(opcode, 15, 12);
2501 Rn = Bits32(opcode, 19, 16);
2502 setflags = BitIsSet(opcode, 20);
2503 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2504 break;
2505 default:
2506 return false;
2507 }
2508
Johnny Chen8fa20592011-02-18 01:22:22 +00002509 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002510 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002511 if (!success)
2512 return false;
2513
2514 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2515
2516 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002517 context.type = eContextArithmetic;
2518 RegisterInfo dwarf_reg;
2519 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00002520 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002521
2522 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2523 return false;
2524 }
2525 return true;
2526}
2527
Johnny Chend761dcf2011-02-17 22:03:29 +00002528// This instruction adds a register value and an optionally-shifted register value, and writes the result
2529// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002530bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002531EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002532{
2533#if 0
2534 // ARM pseudo code...
2535 if ConditionPassed() then
2536 EncodingSpecificOperations();
2537 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2538 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2539 if d == 15 then
2540 ALUWritePC(result); // setflags is always FALSE here
2541 else
2542 R[d] = result;
2543 if setflags then
2544 APSR.N = result<31>;
2545 APSR.Z = IsZeroBit(result);
2546 APSR.C = carry;
2547 APSR.V = overflow;
2548#endif
2549
2550 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002551
Greg Clayton7bc39082011-03-24 23:53:38 +00002552 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002553 {
2554 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002555 ARM_ShifterType shift_t;
2556 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002557 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002558 switch (encoding)
2559 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002560 case eEncodingT1:
2561 Rd = Bits32(opcode, 2, 0);
2562 Rn = Bits32(opcode, 5, 3);
2563 Rm = Bits32(opcode, 8, 6);
2564 setflags = !InITBlock();
2565 shift_t = SRType_LSL;
2566 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002567 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002568 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002569 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002570 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002571 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002572 shift_t = SRType_LSL;
2573 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002574 if (Rn == 15 && Rm == 15)
2575 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002576 if (Rd == 15 && InITBlock() && !LastInITBlock())
2577 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002578 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002579 case eEncodingA1:
2580 Rd = Bits32(opcode, 15, 12);
2581 Rn = Bits32(opcode, 19, 16);
2582 Rm = Bits32(opcode, 3, 0);
2583 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002584 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002585 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002586 default:
2587 return false;
2588 }
2589
Johnny Chen26863dc2011-02-09 23:43:29 +00002590 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002591 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002592 if (!success)
2593 return false;
2594
2595 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002596 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002597 if (!success)
2598 return false;
2599
Johnny Chene97c0d52011-02-18 19:32:20 +00002600 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002601 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002602
2603 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002604 context.type = eContextArithmetic;
2605 RegisterInfo op1_reg;
2606 RegisterInfo op2_reg;
2607 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2608 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00002609 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002610
Johnny Chen10530c22011-02-17 22:37:12 +00002611 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002612 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002613 }
2614 return true;
2615}
2616
Johnny Chen34075cb2011-02-22 01:56:31 +00002617// Compare Negative (immediate) adds a register value and an immediate value.
2618// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002619bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002620EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002621{
2622#if 0
2623 // ARM pseudo code...
2624 if ConditionPassed() then
2625 EncodingSpecificOperations();
2626 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2627 APSR.N = result<31>;
2628 APSR.Z = IsZeroBit(result);
2629 APSR.C = carry;
2630 APSR.V = overflow;
2631#endif
2632
2633 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002634
2635 uint32_t Rn; // the first operand
2636 uint32_t imm32; // the immediate value to be compared with
2637 switch (encoding) {
2638 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002639 Rn = Bits32(opcode, 19, 16);
2640 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2641 if (Rn == 15)
2642 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002643 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002644 case eEncodingA1:
2645 Rn = Bits32(opcode, 19, 16);
2646 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2647 break;
2648 default:
2649 return false;
2650 }
2651 // Read the register value from the operand register Rn.
2652 uint32_t reg_val = ReadCoreReg(Rn, &success);
2653 if (!success)
2654 return false;
2655
Johnny Chen078fbc62011-02-22 19:48:22 +00002656 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002657
2658 EmulateInstruction::Context context;
2659 context.type = EmulateInstruction::eContextImmediate;
2660 context.SetNoArgs ();
2661 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2662 return false;
2663
2664 return true;
2665}
2666
2667// Compare Negative (register) adds a register value and an optionally-shifted register value.
2668// It updates the condition flags based on the result, and discards the result.
2669bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002670EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002671{
2672#if 0
2673 // ARM pseudo code...
2674 if ConditionPassed() then
2675 EncodingSpecificOperations();
2676 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2677 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2678 APSR.N = result<31>;
2679 APSR.Z = IsZeroBit(result);
2680 APSR.C = carry;
2681 APSR.V = overflow;
2682#endif
2683
2684 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002685
2686 uint32_t Rn; // the first operand
2687 uint32_t Rm; // the second operand
2688 ARM_ShifterType shift_t;
2689 uint32_t shift_n; // the shift applied to the value read from Rm
2690 switch (encoding) {
2691 case eEncodingT1:
2692 Rn = Bits32(opcode, 2, 0);
2693 Rm = Bits32(opcode, 5, 3);
2694 shift_t = SRType_LSL;
2695 shift_n = 0;
2696 break;
2697 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002698 Rn = Bits32(opcode, 19, 16);
2699 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002700 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002701 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2702 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002703 return false;
2704 break;
2705 case eEncodingA1:
2706 Rn = Bits32(opcode, 19, 16);
2707 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002708 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002709 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002710 default:
2711 return false;
2712 }
2713 // Read the register value from register Rn.
2714 uint32_t val1 = ReadCoreReg(Rn, &success);
2715 if (!success)
2716 return false;
2717
2718 // Read the register value from register Rm.
2719 uint32_t val2 = ReadCoreReg(Rm, &success);
2720 if (!success)
2721 return false;
2722
2723 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002724 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002725
2726 EmulateInstruction::Context context;
2727 context.type = EmulateInstruction::eContextImmediate;
2728 context.SetNoArgs();
2729 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2730 return false;
2731
2732 return true;
2733}
2734
2735// Compare (immediate) subtracts an immediate value from a register value.
2736// It updates the condition flags based on the result, and discards the result.
2737bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002738EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002739{
2740#if 0
2741 // ARM pseudo code...
2742 if ConditionPassed() then
2743 EncodingSpecificOperations();
2744 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2745 APSR.N = result<31>;
2746 APSR.Z = IsZeroBit(result);
2747 APSR.C = carry;
2748 APSR.V = overflow;
2749#endif
2750
2751 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002752
2753 uint32_t Rn; // the first operand
2754 uint32_t imm32; // the immediate value to be compared with
2755 switch (encoding) {
2756 case eEncodingT1:
2757 Rn = Bits32(opcode, 10, 8);
2758 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002759 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002760 case eEncodingT2:
2761 Rn = Bits32(opcode, 19, 16);
2762 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2763 if (Rn == 15)
2764 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002765 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002766 case eEncodingA1:
2767 Rn = Bits32(opcode, 19, 16);
2768 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002769 break;
2770 default:
2771 return false;
2772 }
2773 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002774 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002775 if (!success)
2776 return false;
2777
Johnny Chen10530c22011-02-17 22:37:12 +00002778 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2779
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002780 EmulateInstruction::Context context;
2781 context.type = EmulateInstruction::eContextImmediate;
2782 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002783 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2784 return false;
2785
Johnny Chend4dc4442011-02-11 02:02:56 +00002786 return true;
2787}
2788
Johnny Chen34075cb2011-02-22 01:56:31 +00002789// Compare (register) subtracts an optionally-shifted register value from a register value.
2790// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002791bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002792EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002793{
2794#if 0
2795 // ARM pseudo code...
2796 if ConditionPassed() then
2797 EncodingSpecificOperations();
2798 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2799 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2800 APSR.N = result<31>;
2801 APSR.Z = IsZeroBit(result);
2802 APSR.C = carry;
2803 APSR.V = overflow;
2804#endif
2805
2806 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002807
2808 uint32_t Rn; // the first operand
2809 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002810 ARM_ShifterType shift_t;
2811 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002812 switch (encoding) {
2813 case eEncodingT1:
2814 Rn = Bits32(opcode, 2, 0);
2815 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002816 shift_t = SRType_LSL;
2817 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002818 break;
2819 case eEncodingT2:
2820 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2821 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002822 shift_t = SRType_LSL;
2823 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002824 if (Rn < 8 && Rm < 8)
2825 return false;
2826 if (Rn == 15 || Rm == 15)
2827 return false;
2828 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002829 case eEncodingA1:
2830 Rn = Bits32(opcode, 19, 16);
2831 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002832 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002833 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002834 default:
2835 return false;
2836 }
2837 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002838 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002839 if (!success)
2840 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002841
Johnny Chene4a4d302011-02-11 21:53:58 +00002842 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002843 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002844 if (!success)
2845 return false;
2846
Johnny Chen34075cb2011-02-22 01:56:31 +00002847 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2848 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002849
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002850 EmulateInstruction::Context context;
2851 context.type = EmulateInstruction::eContextImmediate;
2852 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002853 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2854 return false;
2855
Johnny Chene4a4d302011-02-11 21:53:58 +00002856 return true;
2857}
2858
Johnny Chen82f16aa2011-02-15 20:10:55 +00002859// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2860// shifting in copies of its sign bit, and writes the result to the destination register. It can
2861// optionally update the condition flags based on the result.
2862bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002863EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002864{
2865#if 0
2866 // ARM pseudo code...
2867 if ConditionPassed() then
2868 EncodingSpecificOperations();
2869 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2870 if d == 15 then // Can only occur for ARM encoding
2871 ALUWritePC(result); // setflags is always FALSE here
2872 else
2873 R[d] = result;
2874 if setflags then
2875 APSR.N = result<31>;
2876 APSR.Z = IsZeroBit(result);
2877 APSR.C = carry;
2878 // APSR.V unchanged
2879#endif
2880
Greg Clayton7bc39082011-03-24 23:53:38 +00002881 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002882}
2883
2884// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2885// shifting in copies of its sign bit, and writes the result to the destination register.
2886// The variable number of bits is read from the bottom byte of a register. It can optionally update
2887// the condition flags based on the result.
2888bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002889EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002890{
2891#if 0
2892 // ARM pseudo code...
2893 if ConditionPassed() then
2894 EncodingSpecificOperations();
2895 shift_n = UInt(R[m]<7:0>);
2896 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2897 R[d] = result;
2898 if setflags then
2899 APSR.N = result<31>;
2900 APSR.Z = IsZeroBit(result);
2901 APSR.C = carry;
2902 // APSR.V unchanged
2903#endif
2904
Greg Clayton7bc39082011-03-24 23:53:38 +00002905 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002906}
2907
2908// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2909// shifting in zeros, and writes the result to the destination register. It can optionally
2910// update the condition flags based on the result.
2911bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002912EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002913{
2914#if 0
2915 // ARM pseudo code...
2916 if ConditionPassed() then
2917 EncodingSpecificOperations();
2918 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2919 if d == 15 then // Can only occur for ARM encoding
2920 ALUWritePC(result); // setflags is always FALSE here
2921 else
2922 R[d] = result;
2923 if setflags then
2924 APSR.N = result<31>;
2925 APSR.Z = IsZeroBit(result);
2926 APSR.C = carry;
2927 // APSR.V unchanged
2928#endif
2929
Greg Clayton7bc39082011-03-24 23:53:38 +00002930 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002931}
2932
2933// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2934// shifting in zeros, and writes the result to the destination register. The variable number
2935// of bits is read from the bottom byte of a register. It can optionally update the condition
2936// flags based on the result.
2937bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002938EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002939{
2940#if 0
2941 // ARM pseudo code...
2942 if ConditionPassed() then
2943 EncodingSpecificOperations();
2944 shift_n = UInt(R[m]<7:0>);
2945 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2946 R[d] = result;
2947 if setflags then
2948 APSR.N = result<31>;
2949 APSR.Z = IsZeroBit(result);
2950 APSR.C = carry;
2951 // APSR.V unchanged
2952#endif
2953
Greg Clayton7bc39082011-03-24 23:53:38 +00002954 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002955}
2956
2957// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2958// shifting in zeros, and writes the result to the destination register. It can optionally
2959// update the condition flags based on the result.
2960bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002961EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002962{
2963#if 0
2964 // ARM pseudo code...
2965 if ConditionPassed() then
2966 EncodingSpecificOperations();
2967 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2968 if d == 15 then // Can only occur for ARM encoding
2969 ALUWritePC(result); // setflags is always FALSE here
2970 else
2971 R[d] = result;
2972 if setflags then
2973 APSR.N = result<31>;
2974 APSR.Z = IsZeroBit(result);
2975 APSR.C = carry;
2976 // APSR.V unchanged
2977#endif
2978
Greg Clayton7bc39082011-03-24 23:53:38 +00002979 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002980}
2981
2982// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2983// shifting in zeros, and writes the result to the destination register. The variable number
2984// of bits is read from the bottom byte of a register. It can optionally update the condition
2985// flags based on the result.
2986bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002987EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002988{
2989#if 0
2990 // ARM pseudo code...
2991 if ConditionPassed() then
2992 EncodingSpecificOperations();
2993 shift_n = UInt(R[m]<7:0>);
2994 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2995 R[d] = result;
2996 if setflags then
2997 APSR.N = result<31>;
2998 APSR.Z = IsZeroBit(result);
2999 APSR.C = carry;
3000 // APSR.V unchanged
3001#endif
3002
Greg Clayton7bc39082011-03-24 23:53:38 +00003003 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003004}
3005
Johnny Cheneeab4852011-02-16 22:14:44 +00003006// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3007// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3008// It can optionally update the condition flags based on the result.
3009bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003010EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003011{
3012#if 0
3013 // ARM pseudo code...
3014 if ConditionPassed() then
3015 EncodingSpecificOperations();
3016 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3017 if d == 15 then // Can only occur for ARM encoding
3018 ALUWritePC(result); // setflags is always FALSE here
3019 else
3020 R[d] = result;
3021 if setflags then
3022 APSR.N = result<31>;
3023 APSR.Z = IsZeroBit(result);
3024 APSR.C = carry;
3025 // APSR.V unchanged
3026#endif
3027
Greg Clayton7bc39082011-03-24 23:53:38 +00003028 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003029}
3030
3031// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3032// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3033// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3034// flags based on the result.
3035bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003036EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003037{
3038#if 0
3039 // ARM pseudo code...
3040 if ConditionPassed() then
3041 EncodingSpecificOperations();
3042 shift_n = UInt(R[m]<7:0>);
3043 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3044 R[d] = result;
3045 if setflags then
3046 APSR.N = result<31>;
3047 APSR.Z = IsZeroBit(result);
3048 APSR.C = carry;
3049 // APSR.V unchanged
3050#endif
3051
Greg Clayton7bc39082011-03-24 23:53:38 +00003052 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003053}
3054
3055// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3056// with the carry flag shifted into bit [31].
3057//
3058// RRX can optionally update the condition flags based on the result.
3059// In that case, bit [0] is shifted into the carry flag.
3060bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003061EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003062{
3063#if 0
3064 // ARM pseudo code...
3065 if ConditionPassed() then
3066 EncodingSpecificOperations();
3067 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3068 if d == 15 then // Can only occur for ARM encoding
3069 ALUWritePC(result); // setflags is always FALSE here
3070 else
3071 R[d] = result;
3072 if setflags then
3073 APSR.N = result<31>;
3074 APSR.Z = IsZeroBit(result);
3075 APSR.C = carry;
3076 // APSR.V unchanged
3077#endif
3078
Greg Clayton7bc39082011-03-24 23:53:38 +00003079 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003080}
3081
Johnny Chen41a0a152011-02-16 01:27:54 +00003082bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003083EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003084{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003085 assert(shift_type == SRType_ASR
3086 || shift_type == SRType_LSL
3087 || shift_type == SRType_LSR
3088 || shift_type == SRType_ROR
3089 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003090
Johnny Chen82f16aa2011-02-15 20:10:55 +00003091 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003092
Greg Clayton7bc39082011-03-24 23:53:38 +00003093 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003094 {
Johnny Chene7f89532011-02-15 23:22:46 +00003095 uint32_t Rd; // the destination register
3096 uint32_t Rm; // the first operand register
3097 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003098 uint32_t carry; // the carry bit after the shift operation
3099 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003100
3101 // Special case handling!
3102 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003103 ARMEncoding use_encoding = encoding;
3104 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003105 {
3106 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3107 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003108 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003109 }
3110
Greg Clayton7bc39082011-03-24 23:53:38 +00003111 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003112 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003113 // Due to the above special case handling!
3114 assert(shift_type != SRType_ROR);
3115
Johnny Chen82f16aa2011-02-15 20:10:55 +00003116 Rd = Bits32(opcode, 2, 0);
3117 Rm = Bits32(opcode, 5, 3);
3118 setflags = !InITBlock();
3119 imm5 = Bits32(opcode, 10, 6);
3120 break;
3121 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003122 // A8.6.141 RRX
3123 assert(shift_type != SRType_RRX);
3124
Johnny Chen82f16aa2011-02-15 20:10:55 +00003125 Rd = Bits32(opcode, 11, 8);
3126 Rm = Bits32(opcode, 3, 0);
3127 setflags = BitIsSet(opcode, 20);
3128 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3129 if (BadReg(Rd) || BadReg(Rm))
3130 return false;
3131 break;
3132 case eEncodingA1:
3133 Rd = Bits32(opcode, 15, 12);
3134 Rm = Bits32(opcode, 3, 0);
3135 setflags = BitIsSet(opcode, 20);
3136 imm5 = Bits32(opcode, 11, 7);
3137 break;
3138 default:
3139 return false;
3140 }
3141
Johnny Cheneeab4852011-02-16 22:14:44 +00003142 // A8.6.139 ROR (immediate)
3143 if (shift_type == SRType_ROR && imm5 == 0)
3144 shift_type = SRType_RRX;
3145
Johnny Chen82f16aa2011-02-15 20:10:55 +00003146 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003147 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003148 if (!success)
3149 return false;
3150
Johnny Cheneeab4852011-02-16 22:14:44 +00003151 // Decode the shift amount if not RRX.
3152 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003153
Johnny Chene97c0d52011-02-18 19:32:20 +00003154 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003155
3156 // The context specifies that an immediate is to be moved into Rd.
3157 EmulateInstruction::Context context;
3158 context.type = EmulateInstruction::eContextImmediate;
3159 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003160
Johnny Chen10530c22011-02-17 22:37:12 +00003161 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003162 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003163 }
3164 return true;
3165}
3166
Johnny Chene7f89532011-02-15 23:22:46 +00003167bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003168EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003169{
Johnny Chen41a0a152011-02-16 01:27:54 +00003170 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003171
3172 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003173
Greg Clayton7bc39082011-03-24 23:53:38 +00003174 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003175 {
3176 uint32_t Rd; // the destination register
3177 uint32_t Rn; // the first operand register
3178 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3179 uint32_t carry; // the carry bit after the shift operation
3180 bool setflags;
3181 switch (encoding) {
3182 case eEncodingT1:
3183 Rd = Bits32(opcode, 2, 0);
3184 Rn = Rd;
3185 Rm = Bits32(opcode, 5, 3);
3186 setflags = !InITBlock();
3187 break;
3188 case eEncodingT2:
3189 Rd = Bits32(opcode, 11, 8);
3190 Rn = Bits32(opcode, 19, 16);
3191 Rm = Bits32(opcode, 3, 0);
3192 setflags = BitIsSet(opcode, 20);
3193 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3194 return false;
3195 break;
3196 case eEncodingA1:
3197 Rd = Bits32(opcode, 15, 12);
3198 Rn = Bits32(opcode, 3, 0);
3199 Rm = Bits32(opcode, 11, 8);
3200 setflags = BitIsSet(opcode, 20);
3201 if (Rd == 15 || Rn == 15 || Rm == 15)
3202 return false;
3203 break;
3204 default:
3205 return false;
3206 }
3207
3208 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003209 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003210 if (!success)
3211 return false;
3212 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003213 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003214 if (!success)
3215 return false;
3216
3217 // Get the shift amount.
3218 uint32_t amt = Bits32(val, 7, 0);
3219
Johnny Chene97c0d52011-02-18 19:32:20 +00003220 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003221
3222 // The context specifies that an immediate is to be moved into Rd.
3223 EmulateInstruction::Context context;
3224 context.type = EmulateInstruction::eContextImmediate;
3225 context.SetNoArgs ();
3226
Johnny Chen10530c22011-02-17 22:37:12 +00003227 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003228 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003229 }
3230 return true;
3231}
3232
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003233// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003234// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003235// can be written back to the base register.
3236bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003237EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003238{
3239#if 0
3240 // ARM pseudo code...
3241 if ConditionPassed()
3242 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3243 address = R[n];
3244
3245 for i = 0 to 14
3246 if registers<i> == '1' then
3247 R[i] = MemA[address, 4]; address = address + 4;
3248 if registers<15> == '1' then
3249 LoadWritePC (MemA[address, 4]);
3250
3251 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3252 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3253
3254#endif
3255
3256 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003257
Greg Clayton7bc39082011-03-24 23:53:38 +00003258 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003259 {
3260 uint32_t n;
3261 uint32_t registers = 0;
3262 bool wback;
3263 const uint32_t addr_byte_size = GetAddressByteSize();
3264 switch (encoding)
3265 {
3266 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003267 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003268 n = Bits32 (opcode, 10, 8);
3269 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003270 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003271 wback = BitIsClear (registers, n);
3272 // if BitCount(registers) < 1 then UNPREDICTABLE;
3273 if (BitCount(registers) < 1)
3274 return false;
3275 break;
3276 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003277 // if W == '1' && Rn == '1101' then SEE POP;
3278 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003279 n = Bits32 (opcode, 19, 16);
3280 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003281 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003282 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003283
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003284 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003285 if ((n == 15)
3286 || (BitCount (registers) < 2)
3287 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3288 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003289
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003290 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003291 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003292 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003293
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003294 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003295 if (wback
3296 && BitIsSet (registers, n))
3297 return false;
3298 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003299
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003300 case eEncodingA1:
3301 n = Bits32 (opcode, 19, 16);
3302 registers = Bits32 (opcode, 15, 0);
3303 wback = BitIsSet (opcode, 21);
3304 if ((n == 15)
3305 || (BitCount (registers) < 1))
3306 return false;
3307 break;
3308 default:
3309 return false;
3310 }
3311
3312 int32_t offset = 0;
3313 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3314 if (!success)
3315 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003316
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003317 EmulateInstruction::Context context;
3318 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003319 RegisterInfo dwarf_reg;
3320 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003321 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003322
3323 for (int i = 0; i < 14; ++i)
3324 {
3325 if (BitIsSet (registers, i))
3326 {
Caroline Tice85aab332011-02-08 23:56:10 +00003327 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003328 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003329 if (wback && (n == 13)) // Pop Instruction
3330 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3331
3332 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003333 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003334 if (!success)
3335 return false;
3336
3337 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3338 return false;
3339
3340 offset += addr_byte_size;
3341 }
3342 }
3343
3344 if (BitIsSet (registers, 15))
3345 {
3346 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003347 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003348 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003349 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003350 if (!success)
3351 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003352 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003353 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003354 return false;
3355 }
3356
3357 if (wback && BitIsClear (registers, n))
3358 {
Caroline Ticefa172202011-02-11 22:49:54 +00003359 // R[n] = R[n] + 4 * BitCount (registers)
3360 int32_t offset = addr_byte_size * BitCount (registers);
3361 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003362 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003363
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003364 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3365 return false;
3366 }
3367 if (wback && BitIsSet (registers, n))
3368 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003369 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003370 }
3371 return true;
3372}
Caroline Tice713c2662011-02-11 17:59:55 +00003373
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003374// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3375// The consecutive memory locations end at this address and the address just below the lowest of those locations
3376// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003377bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003378EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003379{
3380#if 0
3381 // ARM pseudo code...
3382 if ConditionPassed() then
3383 EncodingSpecificOperations();
3384 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003385
Caroline Tice713c2662011-02-11 17:59:55 +00003386 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003387 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003388 R[i] = MemA[address,4]; address = address + 4;
3389
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003390 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003391 LoadWritePC(MemA[address,4]);
3392
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003393 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3394 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003395#endif
3396
3397 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003398
Greg Clayton7bc39082011-03-24 23:53:38 +00003399 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003400 {
3401 uint32_t n;
3402 uint32_t registers = 0;
3403 bool wback;
3404 const uint32_t addr_byte_size = GetAddressByteSize();
3405
3406 // EncodingSpecificOperations();
3407 switch (encoding)
3408 {
3409 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003410 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003411 n = Bits32 (opcode, 19, 16);
3412 registers = Bits32 (opcode, 15, 0);
3413 wback = BitIsSet (opcode, 21);
3414
3415 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3416 if ((n == 15) || (BitCount (registers) < 1))
3417 return false;
3418
3419 break;
3420
3421 default:
3422 return false;
3423 }
3424 // address = R[n] - 4*BitCount(registers) + 4;
3425
3426 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003427 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003428
3429 if (!success)
3430 return false;
3431
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003432 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003433
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003434 EmulateInstruction::Context context;
3435 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003436 RegisterInfo dwarf_reg;
3437 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003438 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003439
3440 // for i = 0 to 14
3441 for (int i = 0; i < 14; ++i)
3442 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003443 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003444 if (BitIsSet (registers, i))
3445 {
3446 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003447 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003448 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003449 if (!success)
3450 return false;
3451 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3452 return false;
3453 offset += addr_byte_size;
3454 }
3455 }
3456
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003457 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003458 // LoadWritePC(MemA[address,4]);
3459 if (BitIsSet (registers, 15))
3460 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003461 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003462 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003463 if (!success)
3464 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003465 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003466 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003467 return false;
3468 }
3469
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003470 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003471 if (wback && BitIsClear (registers, n))
3472 {
Caroline Tice713c2662011-02-11 17:59:55 +00003473 if (!success)
3474 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003475
3476 offset = (addr_byte_size * BitCount (registers)) * -1;
3477 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003478 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003479 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003480 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3481 return false;
3482 }
3483
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003484 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003485 if (wback && BitIsSet (registers, n))
3486 return WriteBits32Unknown (n);
3487 }
3488 return true;
3489}
3490
3491// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3492// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3493// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003494bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003495EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003496{
3497#if 0
3498 // ARM pseudo code...
3499 if ConditionPassed() then
3500 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3501 address = R[n] - 4*BitCount(registers);
3502
3503 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003504 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003505 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003506 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003507 LoadWritePC(MemA[address,4]);
3508
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003509 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3510 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003511#endif
3512
3513 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003514
Greg Clayton7bc39082011-03-24 23:53:38 +00003515 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003516 {
3517 uint32_t n;
3518 uint32_t registers = 0;
3519 bool wback;
3520 const uint32_t addr_byte_size = GetAddressByteSize();
3521 switch (encoding)
3522 {
3523 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003524 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003525 n = Bits32 (opcode, 19, 16);
3526 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003527 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003528 wback = BitIsSet (opcode, 21);
3529
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003530 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003531 if ((n == 15)
3532 || (BitCount (registers) < 2)
3533 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3534 return false;
3535
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003536 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003537 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003538 return false;
3539
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003540 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003541 if (wback && BitIsSet (registers, n))
3542 return false;
3543
3544 break;
3545
3546 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003547 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003548 n = Bits32 (opcode, 19, 16);
3549 registers = Bits32 (opcode, 15, 0);
3550 wback = BitIsSet (opcode, 21);
3551
3552 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3553 if ((n == 15) || (BitCount (registers) < 1))
3554 return false;
3555
3556 break;
3557
3558 default:
3559 return false;
3560 }
3561
Caroline Tice713c2662011-02-11 17:59:55 +00003562 // address = R[n] - 4*BitCount(registers);
3563
Caroline Tice0b29e242011-02-08 23:16:02 +00003564 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003565 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003566
3567 if (!success)
3568 return false;
3569
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003570 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003571 EmulateInstruction::Context context;
3572 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003573 RegisterInfo dwarf_reg;
3574 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003575 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003576
3577 for (int i = 0; i < 14; ++i)
3578 {
3579 if (BitIsSet (registers, i))
3580 {
3581 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003582 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003583 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003584 if (!success)
3585 return false;
3586
3587 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3588 return false;
3589
3590 offset += addr_byte_size;
3591 }
3592 }
3593
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003594 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003595 // LoadWritePC(MemA[address,4]);
3596 if (BitIsSet (registers, 15))
3597 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003598 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003599 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003600 if (!success)
3601 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003602 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003603 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003604 return false;
3605 }
3606
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003607 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003608 if (wback && BitIsClear (registers, n))
3609 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003610 if (!success)
3611 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003612
3613 offset = (addr_byte_size * BitCount (registers)) * -1;
3614 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003615 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003616 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003617 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3618 return false;
3619 }
3620
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003621 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003622 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003623 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003624 }
3625 return true;
3626}
Caroline Tice85aab332011-02-08 23:56:10 +00003627
Caroline Tice713c2662011-02-11 17:59:55 +00003628// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3629// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3630// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003631bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003632EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003633{
3634#if 0
3635 if ConditionPassed() then
3636 EncodingSpecificOperations();
3637 address = R[n] + 4;
3638
3639 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003640 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003641 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003642 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003643 LoadWritePC(MemA[address,4]);
3644
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003645 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3646 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003647#endif
3648
3649 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003650
Greg Clayton7bc39082011-03-24 23:53:38 +00003651 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003652 {
3653 uint32_t n;
3654 uint32_t registers = 0;
3655 bool wback;
3656 const uint32_t addr_byte_size = GetAddressByteSize();
3657 switch (encoding)
3658 {
3659 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003660 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003661 n = Bits32 (opcode, 19, 16);
3662 registers = Bits32 (opcode, 15, 0);
3663 wback = BitIsSet (opcode, 21);
3664
3665 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3666 if ((n == 15) || (BitCount (registers) < 1))
3667 return false;
3668
3669 break;
3670 default:
3671 return false;
3672 }
3673 // address = R[n] + 4;
3674
3675 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003676 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003677
3678 if (!success)
3679 return false;
3680
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003681 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003682
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003683 EmulateInstruction::Context context;
3684 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003685 RegisterInfo dwarf_reg;
3686 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003687 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003688
3689 for (int i = 0; i < 14; ++i)
3690 {
3691 if (BitIsSet (registers, i))
3692 {
3693 // R[i] = MemA[address,4]; address = address + 4;
3694
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003695 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003696 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003697 if (!success)
3698 return false;
3699
3700 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3701 return false;
3702
3703 offset += addr_byte_size;
3704 }
3705 }
3706
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003707 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003708 // LoadWritePC(MemA[address,4]);
3709 if (BitIsSet (registers, 15))
3710 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003711 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003712 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003713 if (!success)
3714 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003715 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003716 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003717 return false;
3718 }
3719
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003720 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003721 if (wback && BitIsClear (registers, n))
3722 {
Caroline Tice85aab332011-02-08 23:56:10 +00003723 if (!success)
3724 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003725
3726 offset = addr_byte_size * BitCount (registers);
3727 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003728 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003729 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003730 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3731 return false;
3732 }
3733
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003734 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003735 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003736 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003737 }
3738 return true;
3739}
Caroline Tice0b29e242011-02-08 23:16:02 +00003740
Johnny Chenef21b592011-02-10 01:52:38 +00003741// Load Register (immediate) calculates an address from a base register value and
3742// an immediate offset, loads a word from memory, and writes to a register.
3743// LDR (immediate, Thumb)
3744bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003745EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003746{
3747#if 0
3748 // ARM pseudo code...
3749 if (ConditionPassed())
3750 {
3751 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3752 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3753 address = if index then offset_addr else R[n];
3754 data = MemU[address,4];
3755 if wback then R[n] = offset_addr;
3756 if t == 15 then
3757 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3758 elsif UnalignedSupport() || address<1:0> = '00' then
3759 R[t] = data;
3760 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3761 }
3762#endif
3763
3764 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003765
Greg Clayton7bc39082011-03-24 23:53:38 +00003766 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003767 {
3768 uint32_t Rt; // the destination register
3769 uint32_t Rn; // the base register
3770 uint32_t imm32; // the immediate offset used to form the address
3771 addr_t offset_addr; // the offset address
3772 addr_t address; // the calculated address
3773 uint32_t data; // the literal data value from memory load
3774 bool add, index, wback;
3775 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003776 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003777 Rt = Bits32(opcode, 2, 0);
3778 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003779 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3780 // index = TRUE; add = TRUE; wback = FALSE
3781 add = true;
3782 index = true;
3783 wback = false;
3784
3785 break;
3786
3787 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003788 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003789 Rt = Bits32 (opcode, 10, 8);
3790 Rn = 13;
3791 imm32 = Bits32 (opcode, 7, 0) << 2;
3792
3793 // index = TRUE; add = TRUE; wback = FALSE;
3794 index = true;
3795 add = true;
3796 wback = false;
3797
3798 break;
3799
3800 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003801 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003802 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3803 Rt = Bits32 (opcode, 15, 12);
3804 Rn = Bits32 (opcode, 19, 16);
3805 imm32 = Bits32 (opcode, 11, 0);
3806
3807 // index = TRUE; add = TRUE; wback = FALSE;
3808 index = true;
3809 add = true;
3810 wback = false;
3811
3812 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3813 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3814 return false;
3815
3816 break;
3817
3818 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003819 // if Rn == '1111' then SEE LDR (literal);
3820 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3821 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3822 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003823 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3824 return false;
3825
3826 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3827 Rt = Bits32 (opcode, 15, 12);
3828 Rn = Bits32 (opcode, 19, 16);
3829 imm32 = Bits32 (opcode, 7, 0);
3830
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003831 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003832 index = BitIsSet (opcode, 10);
3833 add = BitIsSet (opcode, 9);
3834 wback = BitIsSet (opcode, 8);
3835
3836 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3837 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3838 return false;
3839
3840 break;
3841
3842 default:
3843 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003844 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003845 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003846 if (!success)
3847 return false;
3848 if (add)
3849 offset_addr = base + imm32;
3850 else
3851 offset_addr = base - imm32;
3852
3853 address = (index ? offset_addr : base);
3854
Greg Claytonc07d4512011-04-26 23:48:45 +00003855 RegisterInfo base_reg;
3856 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
Johnny Chenef21b592011-02-10 01:52:38 +00003857 if (wback)
3858 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003859 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003860 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3861 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003862
Johnny Chenef21b592011-02-10 01:52:38 +00003863 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3864 return false;
3865 }
3866
3867 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003868 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003869 context.type = EmulateInstruction::eContextRegisterLoad;
3870 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003871
3872 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003873 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003874 if (!success)
3875 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003876
3877 if (Rt == 15)
3878 {
3879 if (Bits32(address, 1, 0) == 0)
3880 {
Johnny Chen668b4512011-02-15 21:08:58 +00003881 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003882 return false;
3883 }
3884 else
3885 return false;
3886 }
3887 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3888 {
3889 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3890 return false;
3891 }
3892 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003893 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003894 }
3895 return true;
3896}
3897
Caroline Ticeaf556562011-02-15 18:42:15 +00003898// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3899// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3900// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003901bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003902EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003903{
3904#if 0
3905 if ConditionPassed() then
3906 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3907 address = R[n];
3908
3909 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003910 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003911 if i == n && wback && i != LowestSetBit(registers) then
3912 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3913 else
3914 MemA[address,4] = R[i];
3915 address = address + 4;
3916
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003917 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003918 MemA[address,4] = PCStoreValue();
3919 if wback then R[n] = R[n] + 4*BitCount(registers);
3920#endif
3921
3922 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003923
Greg Clayton7bc39082011-03-24 23:53:38 +00003924 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003925 {
3926 uint32_t n;
3927 uint32_t registers = 0;
3928 bool wback;
3929 const uint32_t addr_byte_size = GetAddressByteSize();
3930
3931 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3932 switch (encoding)
3933 {
3934 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003935 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003936 n = Bits32 (opcode, 10, 8);
3937 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003938 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003939 wback = true;
3940
3941 // if BitCount(registers) < 1 then UNPREDICTABLE;
3942 if (BitCount (registers) < 1)
3943 return false;
3944
3945 break;
3946
3947 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003948 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003949 n = Bits32 (opcode, 19, 16);
3950 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003951 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003952 wback = BitIsSet (opcode, 21);
3953
3954 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3955 if ((n == 15) || (BitCount (registers) < 2))
3956 return false;
3957
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003958 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003959 if (wback && BitIsSet (registers, n))
3960 return false;
3961
3962 break;
3963
3964 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003965 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003966 n = Bits32 (opcode, 19, 16);
3967 registers = Bits32 (opcode, 15, 0);
3968 wback = BitIsSet (opcode, 21);
3969
3970 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3971 if ((n == 15) || (BitCount (registers) < 1))
3972 return false;
3973
3974 break;
3975
3976 default:
3977 return false;
3978 }
3979
3980 // address = R[n];
3981 int32_t offset = 0;
3982 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3983 if (!success)
3984 return false;
3985
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003986 EmulateInstruction::Context context;
3987 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00003988 RegisterInfo base_reg;
3989 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefa172202011-02-11 22:49:54 +00003990
3991 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003992 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003993 for (int i = 0; i < 14; ++i)
3994 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003995 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003996 if (BitIsSet (registers, i))
3997 {
3998 if (i < lowest_set_bit)
3999 lowest_set_bit = i;
4000 // if i == n && wback && i != LowestSetBit(registers) then
4001 if ((i == n) && wback && (i != lowest_set_bit))
4002 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4003 WriteBits32UnknownToMemory (address + offset);
4004 else
4005 {
4006 // MemA[address,4] = R[i];
4007 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4008 if (!success)
4009 return false;
4010
Greg Claytonc07d4512011-04-26 23:48:45 +00004011 RegisterInfo data_reg;
4012 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004013 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004014 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004015 return false;
4016 }
4017
4018 // address = address + 4;
4019 offset += addr_byte_size;
4020 }
4021 }
4022
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004023 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004024 // MemA[address,4] = PCStoreValue();
4025 if (BitIsSet (registers, 15))
4026 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004027 RegisterInfo pc_reg;
4028 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004029 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004030 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004031 if (!success)
4032 return false;
4033
Caroline Tice8d681f52011-03-17 23:50:16 +00004034 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004035 return false;
4036 }
4037
4038 // if wback then R[n] = R[n] + 4*BitCount(registers);
4039 if (wback)
4040 {
4041 offset = addr_byte_size * BitCount (registers);
4042 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004043 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004044 addr_t data = address + offset;
4045 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4046 return false;
4047 }
4048 }
4049 return true;
4050}
4051
Caroline Ticeaf556562011-02-15 18:42:15 +00004052// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4053// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4054// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004055bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004056EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004057{
4058#if 0
4059 if ConditionPassed() then
4060 EncodingSpecificOperations();
4061 address = R[n] - 4*BitCount(registers) + 4;
4062
4063 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004064 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004065 if i == n && wback && i != LowestSetBit(registers) then
4066 MemA[address,4] = bits(32) UNKNOWN;
4067 else
4068 MemA[address,4] = R[i];
4069 address = address + 4;
4070
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004071 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004072 MemA[address,4] = PCStoreValue();
4073
4074 if wback then R[n] = R[n] - 4*BitCount(registers);
4075#endif
4076
4077 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004078
Greg Clayton7bc39082011-03-24 23:53:38 +00004079 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004080 {
4081 uint32_t n;
4082 uint32_t registers = 0;
4083 bool wback;
4084 const uint32_t addr_byte_size = GetAddressByteSize();
4085
4086 // EncodingSpecificOperations();
4087 switch (encoding)
4088 {
4089 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004090 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004091 n = Bits32 (opcode, 19, 16);
4092 registers = Bits32 (opcode, 15, 0);
4093 wback = BitIsSet (opcode, 21);
4094
4095 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4096 if ((n == 15) || (BitCount (registers) < 1))
4097 return false;
4098 break;
4099 default:
4100 return false;
4101 }
4102
4103 // address = R[n] - 4*BitCount(registers) + 4;
4104 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004105 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004106 if (!success)
4107 return false;
4108
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004109 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004110
4111 EmulateInstruction::Context context;
4112 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004113 RegisterInfo base_reg;
4114 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004115
4116 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004117 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004118 for (int i = 0; i < 14; ++i)
4119 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004120 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004121 if (BitIsSet (registers, i))
4122 {
4123 if (i < lowest_bit_set)
4124 lowest_bit_set = i;
4125 //if i == n && wback && i != LowestSetBit(registers) then
4126 if ((i == n) && wback && (i != lowest_bit_set))
4127 // MemA[address,4] = bits(32) UNKNOWN;
4128 WriteBits32UnknownToMemory (address + offset);
4129 else
4130 {
4131 // MemA[address,4] = R[i];
4132 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4133 if (!success)
4134 return false;
4135
Greg Claytonc07d4512011-04-26 23:48:45 +00004136 RegisterInfo data_reg;
4137 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004138 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004139 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004140 return false;
4141 }
4142
4143 // address = address + 4;
4144 offset += addr_byte_size;
4145 }
4146 }
4147
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004148 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004149 // MemA[address,4] = PCStoreValue();
4150 if (BitIsSet (registers, 15))
4151 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004152 RegisterInfo pc_reg;
4153 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004154 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004155 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004156 if (!success)
4157 return false;
4158
Caroline Tice8d681f52011-03-17 23:50:16 +00004159 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004160 return false;
4161 }
4162
4163 // if wback then R[n] = R[n] - 4*BitCount(registers);
4164 if (wback)
4165 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004166 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004167 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4168 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004169 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004170 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4171 return false;
4172 }
4173 }
4174 return true;
4175}
4176
Caroline Ticeaf556562011-02-15 18:42:15 +00004177// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4178// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4179// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004180bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004181EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004182{
4183#if 0
4184 if ConditionPassed() then
4185 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4186 address = R[n] - 4*BitCount(registers);
4187
4188 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004189 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004190 if i == n && wback && i != LowestSetBit(registers) then
4191 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4192 else
4193 MemA[address,4] = R[i];
4194 address = address + 4;
4195
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004196 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004197 MemA[address,4] = PCStoreValue();
4198
4199 if wback then R[n] = R[n] - 4*BitCount(registers);
4200#endif
4201
4202
4203 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004204
Greg Clayton7bc39082011-03-24 23:53:38 +00004205 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004206 {
4207 uint32_t n;
4208 uint32_t registers = 0;
4209 bool wback;
4210 const uint32_t addr_byte_size = GetAddressByteSize();
4211
4212 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4213 switch (encoding)
4214 {
4215 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004216 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004217 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4218 {
4219 // See PUSH
4220 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004221 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004222 n = Bits32 (opcode, 19, 16);
4223 registers = Bits32 (opcode, 15, 0);
4224 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4225 wback = BitIsSet (opcode, 21);
4226 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4227 if ((n == 15) || BitCount (registers) < 2)
4228 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004229 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004230 if (wback && BitIsSet (registers, n))
4231 return false;
4232 break;
4233
4234 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004235 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004236 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4237 {
4238 // See Push
4239 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004240 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004241 n = Bits32 (opcode, 19, 16);
4242 registers = Bits32 (opcode, 15, 0);
4243 wback = BitIsSet (opcode, 21);
4244 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4245 if ((n == 15) || BitCount (registers) < 1)
4246 return false;
4247 break;
4248
4249 default:
4250 return false;
4251 }
4252
4253 // address = R[n] - 4*BitCount(registers);
4254
4255 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004256 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004257 if (!success)
4258 return false;
4259
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004260 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004261
4262 EmulateInstruction::Context context;
4263 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004264 RegisterInfo base_reg;
4265 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004266
4267 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004268 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004269 for (int i = 0; i < 14; ++i)
4270 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004271 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004272 if (BitIsSet (registers, i))
4273 {
4274 if (i < lowest_set_bit)
4275 lowest_set_bit = i;
4276 // if i == n && wback && i != LowestSetBit(registers) then
4277 if ((i == n) && wback && (i != lowest_set_bit))
4278 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4279 WriteBits32UnknownToMemory (address + offset);
4280 else
4281 {
4282 // MemA[address,4] = R[i];
4283 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4284 if (!success)
4285 return false;
4286
Greg Claytonc07d4512011-04-26 23:48:45 +00004287 RegisterInfo data_reg;
4288 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004289 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004290 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004291 return false;
4292 }
4293
4294 // address = address + 4;
4295 offset += addr_byte_size;
4296 }
4297 }
4298
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004299 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004300 // MemA[address,4] = PCStoreValue();
4301 if (BitIsSet (registers, 15))
4302 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004303 RegisterInfo pc_reg;
4304 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004305 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004306 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004307 if (!success)
4308 return false;
4309
Caroline Tice8d681f52011-03-17 23:50:16 +00004310 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004311 return false;
4312 }
4313
4314 // if wback then R[n] = R[n] - 4*BitCount(registers);
4315 if (wback)
4316 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004317 offset = (addr_byte_size * BitCount (registers)) * -1;
4318 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4319 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004320 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004321 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4322 return false;
4323 }
4324 }
4325 return true;
4326}
4327
4328// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4329// from a base register. The consecutive memory locations start just above this address, and the address of the last
4330// of those locations can optionally be written back to the base register.
4331bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004332EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004333{
4334#if 0
4335 if ConditionPassed() then
4336 EncodingSpecificOperations();
4337 address = R[n] + 4;
4338
4339 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004340 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004341 if i == n && wback && i != LowestSetBit(registers) then
4342 MemA[address,4] = bits(32) UNKNOWN;
4343 else
4344 MemA[address,4] = R[i];
4345 address = address + 4;
4346
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004347 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004348 MemA[address,4] = PCStoreValue();
4349
4350 if wback then R[n] = R[n] + 4*BitCount(registers);
4351#endif
4352
4353 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004354
Greg Clayton7bc39082011-03-24 23:53:38 +00004355 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004356 {
4357 uint32_t n;
4358 uint32_t registers = 0;
4359 bool wback;
4360 const uint32_t addr_byte_size = GetAddressByteSize();
4361
4362 // EncodingSpecificOperations();
4363 switch (encoding)
4364 {
4365 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004366 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004367 n = Bits32 (opcode, 19, 16);
4368 registers = Bits32 (opcode, 15, 0);
4369 wback = BitIsSet (opcode, 21);
4370
4371 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4372 if ((n == 15) && (BitCount (registers) < 1))
4373 return false;
4374 break;
4375 default:
4376 return false;
4377 }
4378 // address = R[n] + 4;
4379
4380 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004381 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004382 if (!success)
4383 return false;
4384
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004385 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004386
4387 EmulateInstruction::Context context;
4388 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004389 RegisterInfo base_reg;
4390 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004391
4392 uint32_t lowest_set_bit = 14;
4393 // for i = 0 to 14
4394 for (int i = 0; i < 14; ++i)
4395 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004396 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004397 if (BitIsSet (registers, i))
4398 {
4399 if (i < lowest_set_bit)
4400 lowest_set_bit = i;
4401 // if i == n && wback && i != LowestSetBit(registers) then
4402 if ((i == n) && wback && (i != lowest_set_bit))
4403 // MemA[address,4] = bits(32) UNKNOWN;
4404 WriteBits32UnknownToMemory (address + offset);
4405 // else
4406 else
4407 {
4408 // MemA[address,4] = R[i];
4409 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4410 if (!success)
4411 return false;
4412
Greg Claytonc07d4512011-04-26 23:48:45 +00004413 RegisterInfo data_reg;
4414 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004415 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004416 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004417 return false;
4418 }
4419
4420 // address = address + 4;
4421 offset += addr_byte_size;
4422 }
4423 }
4424
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004425 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004426 // MemA[address,4] = PCStoreValue();
4427 if (BitIsSet (registers, 15))
4428 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004429 RegisterInfo pc_reg;
4430 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004431 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004432 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004433 if (!success)
4434 return false;
4435
Caroline Tice8d681f52011-03-17 23:50:16 +00004436 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004437 return false;
4438 }
4439
4440 // if wback then R[n] = R[n] + 4*BitCount(registers);
4441 if (wback)
4442 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004443 offset = addr_byte_size * BitCount (registers);
4444 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4445 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004446 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004447 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4448 return false;
4449 }
4450 }
4451 return true;
4452}
Caroline Tice7fac8572011-02-15 22:53:54 +00004453
4454// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4455// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4456bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004457EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004458{
4459#if 0
4460 if ConditionPassed() then
4461 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4462 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4463 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004464 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004465 MemU[address,4] = R[t];
4466 else // Can only occur before ARMv7
4467 MemU[address,4] = bits(32) UNKNOWN;
4468 if wback then R[n] = offset_addr;
4469#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004470
Caroline Tice7fac8572011-02-15 22:53:54 +00004471 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004472
Greg Clayton7bc39082011-03-24 23:53:38 +00004473 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004474 {
4475 const uint32_t addr_byte_size = GetAddressByteSize();
4476
4477 uint32_t t;
4478 uint32_t n;
4479 uint32_t imm32;
4480 bool index;
4481 bool add;
4482 bool wback;
4483 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4484 switch (encoding)
4485 {
4486 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004487 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004488 t = Bits32 (opcode, 2, 0);
4489 n = Bits32 (opcode, 5, 3);
4490 imm32 = Bits32 (opcode, 10, 6) << 2;
4491
4492 // index = TRUE; add = TRUE; wback = FALSE;
4493 index = true;
4494 add = false;
4495 wback = false;
4496 break;
4497
4498 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004499 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004500 t = Bits32 (opcode, 10, 8);
4501 n = 13;
4502 imm32 = Bits32 (opcode, 7, 0) << 2;
4503
4504 // index = TRUE; add = TRUE; wback = FALSE;
4505 index = true;
4506 add = true;
4507 wback = false;
4508 break;
4509
4510 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004511 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004512 if (Bits32 (opcode, 19, 16) == 15)
4513 return false;
4514
4515 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4516 t = Bits32 (opcode, 15, 12);
4517 n = Bits32 (opcode, 19, 16);
4518 imm32 = Bits32 (opcode, 11, 0);
4519
4520 // index = TRUE; add = TRUE; wback = FALSE;
4521 index = true;
4522 add = true;
4523 wback = false;
4524
4525 // if t == 15 then UNPREDICTABLE;
4526 if (t == 15)
4527 return false;
4528 break;
4529
4530 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004531 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4532 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4533 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004534 if ((Bits32 (opcode, 19, 16) == 15)
4535 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4536 return false;
4537
4538 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4539 t = Bits32 (opcode, 15, 12);
4540 n = Bits32 (opcode, 19, 16);
4541 imm32 = Bits32 (opcode, 7, 0);
4542
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004543 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004544 index = BitIsSet (opcode, 10);
4545 add = BitIsSet (opcode, 9);
4546 wback = BitIsSet (opcode, 8);
4547
4548 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4549 if ((t == 15) || (wback && (n == t)))
4550 return false;
4551 break;
4552
4553 default:
4554 return false;
4555 }
4556
4557 addr_t offset_addr;
4558 addr_t address;
4559
4560 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004561 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004562 if (!success)
4563 return false;
4564
4565 if (add)
4566 offset_addr = base_address + imm32;
4567 else
4568 offset_addr = base_address - imm32;
4569
4570 // address = if index then offset_addr else R[n];
4571 if (index)
4572 address = offset_addr;
4573 else
4574 address = base_address;
4575
4576 EmulateInstruction::Context context;
4577 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004578 RegisterInfo base_reg;
4579 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004580
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004581 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004582 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4583 {
4584 // MemU[address,4] = R[t];
4585 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4586 if (!success)
4587 return false;
4588
Greg Claytonc07d4512011-04-26 23:48:45 +00004589 RegisterInfo data_reg;
4590 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004591 int32_t offset = address - base_address;
4592 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004593 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004594 return false;
4595 }
4596 else
4597 {
4598 // MemU[address,4] = bits(32) UNKNOWN;
4599 WriteBits32UnknownToMemory (address);
4600 }
4601
4602 // if wback then R[n] = offset_addr;
4603 if (wback)
4604 {
4605 context.type = eContextRegisterLoad;
4606 context.SetAddress (offset_addr);
4607 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4608 return false;
4609 }
4610 }
4611 return true;
4612}
Caroline Ticeaf556562011-02-15 18:42:15 +00004613
Caroline Tice3fd63e92011-02-16 00:33:43 +00004614// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4615// word from a register to memory. The offset register value can optionally be shifted.
4616bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004617EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004618{
4619#if 0
4620 if ConditionPassed() then
4621 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4622 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4623 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4624 address = if index then offset_addr else R[n];
4625 if t == 15 then // Only possible for encoding A1
4626 data = PCStoreValue();
4627 else
4628 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004629 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004630 MemU[address,4] = data;
4631 else // Can only occur before ARMv7
4632 MemU[address,4] = bits(32) UNKNOWN;
4633 if wback then R[n] = offset_addr;
4634#endif
4635
4636 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004637
Greg Clayton7bc39082011-03-24 23:53:38 +00004638 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004639 {
4640 const uint32_t addr_byte_size = GetAddressByteSize();
4641
4642 uint32_t t;
4643 uint32_t n;
4644 uint32_t m;
4645 ARM_ShifterType shift_t;
4646 uint32_t shift_n;
4647 bool index;
4648 bool add;
4649 bool wback;
4650
4651 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4652 switch (encoding)
4653 {
4654 case eEncodingT1:
4655 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4656 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4657 t = Bits32 (opcode, 2, 0);
4658 n = Bits32 (opcode, 5, 3);
4659 m = Bits32 (opcode, 8, 6);
4660
4661 // index = TRUE; add = TRUE; wback = FALSE;
4662 index = true;
4663 add = true;
4664 wback = false;
4665
4666 // (shift_t, shift_n) = (SRType_LSL, 0);
4667 shift_t = SRType_LSL;
4668 shift_n = 0;
4669 break;
4670
4671 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004672 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004673 if (Bits32 (opcode, 19, 16) == 15)
4674 return false;
4675
4676 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4677 t = Bits32 (opcode, 15, 12);
4678 n = Bits32 (opcode, 19, 16);
4679 m = Bits32 (opcode, 3, 0);
4680
4681 // index = TRUE; add = TRUE; wback = FALSE;
4682 index = true;
4683 add = true;
4684 wback = false;
4685
4686 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4687 shift_t = SRType_LSL;
4688 shift_n = Bits32 (opcode, 5, 4);
4689
4690 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4691 if ((t == 15) || (BadReg (m)))
4692 return false;
4693 break;
4694
4695 case eEncodingA1:
4696 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004697 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004698 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4699 t = Bits32 (opcode, 15, 12);
4700 n = Bits32 (opcode, 19, 16);
4701 m = Bits32 (opcode, 3, 0);
4702
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004703 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004704 index = BitIsSet (opcode, 24);
4705 add = BitIsSet (opcode, 23);
4706 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4707
4708 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4709 uint32_t typ = Bits32 (opcode, 6, 5);
4710 uint32_t imm5 = Bits32 (opcode, 11, 7);
4711 shift_n = DecodeImmShift(typ, imm5, shift_t);
4712
4713 // if m == 15 then UNPREDICTABLE;
4714 if (m == 15)
4715 return false;
4716
4717 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4718 if (wback && ((n == 15) || (n == t)))
4719 return false;
4720
4721 break;
4722 }
4723 default:
4724 return false;
4725 }
4726
4727 addr_t offset_addr;
4728 addr_t address;
4729 int32_t offset = 0;
4730
4731 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4732 if (!success)
4733 return false;
4734
4735 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4736 if (!success)
4737 return false;
4738
4739 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004740 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004741
4742 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4743 if (add)
4744 offset_addr = base_address + offset;
4745 else
4746 offset_addr = base_address - offset;
4747
4748 // address = if index then offset_addr else R[n];
4749 if (index)
4750 address = offset_addr;
4751 else
4752 address = base_address;
4753
4754 uint32_t data;
4755 // if t == 15 then // Only possible for encoding A1
4756 if (t == 15)
4757 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004758 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004759 else
4760 // data = R[t];
4761 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4762
4763 if (!success)
4764 return false;
4765
4766 EmulateInstruction::Context context;
4767 context.type = eContextRegisterStore;
4768
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004769 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004770 if (UnalignedSupport ()
4771 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4772 || CurrentInstrSet() == eModeARM)
4773 {
4774 // MemU[address,4] = data;
4775
Greg Claytonc07d4512011-04-26 23:48:45 +00004776 RegisterInfo base_reg;
4777 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004778
Greg Claytonc07d4512011-04-26 23:48:45 +00004779 RegisterInfo data_reg;
4780 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004781
4782 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004783 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004784 return false;
4785
4786 }
4787 else
4788 // MemU[address,4] = bits(32) UNKNOWN;
4789 WriteBits32UnknownToMemory (address);
4790
4791 // if wback then R[n] = offset_addr;
4792 if (wback)
4793 {
4794 context.type = eContextRegisterLoad;
4795 context.SetAddress (offset_addr);
4796 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4797 return false;
4798 }
4799
4800 }
4801 return true;
4802}
Caroline Tice73a29de2011-02-16 20:22:22 +00004803
4804bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004805EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004806{
4807#if 0
4808 if ConditionPassed() then
4809 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4810 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4811 address = if index then offset_addr else R[n];
4812 MemU[address,1] = R[t]<7:0>;
4813 if wback then R[n] = offset_addr;
4814#endif
4815
4816
4817 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004818
Greg Clayton7bc39082011-03-24 23:53:38 +00004819 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004820 {
4821 uint32_t t;
4822 uint32_t n;
4823 uint32_t imm32;
4824 bool index;
4825 bool add;
4826 bool wback;
4827 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4828 switch (encoding)
4829 {
4830 case eEncodingT1:
4831 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4832 t = Bits32 (opcode, 2, 0);
4833 n = Bits32 (opcode, 5, 3);
4834 imm32 = Bits32 (opcode, 10, 6);
4835
4836 // index = TRUE; add = TRUE; wback = FALSE;
4837 index = true;
4838 add = true;
4839 wback = false;
4840 break;
4841
4842 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004843 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004844 if (Bits32 (opcode, 19, 16) == 15)
4845 return false;
4846
4847 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4848 t = Bits32 (opcode, 15, 12);
4849 n = Bits32 (opcode, 19, 16);
4850 imm32 = Bits32 (opcode, 11, 0);
4851
4852 // index = TRUE; add = TRUE; wback = FALSE;
4853 index = true;
4854 add = true;
4855 wback = false;
4856
4857 // if BadReg(t) then UNPREDICTABLE;
4858 if (BadReg (t))
4859 return false;
4860 break;
4861
4862 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004863 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4864 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004865 if (Bits32 (opcode, 19, 16) == 15)
4866 return false;
4867
4868 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4869 t = Bits32 (opcode, 15, 12);
4870 n = Bits32 (opcode, 19, 16);
4871 imm32 = Bits32 (opcode, 7, 0);
4872
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004873 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004874 index = BitIsSet (opcode, 10);
4875 add = BitIsSet (opcode, 9);
4876 wback = BitIsSet (opcode, 8);
4877
4878 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4879 if ((BadReg (t)) || (wback && (n == t)))
4880 return false;
4881 break;
4882
4883 default:
4884 return false;
4885 }
4886
4887 addr_t offset_addr;
4888 addr_t address;
4889 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4890 if (!success)
4891 return false;
4892
4893 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4894 if (add)
4895 offset_addr = base_address + imm32;
4896 else
4897 offset_addr = base_address - imm32;
4898
4899 // address = if index then offset_addr else R[n];
4900 if (index)
4901 address = offset_addr;
4902 else
4903 address = base_address;
4904
Caroline Ticecc96eb52011-02-17 19:20:40 +00004905 // MemU[address,1] = R[t]<7:0>
Greg Claytonc07d4512011-04-26 23:48:45 +00004906 RegisterInfo base_reg;
4907 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004908
Greg Claytonc07d4512011-04-26 23:48:45 +00004909 RegisterInfo data_reg;
4910 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004911
4912 EmulateInstruction::Context context;
4913 context.type = eContextRegisterStore;
4914 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4915
4916 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4917 if (!success)
4918 return false;
4919
4920 data = Bits32 (data, 7, 0);
4921
Caroline Ticecc96eb52011-02-17 19:20:40 +00004922 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004923 return false;
4924
4925 // if wback then R[n] = offset_addr;
4926 if (wback)
4927 {
4928 context.type = eContextRegisterLoad;
4929 context.SetAddress (offset_addr);
4930 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4931 return false;
4932 }
4933
4934 }
4935
4936 return true;
4937}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004938
4939// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4940// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4941bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004942EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004943{
4944#if 0
4945 if ConditionPassed() then
4946 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4947 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4948 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4949 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004950 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004951 MemU[address,2] = R[t]<15:0>;
4952 else // Can only occur before ARMv7
4953 MemU[address,2] = bits(16) UNKNOWN;
4954 if wback then R[n] = offset_addr;
4955#endif
4956
4957 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004958
Greg Clayton7bc39082011-03-24 23:53:38 +00004959 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004960 {
4961 uint32_t t;
4962 uint32_t n;
4963 uint32_t m;
4964 bool index;
4965 bool add;
4966 bool wback;
4967 ARM_ShifterType shift_t;
4968 uint32_t shift_n;
4969
4970 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4971 switch (encoding)
4972 {
4973 case eEncodingT1:
4974 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4975 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4976 t = Bits32 (opcode, 2, 0);
4977 n = Bits32 (opcode, 5, 3);
4978 m = Bits32 (opcode, 8, 6);
4979
4980 // index = TRUE; add = TRUE; wback = FALSE;
4981 index = true;
4982 add = true;
4983 wback = false;
4984
4985 // (shift_t, shift_n) = (SRType_LSL, 0);
4986 shift_t = SRType_LSL;
4987 shift_n = 0;
4988
4989 break;
4990
4991 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004992 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004993 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4994 t = Bits32 (opcode, 15, 12);
4995 n = Bits32 (opcode, 19, 16);
4996 m = Bits32 (opcode, 3, 0);
4997 if (n == 15)
4998 return false;
4999
5000 // index = TRUE; add = TRUE; wback = FALSE;
5001 index = true;
5002 add = true;
5003 wback = false;
5004
5005 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5006 shift_t = SRType_LSL;
5007 shift_n = Bits32 (opcode, 5, 4);
5008
5009 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5010 if (BadReg (t) || BadReg (m))
5011 return false;
5012
5013 break;
5014
5015 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005016 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005017 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5018 t = Bits32 (opcode, 15, 12);
5019 n = Bits32 (opcode, 19, 16);
5020 m = Bits32 (opcode, 3, 0);
5021
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005022 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005023 index = BitIsSet (opcode, 24);
5024 add = BitIsSet (opcode, 23);
5025 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5026
5027 // (shift_t, shift_n) = (SRType_LSL, 0);
5028 shift_t = SRType_LSL;
5029 shift_n = 0;
5030
5031 // if t == 15 || m == 15 then UNPREDICTABLE;
5032 if ((t == 15) || (m == 15))
5033 return false;
5034
5035 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5036 if (wback && ((n == 15) || (n == t)))
5037 return false;
5038
5039 break;
5040
5041 default:
5042 return false;
5043 }
5044
5045 uint32_t Rm = ReadCoreReg (m, &success);
5046 if (!success)
5047 return false;
5048
5049 uint32_t Rn = ReadCoreReg (n, &success);
5050 if (!success)
5051 return false;
5052
5053 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5054 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5055
5056 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5057 addr_t offset_addr;
5058 if (add)
5059 offset_addr = Rn + offset;
5060 else
5061 offset_addr = Rn - offset;
5062
5063 // address = if index then offset_addr else R[n];
5064 addr_t address;
5065 if (index)
5066 address = offset_addr;
5067 else
5068 address = Rn;
5069
5070 EmulateInstruction::Context context;
5071 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005072 RegisterInfo base_reg;
5073 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5074 RegisterInfo offset_reg;
5075 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005076
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005077 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005078 if (UnalignedSupport() || BitIsClear (address, 0))
5079 {
5080 // MemU[address,2] = R[t]<15:0>;
5081 uint32_t Rt = ReadCoreReg (t, &success);
5082 if (!success)
5083 return false;
5084
5085 EmulateInstruction::Context context;
5086 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005087 RegisterInfo base_reg;
5088 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5089 RegisterInfo offset_reg;
5090 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5091 RegisterInfo data_reg;
5092 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005093 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5094
5095 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5096 return false;
5097 }
5098 else // Can only occur before ARMv7
5099 {
5100 // MemU[address,2] = bits(16) UNKNOWN;
5101 }
5102
5103 // if wback then R[n] = offset_addr;
5104 if (wback)
5105 {
5106 context.type = eContextAdjustBaseRegister;
5107 context.SetAddress (offset_addr);
5108 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5109 return false;
5110 }
5111 }
5112
5113 return true;
5114}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005115
Johnny Chen157b9592011-02-18 21:13:05 +00005116// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5117// and writes the result to the destination register. It can optionally update the condition flags
5118// based on the result.
5119bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005120EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005121{
5122#if 0
5123 // ARM pseudo code...
5124 if ConditionPassed() then
5125 EncodingSpecificOperations();
5126 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5127 if d == 15 then // Can only occur for ARM encoding
5128 ALUWritePC(result); // setflags is always FALSE here
5129 else
5130 R[d] = result;
5131 if setflags then
5132 APSR.N = result<31>;
5133 APSR.Z = IsZeroBit(result);
5134 APSR.C = carry;
5135 APSR.V = overflow;
5136#endif
5137
5138 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005139
Greg Clayton7bc39082011-03-24 23:53:38 +00005140 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005141 {
5142 uint32_t Rd, Rn;
5143 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5144 bool setflags;
5145 switch (encoding)
5146 {
5147 case eEncodingT1:
5148 Rd = Bits32(opcode, 11, 8);
5149 Rn = Bits32(opcode, 19, 16);
5150 setflags = BitIsSet(opcode, 20);
5151 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5152 if (BadReg(Rd) || BadReg(Rn))
5153 return false;
5154 break;
5155 case eEncodingA1:
5156 Rd = Bits32(opcode, 15, 12);
5157 Rn = Bits32(opcode, 19, 16);
5158 setflags = BitIsSet(opcode, 20);
5159 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005160
Johnny Chen157b9592011-02-18 21:13:05 +00005161 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005162 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005163 break;
5164 default:
5165 return false;
5166 }
5167
5168 // Read the first operand.
5169 int32_t val1 = ReadCoreReg(Rn, &success);
5170 if (!success)
5171 return false;
5172
5173 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5174
5175 EmulateInstruction::Context context;
5176 context.type = EmulateInstruction::eContextImmediate;
5177 context.SetNoArgs ();
5178
5179 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5180 return false;
5181 }
5182 return true;
5183}
5184
5185// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5186// register value, and writes the result to the destination register. It can optionally update the
5187// condition flags based on the result.
5188bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005189EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005190{
5191#if 0
5192 // ARM pseudo code...
5193 if ConditionPassed() then
5194 EncodingSpecificOperations();
5195 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5196 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5197 if d == 15 then // Can only occur for ARM encoding
5198 ALUWritePC(result); // setflags is always FALSE here
5199 else
5200 R[d] = result;
5201 if setflags then
5202 APSR.N = result<31>;
5203 APSR.Z = IsZeroBit(result);
5204 APSR.C = carry;
5205 APSR.V = overflow;
5206#endif
5207
5208 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005209
Greg Clayton7bc39082011-03-24 23:53:38 +00005210 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005211 {
5212 uint32_t Rd, Rn, Rm;
5213 ARM_ShifterType shift_t;
5214 uint32_t shift_n; // the shift applied to the value read from Rm
5215 bool setflags;
5216 switch (encoding)
5217 {
5218 case eEncodingT1:
5219 Rd = Rn = Bits32(opcode, 2, 0);
5220 Rm = Bits32(opcode, 5, 3);
5221 setflags = !InITBlock();
5222 shift_t = SRType_LSL;
5223 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005224 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005225 case eEncodingT2:
5226 Rd = Bits32(opcode, 11, 8);
5227 Rn = Bits32(opcode, 19, 16);
5228 Rm = Bits32(opcode, 3, 0);
5229 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005230 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005231 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5232 return false;
5233 break;
5234 case eEncodingA1:
5235 Rd = Bits32(opcode, 15, 12);
5236 Rn = Bits32(opcode, 19, 16);
5237 Rm = Bits32(opcode, 3, 0);
5238 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005239 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005240
Johnny Chen157b9592011-02-18 21:13:05 +00005241 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005242 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005243 break;
5244 default:
5245 return false;
5246 }
5247
5248 // Read the first operand.
5249 int32_t val1 = ReadCoreReg(Rn, &success);
5250 if (!success)
5251 return false;
5252
5253 // Read the second operand.
5254 int32_t val2 = ReadCoreReg(Rm, &success);
5255 if (!success)
5256 return false;
5257
5258 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5259 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5260
5261 EmulateInstruction::Context context;
5262 context.type = EmulateInstruction::eContextImmediate;
5263 context.SetNoArgs ();
5264
5265 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5266 return false;
5267 }
5268 return true;
5269}
5270
Johnny Chena695f952011-02-23 21:24:25 +00005271// This instruction adds an immediate value to the PC value to form a PC-relative address,
5272// and writes the result to the destination register.
5273bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005274EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005275{
5276#if 0
5277 // ARM pseudo code...
5278 if ConditionPassed() then
5279 EncodingSpecificOperations();
5280 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5281 if d == 15 then // Can only occur for ARM encodings
5282 ALUWritePC(result);
5283 else
5284 R[d] = result;
5285#endif
5286
5287 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005288
Greg Clayton7bc39082011-03-24 23:53:38 +00005289 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005290 {
5291 uint32_t Rd;
5292 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5293 bool add;
5294 switch (encoding)
5295 {
5296 case eEncodingT1:
5297 Rd = Bits32(opcode, 10, 8);
5298 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5299 break;
5300 case eEncodingT2:
5301 case eEncodingT3:
5302 Rd = Bits32(opcode, 11, 8);
5303 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5304 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5305 if (BadReg(Rd))
5306 return false;
5307 break;
5308 case eEncodingA1:
5309 case eEncodingA2:
5310 Rd = Bits32(opcode, 15, 12);
5311 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5312 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5313 break;
5314 default:
5315 return false;
5316 }
5317
5318 // Read the PC value.
5319 uint32_t pc = ReadCoreReg(PC_REG, &success);
5320 if (!success)
5321 return false;
5322
5323 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5324
5325 EmulateInstruction::Context context;
5326 context.type = EmulateInstruction::eContextImmediate;
5327 context.SetNoArgs ();
5328
5329 if (!WriteCoreReg(context, result, Rd))
5330 return false;
5331 }
5332 return true;
5333}
5334
Johnny Chene97c0d52011-02-18 19:32:20 +00005335// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5336// to the destination register. It can optionally update the condition flags based on the result.
5337bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005338EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005339{
5340#if 0
5341 // ARM pseudo code...
5342 if ConditionPassed() then
5343 EncodingSpecificOperations();
5344 result = R[n] AND imm32;
5345 if d == 15 then // Can only occur for ARM encoding
5346 ALUWritePC(result); // setflags is always FALSE here
5347 else
5348 R[d] = result;
5349 if setflags then
5350 APSR.N = result<31>;
5351 APSR.Z = IsZeroBit(result);
5352 APSR.C = carry;
5353 // APSR.V unchanged
5354#endif
5355
5356 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005357
Greg Clayton7bc39082011-03-24 23:53:38 +00005358 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005359 {
5360 uint32_t Rd, Rn;
5361 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5362 bool setflags;
5363 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5364 switch (encoding)
5365 {
5366 case eEncodingT1:
5367 Rd = Bits32(opcode, 11, 8);
5368 Rn = Bits32(opcode, 19, 16);
5369 setflags = BitIsSet(opcode, 20);
5370 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005371 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005372 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005373 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005374 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5375 return false;
5376 break;
5377 case eEncodingA1:
5378 Rd = Bits32(opcode, 15, 12);
5379 Rn = Bits32(opcode, 19, 16);
5380 setflags = BitIsSet(opcode, 20);
5381 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005382
Johnny Chene97c0d52011-02-18 19:32:20 +00005383 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005384 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005385 break;
5386 default:
5387 return false;
5388 }
5389
Johnny Chene97c0d52011-02-18 19:32:20 +00005390 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005391 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005392 if (!success)
5393 return false;
5394
5395 uint32_t result = val1 & imm32;
5396
5397 EmulateInstruction::Context context;
5398 context.type = EmulateInstruction::eContextImmediate;
5399 context.SetNoArgs ();
5400
5401 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5402 return false;
5403 }
5404 return true;
5405}
5406
5407// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5408// and writes the result to the destination register. It can optionally update the condition flags
5409// based on the result.
5410bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005411EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005412{
5413#if 0
5414 // ARM pseudo code...
5415 if ConditionPassed() then
5416 EncodingSpecificOperations();
5417 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5418 result = R[n] AND shifted;
5419 if d == 15 then // Can only occur for ARM encoding
5420 ALUWritePC(result); // setflags is always FALSE here
5421 else
5422 R[d] = result;
5423 if setflags then
5424 APSR.N = result<31>;
5425 APSR.Z = IsZeroBit(result);
5426 APSR.C = carry;
5427 // APSR.V unchanged
5428#endif
5429
5430 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005431
Greg Clayton7bc39082011-03-24 23:53:38 +00005432 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005433 {
5434 uint32_t Rd, Rn, Rm;
5435 ARM_ShifterType shift_t;
5436 uint32_t shift_n; // the shift applied to the value read from Rm
5437 bool setflags;
5438 uint32_t carry;
5439 switch (encoding)
5440 {
5441 case eEncodingT1:
5442 Rd = Rn = Bits32(opcode, 2, 0);
5443 Rm = Bits32(opcode, 5, 3);
5444 setflags = !InITBlock();
5445 shift_t = SRType_LSL;
5446 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005447 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005448 case eEncodingT2:
5449 Rd = Bits32(opcode, 11, 8);
5450 Rn = Bits32(opcode, 19, 16);
5451 Rm = Bits32(opcode, 3, 0);
5452 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005453 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005454 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005455 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005456 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005457 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5458 return false;
5459 break;
5460 case eEncodingA1:
5461 Rd = Bits32(opcode, 15, 12);
5462 Rn = Bits32(opcode, 19, 16);
5463 Rm = Bits32(opcode, 3, 0);
5464 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005465 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005466
Johnny Chene97c0d52011-02-18 19:32:20 +00005467 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005468 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005469 break;
5470 default:
5471 return false;
5472 }
5473
Johnny Chene97c0d52011-02-18 19:32:20 +00005474 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005475 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005476 if (!success)
5477 return false;
5478
5479 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005480 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005481 if (!success)
5482 return false;
5483
5484 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5485 uint32_t result = val1 & shifted;
5486
5487 EmulateInstruction::Context context;
5488 context.type = EmulateInstruction::eContextImmediate;
5489 context.SetNoArgs ();
5490
5491 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5492 return false;
5493 }
5494 return true;
5495}
5496
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005497// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5498// immediate value, and writes the result to the destination register. It can optionally update the
5499// condition flags based on the result.
5500bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005501EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005502{
5503#if 0
5504 // ARM pseudo code...
5505 if ConditionPassed() then
5506 EncodingSpecificOperations();
5507 result = R[n] AND NOT(imm32);
5508 if d == 15 then // Can only occur for ARM encoding
5509 ALUWritePC(result); // setflags is always FALSE here
5510 else
5511 R[d] = result;
5512 if setflags then
5513 APSR.N = result<31>;
5514 APSR.Z = IsZeroBit(result);
5515 APSR.C = carry;
5516 // APSR.V unchanged
5517#endif
5518
5519 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005520
Greg Clayton7bc39082011-03-24 23:53:38 +00005521 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005522 {
5523 uint32_t Rd, Rn;
5524 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5525 bool setflags;
5526 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5527 switch (encoding)
5528 {
5529 case eEncodingT1:
5530 Rd = Bits32(opcode, 11, 8);
5531 Rn = Bits32(opcode, 19, 16);
5532 setflags = BitIsSet(opcode, 20);
5533 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5534 if (BadReg(Rd) || BadReg(Rn))
5535 return false;
5536 break;
5537 case eEncodingA1:
5538 Rd = Bits32(opcode, 15, 12);
5539 Rn = Bits32(opcode, 19, 16);
5540 setflags = BitIsSet(opcode, 20);
5541 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005542
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005543 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005544 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005545 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005546 break;
5547 default:
5548 return false;
5549 }
5550
5551 // Read the first operand.
5552 uint32_t val1 = ReadCoreReg(Rn, &success);
5553 if (!success)
5554 return false;
5555
5556 uint32_t result = val1 & ~imm32;
5557
5558 EmulateInstruction::Context context;
5559 context.type = EmulateInstruction::eContextImmediate;
5560 context.SetNoArgs ();
5561
5562 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5563 return false;
5564 }
5565 return true;
5566}
5567
5568// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5569// optionally-shifted register value, and writes the result to the destination register.
5570// It can optionally update the condition flags based on the result.
5571bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005572EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005573{
5574#if 0
5575 // ARM pseudo code...
5576 if ConditionPassed() then
5577 EncodingSpecificOperations();
5578 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5579 result = R[n] AND NOT(shifted);
5580 if d == 15 then // Can only occur for ARM encoding
5581 ALUWritePC(result); // setflags is always FALSE here
5582 else
5583 R[d] = result;
5584 if setflags then
5585 APSR.N = result<31>;
5586 APSR.Z = IsZeroBit(result);
5587 APSR.C = carry;
5588 // APSR.V unchanged
5589#endif
5590
5591 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005592
Greg Clayton7bc39082011-03-24 23:53:38 +00005593 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005594 {
5595 uint32_t Rd, Rn, Rm;
5596 ARM_ShifterType shift_t;
5597 uint32_t shift_n; // the shift applied to the value read from Rm
5598 bool setflags;
5599 uint32_t carry;
5600 switch (encoding)
5601 {
5602 case eEncodingT1:
5603 Rd = Rn = Bits32(opcode, 2, 0);
5604 Rm = Bits32(opcode, 5, 3);
5605 setflags = !InITBlock();
5606 shift_t = SRType_LSL;
5607 shift_n = 0;
5608 break;
5609 case eEncodingT2:
5610 Rd = Bits32(opcode, 11, 8);
5611 Rn = Bits32(opcode, 19, 16);
5612 Rm = Bits32(opcode, 3, 0);
5613 setflags = BitIsSet(opcode, 20);
5614 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5615 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5616 return false;
5617 break;
5618 case eEncodingA1:
5619 Rd = Bits32(opcode, 15, 12);
5620 Rn = Bits32(opcode, 19, 16);
5621 Rm = Bits32(opcode, 3, 0);
5622 setflags = BitIsSet(opcode, 20);
5623 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005624
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005625 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005626 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005627 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005628 break;
5629 default:
5630 return false;
5631 }
5632
5633 // Read the first operand.
5634 uint32_t val1 = ReadCoreReg(Rn, &success);
5635 if (!success)
5636 return false;
5637
5638 // Read the second operand.
5639 uint32_t val2 = ReadCoreReg(Rm, &success);
5640 if (!success)
5641 return false;
5642
5643 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5644 uint32_t result = val1 & ~shifted;
5645
5646 EmulateInstruction::Context context;
5647 context.type = EmulateInstruction::eContextImmediate;
5648 context.SetNoArgs ();
5649
5650 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5651 return false;
5652 }
5653 return true;
5654}
5655
Caroline Tice4d729c52011-02-18 00:55:53 +00005656// 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 +00005657// 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 +00005658bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005659EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005660{
5661#if 0
5662 if ConditionPassed() then
5663 EncodingSpecificOperations();
5664 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5665 address = if index then offset_addr else R[n];
5666 data = MemU[address,4];
5667 if wback then R[n] = offset_addr;
5668 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005669 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5670 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005671 R[t] = data;
5672 else // Can only apply before ARMv7
5673 R[t] = ROR(data, 8*UInt(address<1:0>));
5674#endif
5675
5676 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005677
Greg Clayton7bc39082011-03-24 23:53:38 +00005678 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005679 {
5680 const uint32_t addr_byte_size = GetAddressByteSize();
5681
5682 uint32_t t;
5683 uint32_t n;
5684 uint32_t imm32;
5685 bool index;
5686 bool add;
5687 bool wback;
5688
5689 switch (encoding)
5690 {
5691 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005692 // if Rn == '1111' then SEE LDR (literal);
5693 // if P == '0' && W == '1' then SEE LDRT;
5694 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005695 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5696 t = Bits32 (opcode, 15, 12);
5697 n = Bits32 (opcode, 19, 16);
5698 imm32 = Bits32 (opcode, 11, 0);
5699
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005700 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5701 index = BitIsSet (opcode, 24);
5702 add = BitIsSet (opcode, 23);
5703 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005704
5705 // if wback && n == t then UNPREDICTABLE;
5706 if (wback && (n == t))
5707 return false;
5708
5709 break;
5710
5711 default:
5712 return false;
5713 }
5714
5715 addr_t address;
5716 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005717 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005718 if (!success)
5719 return false;
5720
5721 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5722 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005723 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005724 else
5725 offset_addr = base_address - imm32;
5726
5727 // address = if index then offset_addr else R[n];
5728 if (index)
5729 address = offset_addr;
5730 else
5731 address = base_address;
5732
5733 // data = MemU[address,4];
5734
Greg Claytonc07d4512011-04-26 23:48:45 +00005735 RegisterInfo base_reg;
5736 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4d729c52011-02-18 00:55:53 +00005737
5738 EmulateInstruction::Context context;
5739 context.type = eContextRegisterLoad;
5740 context.SetRegisterPlusOffset (base_reg, address - base_address);
5741
5742 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5743 if (!success)
5744 return false;
5745
5746 // if wback then R[n] = offset_addr;
5747 if (wback)
5748 {
5749 context.type = eContextAdjustBaseRegister;
5750 context.SetAddress (offset_addr);
5751 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5752 return false;
5753 }
5754
5755 // if t == 15 then
5756 if (t == 15)
5757 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005758 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005759 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5760 {
5761 // LoadWritePC (data);
5762 context.type = eContextRegisterLoad;
5763 context.SetRegisterPlusOffset (base_reg, address - base_address);
5764 LoadWritePC (context, data);
5765 }
5766 else
5767 return false;
5768 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005769 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005770 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5771 {
5772 // R[t] = data;
5773 context.type = eContextRegisterLoad;
5774 context.SetRegisterPlusOffset (base_reg, address - base_address);
5775 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5776 return false;
5777 }
5778 // else // Can only apply before ARMv7
5779 else
5780 {
5781 // R[t] = ROR(data, 8*UInt(address<1:0>));
5782 data = ROR (data, Bits32 (address, 1, 0));
5783 context.type = eContextRegisterLoad;
5784 context.SetImmediate (data);
5785 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5786 return false;
5787 }
5788
5789 }
5790 return true;
5791}
5792
Caroline Ticefe479112011-02-18 18:52:37 +00005793// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5794// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5795bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005796EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005797{
5798#if 0
5799 if ConditionPassed() then
5800 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5801 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5802 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5803 address = if index then offset_addr else R[n];
5804 data = MemU[address,4];
5805 if wback then R[n] = offset_addr;
5806 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005807 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5808 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005809 R[t] = data;
5810 else // Can only apply before ARMv7
5811 if CurrentInstrSet() == InstrSet_ARM then
5812 R[t] = ROR(data, 8*UInt(address<1:0>));
5813 else
5814 R[t] = bits(32) UNKNOWN;
5815#endif
5816
5817 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005818
Greg Clayton7bc39082011-03-24 23:53:38 +00005819 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005820 {
5821 const uint32_t addr_byte_size = GetAddressByteSize();
5822
5823 uint32_t t;
5824 uint32_t n;
5825 uint32_t m;
5826 bool index;
5827 bool add;
5828 bool wback;
5829 ARM_ShifterType shift_t;
5830 uint32_t shift_n;
5831
5832 switch (encoding)
5833 {
5834 case eEncodingT1:
5835 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5836 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5837 t = Bits32 (opcode, 2, 0);
5838 n = Bits32 (opcode, 5, 3);
5839 m = Bits32 (opcode, 8, 6);
5840
5841 // index = TRUE; add = TRUE; wback = FALSE;
5842 index = true;
5843 add = true;
5844 wback = false;
5845
5846 // (shift_t, shift_n) = (SRType_LSL, 0);
5847 shift_t = SRType_LSL;
5848 shift_n = 0;
5849
5850 break;
5851
5852 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005853 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005854 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5855 t = Bits32 (opcode, 15, 12);
5856 n = Bits32 (opcode, 19, 16);
5857 m = Bits32 (opcode, 3, 0);
5858
5859 // index = TRUE; add = TRUE; wback = FALSE;
5860 index = true;
5861 add = true;
5862 wback = false;
5863
5864 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5865 shift_t = SRType_LSL;
5866 shift_n = Bits32 (opcode, 5, 4);
5867
5868 // if BadReg(m) then UNPREDICTABLE;
5869 if (BadReg (m))
5870 return false;
5871
5872 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5873 if ((t == 15) && InITBlock() && !LastInITBlock())
5874 return false;
5875
5876 break;
5877
5878 case eEncodingA1:
5879 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005880 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005881 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5882 t = Bits32 (opcode, 15, 12);
5883 n = Bits32 (opcode, 19, 16);
5884 m = Bits32 (opcode, 3, 0);
5885
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005886 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005887 index = BitIsSet (opcode, 24);
5888 add = BitIsSet (opcode, 23);
5889 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5890
5891 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5892 uint32_t type = Bits32 (opcode, 6, 5);
5893 uint32_t imm5 = Bits32 (opcode, 11, 7);
5894 shift_n = DecodeImmShift (type, imm5, shift_t);
5895
5896 // if m == 15 then UNPREDICTABLE;
5897 if (m == 15)
5898 return false;
5899
5900 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5901 if (wback && ((n == 15) || (n == t)))
5902 return false;
5903 }
5904 break;
5905
5906
5907 default:
5908 return false;
5909 }
5910
5911 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5912 if (!success)
5913 return false;
5914
5915 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5916 if (!success)
5917 return false;
5918
5919 addr_t offset_addr;
5920 addr_t address;
5921
5922 // 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 +00005923 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005924
5925 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5926 if (add)
5927 offset_addr = Rn + offset;
5928 else
5929 offset_addr = Rn - offset;
5930
5931 // address = if index then offset_addr else R[n];
5932 if (index)
5933 address = offset_addr;
5934 else
5935 address = Rn;
5936
5937 // data = MemU[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +00005938 RegisterInfo base_reg;
5939 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefe479112011-02-18 18:52:37 +00005940
5941 EmulateInstruction::Context context;
5942 context.type = eContextRegisterLoad;
5943 context.SetRegisterPlusOffset (base_reg, address - Rn);
5944
5945 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5946 if (!success)
5947 return false;
5948
5949 // if wback then R[n] = offset_addr;
5950 if (wback)
5951 {
5952 context.type = eContextAdjustBaseRegister;
5953 context.SetAddress (offset_addr);
5954 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5955 return false;
5956 }
5957
5958 // if t == 15 then
5959 if (t == 15)
5960 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005961 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005962 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5963 {
5964 context.type = eContextRegisterLoad;
5965 context.SetRegisterPlusOffset (base_reg, address - Rn);
5966 LoadWritePC (context, data);
5967 }
5968 else
5969 return false;
5970 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005971 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005972 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5973 {
5974 // R[t] = data;
5975 context.type = eContextRegisterLoad;
5976 context.SetRegisterPlusOffset (base_reg, address - Rn);
5977 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5978 return false;
5979 }
5980 else // Can only apply before ARMv7
5981 {
5982 // if CurrentInstrSet() == InstrSet_ARM then
5983 if (CurrentInstrSet () == eModeARM)
5984 {
5985 // R[t] = ROR(data, 8*UInt(address<1:0>));
5986 data = ROR (data, Bits32 (address, 1, 0));
5987 context.type = eContextRegisterLoad;
5988 context.SetImmediate (data);
5989 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5990 return false;
5991 }
5992 else
5993 {
5994 // R[t] = bits(32) UNKNOWN;
5995 WriteBits32Unknown (t);
5996 }
5997 }
5998 }
5999 return true;
6000}
Caroline Tice21b604b2011-02-18 21:06:04 +00006001
6002// LDRB (immediate, Thumb)
6003bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006004EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00006005{
6006#if 0
6007 if ConditionPassed() then
6008 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6009 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6010 address = if index then offset_addr else R[n];
6011 R[t] = ZeroExtend(MemU[address,1], 32);
6012 if wback then R[n] = offset_addr;
6013#endif
6014
6015 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00006016
Greg Clayton7bc39082011-03-24 23:53:38 +00006017 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00006018 {
6019 uint32_t t;
6020 uint32_t n;
6021 uint32_t imm32;
6022 bool index;
6023 bool add;
6024 bool wback;
6025
6026 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6027 switch (encoding)
6028 {
6029 case eEncodingT1:
6030 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6031 t = Bits32 (opcode, 2, 0);
6032 n = Bits32 (opcode, 5, 3);
6033 imm32 = Bits32 (opcode, 10, 6);
6034
6035 // index = TRUE; add = TRUE; wback = FALSE;
6036 index = true;
6037 add = true;
6038 wback= false;
6039
6040 break;
6041
6042 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006043 // if Rt == '1111' then SEE PLD;
6044 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006045 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6046 t = Bits32 (opcode, 15, 12);
6047 n = Bits32 (opcode, 19, 16);
6048 imm32 = Bits32 (opcode, 11, 0);
6049
6050 // index = TRUE; add = TRUE; wback = FALSE;
6051 index = true;
6052 add = true;
6053 wback = false;
6054
6055 // if t == 13 then UNPREDICTABLE;
6056 if (t == 13)
6057 return false;
6058
6059 break;
6060
6061 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006062 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6063 // if Rn == '1111' then SEE LDRB (literal);
6064 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6065 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006066 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6067 return false;
6068
6069 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6070 t = Bits32 (opcode, 15, 12);
6071 n = Bits32 (opcode, 19, 16);
6072 imm32 = Bits32 (opcode, 7, 0);
6073
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006074 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006075 index = BitIsSet (opcode, 10);
6076 add = BitIsSet (opcode, 9);
6077 wback = BitIsSet (opcode, 8);
6078
6079 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6080 if (BadReg (t) || (wback && (n == t)))
6081 return false;
6082
6083 break;
6084
6085 default:
6086 return false;
6087 }
6088
6089 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6090 if (!success)
6091 return false;
6092
6093 addr_t address;
6094 addr_t offset_addr;
6095
6096 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6097 if (add)
6098 offset_addr = Rn + imm32;
6099 else
6100 offset_addr = Rn - imm32;
6101
6102 // address = if index then offset_addr else R[n];
6103 if (index)
6104 address = offset_addr;
6105 else
6106 address = Rn;
6107
6108 // R[t] = ZeroExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006109 RegisterInfo base_reg;
6110 RegisterInfo data_reg;
6111 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6112 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice21b604b2011-02-18 21:06:04 +00006113
6114 EmulateInstruction::Context context;
6115 context.type = eContextRegisterLoad;
6116 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6117
6118 uint64_t data = MemURead (context, address, 1, 0, &success);
6119 if (!success)
6120 return false;
6121
6122 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6123 return false;
6124
6125 // if wback then R[n] = offset_addr;
6126 if (wback)
6127 {
6128 context.type = eContextAdjustBaseRegister;
6129 context.SetAddress (offset_addr);
6130 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6131 return false;
6132 }
6133 }
6134 return true;
6135}
Caroline Ticef55261f2011-02-18 22:24:22 +00006136
6137// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6138// zero-extends it to form a 32-bit word and writes it to a register.
6139bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006140EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006141{
6142#if 0
6143 if ConditionPassed() then
6144 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6145 base = Align(PC,4);
6146 address = if add then (base + imm32) else (base - imm32);
6147 R[t] = ZeroExtend(MemU[address,1], 32);
6148#endif
6149
6150 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006151
Greg Clayton7bc39082011-03-24 23:53:38 +00006152 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006153 {
6154 uint32_t t;
6155 uint32_t imm32;
6156 bool add;
6157 switch (encoding)
6158 {
6159 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006160 // if Rt == '1111' then SEE PLD;
6161 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006162 t = Bits32 (opcode, 15, 12);
6163 imm32 = Bits32 (opcode, 11, 0);
6164 add = BitIsSet (opcode, 23);
6165
6166 // if t == 13 then UNPREDICTABLE;
6167 if (t == 13)
6168 return false;
6169
6170 break;
6171
6172 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006173 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006174 t = Bits32 (opcode, 15, 12);
6175 imm32 = Bits32 (opcode, 11, 0);
6176 add = BitIsSet (opcode, 23);
6177
6178 // if t == 15 then UNPREDICTABLE;
6179 if (t == 15)
6180 return false;
6181 break;
6182
6183 default:
6184 return false;
6185 }
6186
6187 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006188 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006189 if (!success)
6190 return false;
6191
6192 uint32_t base = AlignPC (pc_val);
6193
6194 addr_t address;
6195 // address = if add then (base + imm32) else (base - imm32);
6196 if (add)
6197 address = base + imm32;
6198 else
6199 address = base - imm32;
6200
6201 // R[t] = ZeroExtend(MemU[address,1], 32);
6202 EmulateInstruction::Context context;
6203 context.type = eContextRelativeBranchImmediate;
6204 context.SetImmediate (address - base);
6205
6206 uint64_t data = MemURead (context, address, 1, 0, &success);
6207 if (!success)
6208 return false;
6209
6210 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6211 return false;
6212 }
6213 return true;
6214}
Caroline Tice30fec122011-02-18 23:52:21 +00006215
6216// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6217// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6218// optionally be shifted.
6219bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006220EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006221{
6222#if 0
6223 if ConditionPassed() then
6224 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6225 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6226 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6227 address = if index then offset_addr else R[n];
6228 R[t] = ZeroExtend(MemU[address,1],32);
6229 if wback then R[n] = offset_addr;
6230#endif
6231
6232 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006233
Greg Clayton7bc39082011-03-24 23:53:38 +00006234 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006235 {
6236 uint32_t t;
6237 uint32_t n;
6238 uint32_t m;
6239 bool index;
6240 bool add;
6241 bool wback;
6242 ARM_ShifterType shift_t;
6243 uint32_t shift_n;
6244
6245 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6246 switch (encoding)
6247 {
6248 case eEncodingT1:
6249 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6250 t = Bits32 (opcode, 2, 0);
6251 n = Bits32 (opcode, 5, 3);
6252 m = Bits32 (opcode, 8, 6);
6253
6254 // index = TRUE; add = TRUE; wback = FALSE;
6255 index = true;
6256 add = true;
6257 wback = false;
6258
6259 // (shift_t, shift_n) = (SRType_LSL, 0);
6260 shift_t = SRType_LSL;
6261 shift_n = 0;
6262 break;
6263
6264 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006265 // if Rt == '1111' then SEE PLD;
6266 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006267 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6268 t = Bits32 (opcode, 15, 12);
6269 n = Bits32 (opcode, 19, 16);
6270 m = Bits32 (opcode, 3, 0);
6271
6272 // index = TRUE; add = TRUE; wback = FALSE;
6273 index = true;
6274 add = true;
6275 wback = false;
6276
6277 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6278 shift_t = SRType_LSL;
6279 shift_n = Bits32 (opcode, 5, 4);
6280
6281 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6282 if ((t == 13) || BadReg (m))
6283 return false;
6284 break;
6285
6286 case eEncodingA1:
6287 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006288 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006289 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6290 t = Bits32 (opcode, 15, 12);
6291 n = Bits32 (opcode, 19, 16);
6292 m = Bits32 (opcode, 3, 0);
6293
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006294 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006295 index = BitIsSet (opcode, 24);
6296 add = BitIsSet (opcode, 23);
6297 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6298
6299 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6300 uint32_t type = Bits32 (opcode, 6, 5);
6301 uint32_t imm5 = Bits32 (opcode, 11, 7);
6302 shift_n = DecodeImmShift (type, imm5, shift_t);
6303
6304 // if t == 15 || m == 15 then UNPREDICTABLE;
6305 if ((t == 15) || (m == 15))
6306 return false;
6307
6308 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6309 if (wback && ((n == 15) || (n == t)))
6310 return false;
6311 }
6312 break;
6313
6314 default:
6315 return false;
6316 }
6317
6318 addr_t offset_addr;
6319 addr_t address;
6320
6321 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6322 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6323 if (!success)
6324 return false;
6325
6326 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6327
6328 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6329 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6330 if (!success)
6331 return false;
6332
6333 if (add)
6334 offset_addr = Rn + offset;
6335 else
6336 offset_addr = Rn - offset;
6337
6338 // address = if index then offset_addr else R[n];
6339 if (index)
6340 address = offset_addr;
6341 else
6342 address = Rn;
6343
6344 // R[t] = ZeroExtend(MemU[address,1],32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006345 RegisterInfo base_reg;
6346 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice30fec122011-02-18 23:52:21 +00006347
6348 EmulateInstruction::Context context;
6349 context.type = eContextRegisterLoad;
6350 context.SetRegisterPlusOffset (base_reg, address - Rn);
6351
6352 uint64_t data = MemURead (context, address, 1, 0, &success);
6353 if (!success)
6354 return false;
6355
6356 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6357 return false;
6358
6359 // if wback then R[n] = offset_addr;
6360 if (wback)
6361 {
6362 context.type = eContextAdjustBaseRegister;
6363 context.SetAddress (offset_addr);
6364 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6365 return false;
6366 }
6367 }
6368 return true;
6369}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006370
6371// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6372// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6373// post-indexed, or pre-indexed addressing.
6374bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006375EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006376{
6377#if 0
6378 if ConditionPassed() then
6379 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6380 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6381 address = if index then offset_addr else R[n];
6382 data = MemU[address,2];
6383 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006384 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006385 R[t] = ZeroExtend(data, 32);
6386 else // Can only apply before ARMv7
6387 R[t] = bits(32) UNKNOWN;
6388#endif
6389
6390
6391 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006392
Greg Clayton7bc39082011-03-24 23:53:38 +00006393 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006394 {
6395 uint32_t t;
6396 uint32_t n;
6397 uint32_t imm32;
6398 bool index;
6399 bool add;
6400 bool wback;
6401
6402 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6403 switch (encoding)
6404 {
6405 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006406 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006407 t = Bits32 (opcode, 2, 0);
6408 n = Bits32 (opcode, 5, 3);
6409 imm32 = Bits32 (opcode, 10, 6) << 1;
6410
6411 // index = TRUE; add = TRUE; wback = FALSE;
6412 index = true;
6413 add = true;
6414 wback = false;
6415
6416 break;
6417
6418 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006419 // if Rt == '1111' then SEE "Unallocated memory hints";
6420 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006421 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6422 t = Bits32 (opcode, 15, 12);
6423 n = Bits32 (opcode, 19, 16);
6424 imm32 = Bits32 (opcode, 11, 0);
6425
6426 // index = TRUE; add = TRUE; wback = FALSE;
6427 index = true;
6428 add = true;
6429 wback = false;
6430
6431 // if t == 13 then UNPREDICTABLE;
6432 if (t == 13)
6433 return false;
6434 break;
6435
6436 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006437 // if Rn == '1111' then SEE LDRH (literal);
6438 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6439 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6440 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006441 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6442 return false;
6443
6444 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6445 t = Bits32 (opcode, 15, 12);
6446 n = Bits32 (opcode, 19, 16);
6447 imm32 = Bits32 (opcode, 7, 0);
6448
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006449 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006450 index = BitIsSet (opcode, 10);
6451 add = BitIsSet (opcode, 9);
6452 wback = BitIsSet (opcode, 8);
6453
6454 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6455 if (BadReg (t) || (wback && (n == t)))
6456 return false;
6457 break;
6458
6459 default:
6460 return false;
6461 }
6462
6463 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6464 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6465 if (!success)
6466 return false;
6467
6468 addr_t offset_addr;
6469 addr_t address;
6470
6471 if (add)
6472 offset_addr = Rn + imm32;
6473 else
6474 offset_addr = Rn - imm32;
6475
6476 // address = if index then offset_addr else R[n];
6477 if (index)
6478 address = offset_addr;
6479 else
6480 address = Rn;
6481
6482 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006483 RegisterInfo base_reg;
6484 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006485
6486 EmulateInstruction::Context context;
6487 context.type = eContextRegisterLoad;
6488 context.SetRegisterPlusOffset (base_reg, address - Rn);
6489
6490 uint64_t data = MemURead (context, address, 2, 0, &success);
6491 if (!success)
6492 return false;
6493
6494 // if wback then R[n] = offset_addr;
6495 if (wback)
6496 {
6497 context.type = eContextAdjustBaseRegister;
6498 context.SetAddress (offset_addr);
6499 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6500 return false;
6501 }
6502
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006503 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006504 if (UnalignedSupport () || BitIsClear (address, 0))
6505 {
6506 // R[t] = ZeroExtend(data, 32);
6507 context.type = eContextRegisterLoad;
6508 context.SetRegisterPlusOffset (base_reg, address - Rn);
6509 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6510 return false;
6511 }
6512 else // Can only apply before ARMv7
6513 {
6514 // R[t] = bits(32) UNKNOWN;
6515 WriteBits32Unknown (t);
6516 }
6517 }
6518 return true;
6519}
Caroline Ticefe479112011-02-18 18:52:37 +00006520
Caroline Tice952b5382011-02-28 23:15:24 +00006521// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6522// zero-extends it to form a 32-bit word, and writes it to a register.
6523bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006524EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006525{
6526#if 0
6527 if ConditionPassed() then
6528 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6529 base = Align(PC,4);
6530 address = if add then (base + imm32) else (base - imm32);
6531 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006532 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006533 R[t] = ZeroExtend(data, 32);
6534 else // Can only apply before ARMv7
6535 R[t] = bits(32) UNKNOWN;
6536#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006537
Caroline Tice952b5382011-02-28 23:15:24 +00006538 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006539
Greg Clayton7bc39082011-03-24 23:53:38 +00006540 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006541 {
6542 uint32_t t;
6543 uint32_t imm32;
6544 bool add;
6545
6546 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6547 switch (encoding)
6548 {
6549 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006550 // if Rt == '1111' then SEE "Unallocated memory hints";
6551 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006552 t = Bits32 (opcode, 15, 12);
6553 imm32 = Bits32 (opcode, 11, 0);
6554 add = BitIsSet (opcode, 23);
6555
6556 // if t == 13 then UNPREDICTABLE;
6557 if (t == 13)
6558 return false;
6559
6560 break;
6561
6562 case eEncodingA1:
6563 {
6564 uint32_t imm4H = Bits32 (opcode, 11, 8);
6565 uint32_t imm4L = Bits32 (opcode, 3, 0);
6566
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006567 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006568 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006569 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006570 add = BitIsSet (opcode, 23);
6571
6572 // if t == 15 then UNPREDICTABLE;
6573 if (t == 15)
6574 return false;
6575 break;
6576 }
6577
6578 default:
6579 return false;
6580 }
6581
6582 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006583 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006584 if (!success)
6585 return false;
6586
6587 addr_t base = AlignPC (pc_value);
6588 addr_t address;
6589
6590 // address = if add then (base + imm32) else (base - imm32);
6591 if (add)
6592 address = base + imm32;
6593 else
6594 address = base - imm32;
6595
6596 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006597 RegisterInfo base_reg;
6598 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice952b5382011-02-28 23:15:24 +00006599
6600 EmulateInstruction::Context context;
6601 context.type = eContextRegisterLoad;
6602 context.SetRegisterPlusOffset (base_reg, address - base);
6603
6604 uint64_t data = MemURead (context, address, 2, 0, &success);
6605 if (!success)
6606 return false;
6607
6608
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006609 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006610 if (UnalignedSupport () || BitIsClear (address, 0))
6611 {
6612 // R[t] = ZeroExtend(data, 32);
6613 context.type = eContextRegisterLoad;
6614 context.SetRegisterPlusOffset (base_reg, address - base);
6615 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6616 return false;
6617
6618 }
6619 else // Can only apply before ARMv7
6620 {
6621 // R[t] = bits(32) UNKNOWN;
6622 WriteBits32Unknown (t);
6623 }
6624 }
6625 return true;
6626}
6627
Caroline Tice0e6bc952011-03-01 18:00:42 +00006628// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6629// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6630// be shifted left by 0, 1, 2, or 3 bits.
6631bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006632EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006633{
6634#if 0
6635 if ConditionPassed() then
6636 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6637 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6638 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6639 address = if index then offset_addr else R[n];
6640 data = MemU[address,2];
6641 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006642 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006643 R[t] = ZeroExtend(data, 32);
6644 else // Can only apply before ARMv7
6645 R[t] = bits(32) UNKNOWN;
6646#endif
6647
6648 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006649
Greg Clayton7bc39082011-03-24 23:53:38 +00006650 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006651 {
6652 uint32_t t;
6653 uint32_t n;
6654 uint32_t m;
6655 bool index;
6656 bool add;
6657 bool wback;
6658 ARM_ShifterType shift_t;
6659 uint32_t shift_n;
6660
6661 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6662 switch (encoding)
6663 {
6664 case eEncodingT1:
6665 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6666 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6667 t = Bits32 (opcode, 2, 0);
6668 n = Bits32 (opcode, 5, 3);
6669 m = Bits32 (opcode, 8, 6);
6670
6671 // index = TRUE; add = TRUE; wback = FALSE;
6672 index = true;
6673 add = true;
6674 wback = false;
6675
6676 // (shift_t, shift_n) = (SRType_LSL, 0);
6677 shift_t = SRType_LSL;
6678 shift_n = 0;
6679
6680 break;
6681
6682 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006683 // if Rn == '1111' then SEE LDRH (literal);
6684 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006685 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6686 t = Bits32 (opcode, 15, 12);
6687 n = Bits32 (opcode, 19, 16);
6688 m = Bits32 (opcode, 3, 0);
6689
6690 // index = TRUE; add = TRUE; wback = FALSE;
6691 index = true;
6692 add = true;
6693 wback = false;
6694
6695 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6696 shift_t = SRType_LSL;
6697 shift_n = Bits32 (opcode, 5, 4);
6698
6699 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6700 if ((t == 13) || BadReg (m))
6701 return false;
6702 break;
6703
6704 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006705 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006706 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6707 t = Bits32 (opcode, 15, 12);
6708 n = Bits32 (opcode, 19, 16);
6709 m = Bits32 (opcode, 3, 0);
6710
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006711 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006712 index = BitIsSet (opcode, 24);
6713 add = BitIsSet (opcode, 23);
6714 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6715
6716 // (shift_t, shift_n) = (SRType_LSL, 0);
6717 shift_t = SRType_LSL;
6718 shift_n = 0;
6719
6720 // if t == 15 || m == 15 then UNPREDICTABLE;
6721 if ((t == 15) || (m == 15))
6722 return false;
6723
6724 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6725 if (wback && ((n == 15) || (n == t)))
6726 return false;
6727
6728 break;
6729
6730 default:
6731 return false;
6732 }
6733
6734 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6735
6736 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6737 if (!success)
6738 return false;
6739
6740 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6741
6742 addr_t offset_addr;
6743 addr_t address;
6744
6745 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6746 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6747 if (!success)
6748 return false;
6749
6750 if (add)
6751 offset_addr = Rn + offset;
6752 else
6753 offset_addr = Rn - offset;
6754
6755 // address = if index then offset_addr else R[n];
6756 if (index)
6757 address = offset_addr;
6758 else
6759 address = Rn;
6760
6761 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006762 RegisterInfo base_reg;
6763 RegisterInfo offset_reg;
6764 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6765 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice0e6bc952011-03-01 18:00:42 +00006766
6767 EmulateInstruction::Context context;
6768 context.type = eContextRegisterLoad;
6769 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6770 uint64_t data = MemURead (context, address, 2, 0, &success);
6771 if (!success)
6772 return false;
6773
6774 // if wback then R[n] = offset_addr;
6775 if (wback)
6776 {
6777 context.type = eContextAdjustBaseRegister;
6778 context.SetAddress (offset_addr);
6779 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6780 return false;
6781 }
6782
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006783 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006784 if (UnalignedSupport() || BitIsClear (address, 0))
6785 {
6786 // R[t] = ZeroExtend(data, 32);
6787 context.type = eContextRegisterLoad;
6788 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6789 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6790 return false;
6791 }
6792 else // Can only apply before ARMv7
6793 {
6794 // R[t] = bits(32) UNKNOWN;
6795 WriteBits32Unknown (t);
6796 }
6797 }
6798 return true;
6799}
6800
Caroline Ticea5e28af2011-03-01 21:53:03 +00006801// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6802// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6803// or pre-indexed addressing.
6804bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006805EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006806{
6807#if 0
6808 if ConditionPassed() then
6809 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6810 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6811 address = if index then offset_addr else R[n];
6812 R[t] = SignExtend(MemU[address,1], 32);
6813 if wback then R[n] = offset_addr;
6814#endif
6815
6816 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006817
Greg Clayton7bc39082011-03-24 23:53:38 +00006818 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006819 {
6820 uint32_t t;
6821 uint32_t n;
6822 uint32_t imm32;
6823 bool index;
6824 bool add;
6825 bool wback;
6826
6827 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6828 switch (encoding)
6829 {
6830 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006831 // if Rt == '1111' then SEE PLI;
6832 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006833 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6834 t = Bits32 (opcode, 15, 12);
6835 n = Bits32 (opcode, 19, 16);
6836 imm32 = Bits32 (opcode, 11, 0);
6837
6838 // index = TRUE; add = TRUE; wback = FALSE;
6839 index = true;
6840 add = true;
6841 wback = false;
6842
6843 // if t == 13 then UNPREDICTABLE;
6844 if (t == 13)
6845 return false;
6846
6847 break;
6848
6849 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006850 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6851 // if Rn == '1111' then SEE LDRSB (literal);
6852 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6853 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006854 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6855 return false;
6856
6857 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6858 t = Bits32 (opcode, 15, 12);
6859 n = Bits32 (opcode, 19, 16);
6860 imm32 = Bits32 (opcode, 7, 0);
6861
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006862 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006863 index = BitIsSet (opcode, 10);
6864 add = BitIsSet (opcode, 9);
6865 wback = BitIsSet (opcode, 8);
6866
6867 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006868 if (((t == 13) || ((t == 15)
6869 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6870 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006871 return false;
6872
6873 break;
6874
6875 case eEncodingA1:
6876 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006877 // if Rn == '1111' then SEE LDRSB (literal);
6878 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006879 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6880 t = Bits32 (opcode, 15, 12);
6881 n = Bits32 (opcode, 19, 16);
6882
6883 uint32_t imm4H = Bits32 (opcode, 11, 8);
6884 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006885 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006886
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006887 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006888 index = BitIsSet (opcode, 24);
6889 add = BitIsSet (opcode, 23);
6890 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6891
6892 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6893 if ((t == 15) || (wback && (n == t)))
6894 return false;
6895
6896 break;
6897 }
6898
6899 default:
6900 return false;
6901 }
6902
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006903 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006904 if (!success)
6905 return false;
6906
6907 addr_t offset_addr;
6908 addr_t address;
6909
6910 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6911 if (add)
6912 offset_addr = Rn + imm32;
6913 else
6914 offset_addr = Rn - imm32;
6915
6916 // address = if index then offset_addr else R[n];
6917 if (index)
6918 address = offset_addr;
6919 else
6920 address = Rn;
6921
6922 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006923 RegisterInfo base_reg;
6924 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006925
6926 EmulateInstruction::Context context;
6927 context.type = eContextRegisterLoad;
6928 context.SetRegisterPlusOffset (base_reg, address - Rn);
6929
6930 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6931 if (!success)
6932 return false;
6933
6934 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6936 return false;
6937
6938 // if wback then R[n] = offset_addr;
6939 if (wback)
6940 {
6941 context.type = eContextAdjustBaseRegister;
6942 context.SetAddress (offset_addr);
6943 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6944 return false;
6945 }
6946 }
6947
6948 return true;
6949}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006950
Caroline Tice5f593912011-03-01 22:25:17 +00006951// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6952// sign-extends it to form a 32-bit word, and writes tit to a register.
6953bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006954EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006955{
6956#if 0
6957 if ConditionPassed() then
6958 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6959 base = Align(PC,4);
6960 address = if add then (base + imm32) else (base - imm32);
6961 R[t] = SignExtend(MemU[address,1], 32);
6962#endif
6963
6964 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006965
Greg Clayton7bc39082011-03-24 23:53:38 +00006966 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006967 {
6968 uint32_t t;
6969 uint32_t imm32;
6970 bool add;
6971
6972 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6973 switch (encoding)
6974 {
6975 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006976 // if Rt == '1111' then SEE PLI;
6977 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006978 t = Bits32 (opcode, 15, 12);
6979 imm32 = Bits32 (opcode, 11, 0);
6980 add = BitIsSet (opcode, 23);
6981
6982 // if t == 13 then UNPREDICTABLE;
6983 if (t == 13)
6984 return false;
6985
6986 break;
6987
6988 case eEncodingA1:
6989 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006990 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006991 t = Bits32 (opcode, 15, 12);
6992 uint32_t imm4H = Bits32 (opcode, 11, 8);
6993 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006994 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006995 add = BitIsSet (opcode, 23);
6996
6997 // if t == 15 then UNPREDICTABLE;
6998 if (t == 15)
6999 return false;
7000
7001 break;
7002 }
7003
7004 default:
7005 return false;
7006 }
7007
7008 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007009 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007010 if (!success)
7011 return false;
7012 uint64_t base = AlignPC (pc_value);
7013
7014 // address = if add then (base + imm32) else (base - imm32);
7015 addr_t address;
7016 if (add)
7017 address = base + imm32;
7018 else
7019 address = base - imm32;
7020
7021 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007022 RegisterInfo base_reg;
7023 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice5f593912011-03-01 22:25:17 +00007024
7025 EmulateInstruction::Context context;
7026 context.type = eContextRegisterLoad;
7027 context.SetRegisterPlusOffset (base_reg, address - base);
7028
7029 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7030 if (!success)
7031 return false;
7032
7033 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7034 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7035 return false;
7036 }
7037 return true;
7038}
7039
Caroline Tice672f3112011-03-01 23:55:59 +00007040// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7041// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7042// shifted left by 0, 1, 2, or 3 bits.
7043bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007044EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007045{
7046#if 0
7047 if ConditionPassed() then
7048 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7049 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7050 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7051 address = if index then offset_addr else R[n];
7052 R[t] = SignExtend(MemU[address,1], 32);
7053 if wback then R[n] = offset_addr;
7054#endif
7055
7056 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007057
Greg Clayton7bc39082011-03-24 23:53:38 +00007058 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007059 {
7060 uint32_t t;
7061 uint32_t n;
7062 uint32_t m;
7063 bool index;
7064 bool add;
7065 bool wback;
7066 ARM_ShifterType shift_t;
7067 uint32_t shift_n;
7068
7069 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7070 switch (encoding)
7071 {
7072 case eEncodingT1:
7073 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7074 t = Bits32 (opcode, 2, 0);
7075 n = Bits32 (opcode, 5, 3);
7076 m = Bits32 (opcode, 8, 6);
7077
7078 // index = TRUE; add = TRUE; wback = FALSE;
7079 index = true;
7080 add = true;
7081 wback = false;
7082
7083 // (shift_t, shift_n) = (SRType_LSL, 0);
7084 shift_t = SRType_LSL;
7085 shift_n = 0;
7086
7087 break;
7088
7089 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007090 // if Rt == '1111' then SEE PLI;
7091 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007092 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7093 t = Bits32 (opcode, 15, 12);
7094 n = Bits32 (opcode, 19, 16);
7095 m = Bits32 (opcode, 3, 0);
7096
7097 // index = TRUE; add = TRUE; wback = FALSE;
7098 index = true;
7099 add = true;
7100 wback = false;
7101
7102 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7103 shift_t = SRType_LSL;
7104 shift_n = Bits32 (opcode, 5, 4);
7105
7106 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7107 if ((t == 13) || BadReg (m))
7108 return false;
7109 break;
7110
7111 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007112 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007113 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7114 t = Bits32 (opcode, 15, 12);
7115 n = Bits32 (opcode, 19, 16);
7116 m = Bits32 (opcode, 3, 0);
7117
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007118 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007119 index = BitIsSet (opcode, 24);
7120 add = BitIsSet (opcode, 23);
7121 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7122
7123 // (shift_t, shift_n) = (SRType_LSL, 0);
7124 shift_t = SRType_LSL;
7125 shift_n = 0;
7126
7127 // if t == 15 || m == 15 then UNPREDICTABLE;
7128 if ((t == 15) || (m == 15))
7129 return false;
7130
7131 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7132 if (wback && ((n == 15) || (n == t)))
7133 return false;
7134 break;
7135
7136 default:
7137 return false;
7138 }
7139
7140 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7141 if (!success)
7142 return false;
7143
7144 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7145 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7146
7147 addr_t offset_addr;
7148 addr_t address;
7149
7150 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7151 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7152 if (!success)
7153 return false;
7154
7155 if (add)
7156 offset_addr = Rn + offset;
7157 else
7158 offset_addr = Rn - offset;
7159
7160 // address = if index then offset_addr else R[n];
7161 if (index)
7162 address = offset_addr;
7163 else
7164 address = Rn;
7165
7166 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007167 RegisterInfo base_reg;
7168 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7169 RegisterInfo offset_reg;
7170 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice672f3112011-03-01 23:55:59 +00007171
7172 EmulateInstruction::Context context;
7173 context.type = eContextRegisterLoad;
7174 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7175
7176 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7177 if (!success)
7178 return false;
7179
7180 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7181 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7182 return false;
7183
7184 // if wback then R[n] = offset_addr;
7185 if (wback)
7186 {
7187 context.type = eContextAdjustBaseRegister;
7188 context.SetAddress (offset_addr);
7189 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7190 return false;
7191 }
7192 }
7193 return true;
7194}
7195
Caroline Tice78fb5632011-03-02 00:39:42 +00007196// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7197// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7198// pre-indexed addressing.
7199bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007200EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007201{
7202#if 0
7203 if ConditionPassed() then
7204 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7205 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7206 address = if index then offset_addr else R[n];
7207 data = MemU[address,2];
7208 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007209 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007210 R[t] = SignExtend(data, 32);
7211 else // Can only apply before ARMv7
7212 R[t] = bits(32) UNKNOWN;
7213#endif
7214
7215 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007216
Greg Clayton7bc39082011-03-24 23:53:38 +00007217 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007218 {
7219 uint32_t t;
7220 uint32_t n;
7221 uint32_t imm32;
7222 bool index;
7223 bool add;
7224 bool wback;
7225
7226 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7227 switch (encoding)
7228 {
7229 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007230 // if Rn == '1111' then SEE LDRSH (literal);
7231 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007232 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7233 t = Bits32 (opcode, 15, 12);
7234 n = Bits32 (opcode, 19, 16);
7235 imm32 = Bits32 (opcode, 11, 0);
7236
7237 // index = TRUE; add = TRUE; wback = FALSE;
7238 index = true;
7239 add = true;
7240 wback = false;
7241
7242 // if t == 13 then UNPREDICTABLE;
7243 if (t == 13)
7244 return false;
7245
7246 break;
7247
7248 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007249 // if Rn == '1111' then SEE LDRSH (literal);
7250 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7251 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7252 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007253 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7254 return false;
7255
7256 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7257 t = Bits32 (opcode, 15, 12);
7258 n = Bits32 (opcode, 19, 16);
7259 imm32 = Bits32 (opcode, 7, 0);
7260
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007261 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007262 index = BitIsSet (opcode, 10);
7263 add = BitIsSet (opcode, 9);
7264 wback = BitIsSet (opcode, 8);
7265
7266 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7267 if (BadReg (t) || (wback && (n == t)))
7268 return false;
7269
7270 break;
7271
7272 case eEncodingA1:
7273 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007274 // if Rn == '1111' then SEE LDRSH (literal);
7275 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007276 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7277 t = Bits32 (opcode, 15, 12);
7278 n = Bits32 (opcode, 19, 16);
7279 uint32_t imm4H = Bits32 (opcode, 11,8);
7280 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007281 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007282
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007283 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007284 index = BitIsSet (opcode, 24);
7285 add = BitIsSet (opcode, 23);
7286 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7287
7288 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7289 if ((t == 15) || (wback && (n == t)))
7290 return false;
7291
7292 break;
7293 }
7294
7295 default:
7296 return false;
7297 }
7298
7299 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7300 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7301 if (!success)
7302 return false;
7303
7304 addr_t offset_addr;
7305 if (add)
7306 offset_addr = Rn + imm32;
7307 else
7308 offset_addr = Rn - imm32;
7309
7310 // address = if index then offset_addr else R[n];
7311 addr_t address;
7312 if (index)
7313 address = offset_addr;
7314 else
7315 address = Rn;
7316
7317 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007318 RegisterInfo base_reg;
7319 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice78fb5632011-03-02 00:39:42 +00007320
7321 EmulateInstruction::Context context;
7322 context.type = eContextRegisterLoad;
7323 context.SetRegisterPlusOffset (base_reg, address - Rn);
7324
7325 uint64_t data = MemURead (context, address, 2, 0, &success);
7326 if (!success)
7327 return false;
7328
7329 // if wback then R[n] = offset_addr;
7330 if (wback)
7331 {
7332 context.type = eContextAdjustBaseRegister;
7333 context.SetAddress (offset_addr);
7334 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7335 return false;
7336 }
7337
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007338 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007339 if (UnalignedSupport() || BitIsClear (address, 0))
7340 {
7341 // R[t] = SignExtend(data, 32);
7342 int64_t signed_data = llvm::SignExtend64<16>(data);
7343 context.type = eContextRegisterLoad;
7344 context.SetRegisterPlusOffset (base_reg, address - Rn);
7345 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7346 return false;
7347 }
7348 else // Can only apply before ARMv7
7349 {
7350 // R[t] = bits(32) UNKNOWN;
7351 WriteBits32Unknown (t);
7352 }
7353 }
7354 return true;
7355}
7356
Caroline Ticed2fac092011-03-02 19:45:34 +00007357// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7358// sign-extends it to from a 32-bit word, and writes it to a register.
7359bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007360EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007361{
7362#if 0
7363 if ConditionPassed() then
7364 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7365 base = Align(PC,4);
7366 address = if add then (base + imm32) else (base - imm32);
7367 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007368 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007369 R[t] = SignExtend(data, 32);
7370 else // Can only apply before ARMv7
7371 R[t] = bits(32) UNKNOWN;
7372#endif
7373
7374 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007375
Greg Clayton7bc39082011-03-24 23:53:38 +00007376 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007377 {
7378 uint32_t t;
7379 uint32_t imm32;
7380 bool add;
7381
7382 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7383 switch (encoding)
7384 {
7385 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007386 // if Rt == '1111' then SEE "Unallocated memory hints";
7387 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007388 t = Bits32 (opcode, 15, 12);
7389 imm32 = Bits32 (opcode, 11, 0);
7390 add = BitIsSet (opcode, 23);
7391
7392 // if t == 13 then UNPREDICTABLE;
7393 if (t == 13)
7394 return false;
7395
7396 break;
7397
7398 case eEncodingA1:
7399 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007400 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007401 t = Bits32 (opcode, 15, 12);
7402 uint32_t imm4H = Bits32 (opcode, 11, 8);
7403 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007404 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007405 add = BitIsSet (opcode, 23);
7406
7407 // if t == 15 then UNPREDICTABLE;
7408 if (t == 15)
7409 return false;
7410
7411 break;
7412 }
7413 default:
7414 return false;
7415 }
7416
7417 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007418 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007419 if (!success)
7420 return false;
7421
7422 uint64_t base = AlignPC (pc_value);
7423
7424 addr_t address;
7425 // address = if add then (base + imm32) else (base - imm32);
7426 if (add)
7427 address = base + imm32;
7428 else
7429 address = base - imm32;
7430
7431 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007432 RegisterInfo base_reg;
7433 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Ticed2fac092011-03-02 19:45:34 +00007434
7435 EmulateInstruction::Context context;
7436 context.type = eContextRegisterLoad;
7437 context.SetRegisterPlusOffset (base_reg, imm32);
7438
7439 uint64_t data = MemURead (context, address, 2, 0, &success);
7440 if (!success)
7441 return false;
7442
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007443 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007444 if (UnalignedSupport() || BitIsClear (address, 0))
7445 {
7446 // R[t] = SignExtend(data, 32);
7447 int64_t signed_data = llvm::SignExtend64<16>(data);
7448 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7449 return false;
7450 }
7451 else // Can only apply before ARMv7
7452 {
7453 // R[t] = bits(32) UNKNOWN;
7454 WriteBits32Unknown (t);
7455 }
7456 }
7457 return true;
7458}
7459
Caroline Tice291a3e92011-03-02 21:13:44 +00007460// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7461// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7462// shifted left by 0, 1, 2, or 3 bits.
7463bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007464EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007465{
7466#if 0
7467 if ConditionPassed() then
7468 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7469 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7470 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7471 address = if index then offset_addr else R[n];
7472 data = MemU[address,2];
7473 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007474 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007475 R[t] = SignExtend(data, 32);
7476 else // Can only apply before ARMv7
7477 R[t] = bits(32) UNKNOWN;
7478#endif
7479
7480 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007481
Greg Clayton7bc39082011-03-24 23:53:38 +00007482 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007483 {
7484 uint32_t t;
7485 uint32_t n;
7486 uint32_t m;
7487 bool index;
7488 bool add;
7489 bool wback;
7490 ARM_ShifterType shift_t;
7491 uint32_t shift_n;
7492
7493 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7494 switch (encoding)
7495 {
7496 case eEncodingT1:
7497 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7498 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7499 t = Bits32 (opcode, 2, 0);
7500 n = Bits32 (opcode, 5, 3);
7501 m = Bits32 (opcode, 8, 6);
7502
7503 // index = TRUE; add = TRUE; wback = FALSE;
7504 index = true;
7505 add = true;
7506 wback = false;
7507
7508 // (shift_t, shift_n) = (SRType_LSL, 0);
7509 shift_t = SRType_LSL;
7510 shift_n = 0;
7511
7512 break;
7513
7514 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007515 // if Rn == '1111' then SEE LDRSH (literal);
7516 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007517 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7518 t = Bits32 (opcode, 15, 12);
7519 n = Bits32 (opcode, 19, 16);
7520 m = Bits32 (opcode, 3, 0);
7521
7522 // index = TRUE; add = TRUE; wback = FALSE;
7523 index = true;
7524 add = true;
7525 wback = false;
7526
7527 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7528 shift_t = SRType_LSL;
7529 shift_n = Bits32 (opcode, 5, 4);
7530
7531 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7532 if ((t == 13) || BadReg (m))
7533 return false;
7534
7535 break;
7536
7537 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007538 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007539 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7540 t = Bits32 (opcode, 15, 12);
7541 n = Bits32 (opcode, 19, 16);
7542 m = Bits32 (opcode, 3, 0);
7543
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007544 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007545 index = BitIsSet (opcode, 24);
7546 add = BitIsSet (opcode, 23);
7547 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7548
7549 // (shift_t, shift_n) = (SRType_LSL, 0);
7550 shift_t = SRType_LSL;
7551 shift_n = 0;
7552
7553 // if t == 15 || m == 15 then UNPREDICTABLE;
7554 if ((t == 15) || (m == 15))
7555 return false;
7556
7557 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7558 if (wback && ((n == 15) || (n == t)))
7559 return false;
7560
7561 break;
7562
7563 default:
7564 break;
7565 }
7566
7567 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7568 if (!success)
7569 return false;
7570
7571 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7572 if (!success)
7573 return false;
7574
7575 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7576 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7577
7578 addr_t offset_addr;
7579 addr_t address;
7580
7581 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7582 if (add)
7583 offset_addr = Rn + offset;
7584 else
7585 offset_addr = Rn - offset;
7586
7587 // address = if index then offset_addr else R[n];
7588 if (index)
7589 address = offset_addr;
7590 else
7591 address = Rn;
7592
7593 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007594 RegisterInfo base_reg;
7595 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007596
Greg Claytonc07d4512011-04-26 23:48:45 +00007597 RegisterInfo offset_reg;
7598 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007599
7600 EmulateInstruction::Context context;
7601 context.type = eContextRegisterLoad;
7602 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7603
7604 uint64_t data = MemURead (context, address, 2, 0, &success);
7605 if (!success)
7606 return false;
7607
7608 // if wback then R[n] = offset_addr;
7609 if (wback)
7610 {
7611 context.type = eContextAdjustBaseRegister;
7612 context.SetAddress (offset_addr);
7613 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7614 return false;
7615 }
7616
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007617 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007618 if (UnalignedSupport() || BitIsClear (address, 0))
7619 {
7620 // R[t] = SignExtend(data, 32);
7621 context.type = eContextRegisterLoad;
7622 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7623
7624 int64_t signed_data = llvm::SignExtend64<16>(data);
7625 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7626 return false;
7627 }
7628 else // Can only apply before ARMv7
7629 {
7630 // R[t] = bits(32) UNKNOWN;
7631 WriteBits32Unknown (t);
7632 }
7633 }
7634 return true;
7635}
Caroline Tice6bf65162011-03-03 17:42:58 +00007636
7637// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7638// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7639bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007640EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007641{
7642#if 0
7643 if ConditionPassed() then
7644 EncodingSpecificOperations();
7645 rotated = ROR(R[m], rotation);
7646 R[d] = SignExtend(rotated<7:0>, 32);
7647#endif
7648
7649 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007650
Greg Clayton7bc39082011-03-24 23:53:38 +00007651 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007652 {
7653 uint32_t d;
7654 uint32_t m;
7655 uint32_t rotation;
7656
7657 // EncodingSpecificOperations();
7658 switch (encoding)
7659 {
7660 case eEncodingT1:
7661 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7662 d = Bits32 (opcode, 2, 0);
7663 m = Bits32 (opcode, 5, 3);
7664 rotation = 0;
7665
7666 break;
7667
7668 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007669 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007670 d = Bits32 (opcode, 11, 8);
7671 m = Bits32 (opcode, 3, 0);
7672 rotation = Bits32 (opcode, 5, 4) << 3;
7673
7674 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7675 if (BadReg (d) || BadReg (m))
7676 return false;
7677
7678 break;
7679
7680 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007681 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007682 d = Bits32 (opcode, 15, 12);
7683 m = Bits32 (opcode, 3, 0);
7684 rotation = Bits32 (opcode, 11, 10) << 3;
7685
7686 // if d == 15 || m == 15 then UNPREDICTABLE;
7687 if ((d == 15) || (m == 15))
7688 return false;
7689
7690 break;
7691
7692 default:
7693 return false;
7694 }
7695
Caroline Tice868198b2011-03-03 18:04:49 +00007696 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7697 if (!success)
7698 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007699
7700 // rotated = ROR(R[m], rotation);
7701 uint64_t rotated = ROR (Rm, rotation);
7702
7703 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007704 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007705
Greg Claytonc07d4512011-04-26 23:48:45 +00007706 RegisterInfo source_reg;
7707 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice6bf65162011-03-03 17:42:58 +00007708
7709 EmulateInstruction::Context context;
7710 context.type = eContextRegisterLoad;
7711 context.SetRegister (source_reg);
7712
Caroline Tice8ce96d92011-03-03 18:27:17 +00007713 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007714 return false;
7715 }
7716 return true;
7717}
Caroline Tice291a3e92011-03-02 21:13:44 +00007718
Caroline Tice868198b2011-03-03 18:04:49 +00007719// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7720// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7721bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007722EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007723{
7724#if 0
7725 if ConditionPassed() then
7726 EncodingSpecificOperations();
7727 rotated = ROR(R[m], rotation);
7728 R[d] = SignExtend(rotated<15:0>, 32);
7729#endif
7730
7731 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007732
Greg Clayton7bc39082011-03-24 23:53:38 +00007733 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007734 {
7735 uint32_t d;
7736 uint32_t m;
7737 uint32_t rotation;
7738
7739 // EncodingSpecificOperations();
7740 switch (encoding)
7741 {
7742 case eEncodingT1:
7743 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7744 d = Bits32 (opcode, 2, 0);
7745 m = Bits32 (opcode, 5, 3);
7746 rotation = 0;
7747
7748 break;
7749
7750 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007751 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007752 d = Bits32 (opcode, 11, 8);
7753 m = Bits32 (opcode, 3, 0);
7754 rotation = Bits32 (opcode, 5, 4) << 3;
7755
7756 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7757 if (BadReg (d) || BadReg (m))
7758 return false;
7759
7760 break;
7761
7762 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007763 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007764 d = Bits32 (opcode, 15, 12);
7765 m = Bits32 (opcode, 3, 0);
7766 rotation = Bits32 (opcode, 11, 10) << 3;
7767
7768 // if d == 15 || m == 15 then UNPREDICTABLE;
7769 if ((d == 15) || (m == 15))
7770 return false;
7771
7772 break;
7773
7774 default:
7775 return false;
7776 }
7777
7778 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7779 if (!success)
7780 return false;
7781
7782 // rotated = ROR(R[m], rotation);
7783 uint64_t rotated = ROR (Rm, rotation);
7784
7785 // R[d] = SignExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007786 RegisterInfo source_reg;
7787 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice868198b2011-03-03 18:04:49 +00007788
7789 EmulateInstruction::Context context;
7790 context.type = eContextRegisterLoad;
7791 context.SetRegister (source_reg);
7792
Caroline Tice8ce96d92011-03-03 18:27:17 +00007793 int64_t data = llvm::SignExtend64<16> (rotated);
7794 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007795 return false;
7796 }
7797
7798 return true;
7799}
7800
Caroline Tice8ce96d92011-03-03 18:27:17 +00007801// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7802// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7803bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007804EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007805{
7806#if 0
7807 if ConditionPassed() then
7808 EncodingSpecificOperations();
7809 rotated = ROR(R[m], rotation);
7810 R[d] = ZeroExtend(rotated<7:0>, 32);
7811#endif
7812
7813 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007814
Greg Clayton7bc39082011-03-24 23:53:38 +00007815 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007816 {
7817 uint32_t d;
7818 uint32_t m;
7819 uint32_t rotation;
7820
7821 // EncodingSpecificOperations();
7822 switch (encoding)
7823 {
7824 case eEncodingT1:
7825 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7826 d = Bits32 (opcode, 2, 0);
7827 m = Bits32 (opcode, 5, 3);
7828 rotation = 0;
7829
7830 break;
7831
7832 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007833 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007834 d = Bits32 (opcode, 11, 8);
7835 m = Bits32 (opcode, 3, 0);
7836 rotation = Bits32 (opcode, 5, 4) << 3;
7837
7838 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7839 if (BadReg (d) || BadReg (m))
7840 return false;
7841
7842 break;
7843
7844 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007845 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007846 d = Bits32 (opcode, 15, 12);
7847 m = Bits32 (opcode, 3, 0);
7848 rotation = Bits32 (opcode, 11, 10) << 3;
7849
7850 // if d == 15 || m == 15 then UNPREDICTABLE;
7851 if ((d == 15) || (m == 15))
7852 return false;
7853
7854 break;
7855
7856 default:
7857 return false;
7858 }
7859
7860 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7861 if (!success)
7862 return false;
7863
7864 // rotated = ROR(R[m], rotation);
7865 uint64_t rotated = ROR (Rm, rotation);
7866
7867 // R[d] = ZeroExtend(rotated<7:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007868 RegisterInfo source_reg;
7869 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007870
7871 EmulateInstruction::Context context;
7872 context.type = eContextRegisterLoad;
7873 context.SetRegister (source_reg);
7874
7875 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7876 return false;
7877 }
7878 return true;
7879}
7880
Caroline Tice11555f22011-03-03 18:48:58 +00007881// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7882// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7883bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007884EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007885{
7886#if 0
7887 if ConditionPassed() then
7888 EncodingSpecificOperations();
7889 rotated = ROR(R[m], rotation);
7890 R[d] = ZeroExtend(rotated<15:0>, 32);
7891#endif
7892
7893 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007894
Greg Clayton7bc39082011-03-24 23:53:38 +00007895 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007896 {
7897 uint32_t d;
7898 uint32_t m;
7899 uint32_t rotation;
7900
7901 switch (encoding)
7902 {
7903 case eEncodingT1:
7904 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7905 d = Bits32 (opcode, 2, 0);
7906 m = Bits32 (opcode, 5, 3);
7907 rotation = 0;
7908
7909 break;
7910
7911 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007912 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007913 d = Bits32 (opcode, 11, 8);
7914 m = Bits32 (opcode, 3, 0);
7915 rotation = Bits32 (opcode, 5, 4) << 3;
7916
7917 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7918 if (BadReg (d) || BadReg (m))
7919 return false;
7920
7921 break;
7922
7923 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007924 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007925 d = Bits32 (opcode, 15, 12);
7926 m = Bits32 (opcode, 3, 0);
7927 rotation = Bits32 (opcode, 11, 10) << 3;
7928
7929 // if d == 15 || m == 15 then UNPREDICTABLE;
7930 if ((d == 15) || (m == 15))
7931 return false;
7932
7933 break;
7934
7935 default:
7936 return false;
7937 }
7938
7939 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7940 if (!success)
7941 return false;
7942
7943 // rotated = ROR(R[m], rotation);
7944 uint64_t rotated = ROR (Rm, rotation);
7945
7946 // R[d] = ZeroExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007947 RegisterInfo source_reg;
7948 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice11555f22011-03-03 18:48:58 +00007949
7950 EmulateInstruction::Context context;
7951 context.type = eContextRegisterLoad;
7952 context.SetRegister (source_reg);
7953
7954 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7955 return false;
7956 }
7957 return true;
7958}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007959
7960// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7961// word respectively.
7962bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007963EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007964{
7965#if 0
7966 if ConditionPassed() then
7967 EncodingSpecificOperations();
7968 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7969 UNPREDICTABLE;
7970 else
7971 address = if increment then R[n] else R[n]-8;
7972 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007973 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007974 BranchWritePC(MemA[address,4]);
7975 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7976#endif
7977
7978 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007979
Greg Clayton7bc39082011-03-24 23:53:38 +00007980 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007981 {
7982 uint32_t n;
7983 bool wback;
7984 bool increment;
7985 bool wordhigher;
7986
7987 // EncodingSpecificOperations();
7988 switch (encoding)
7989 {
7990 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007991 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007992 n = Bits32 (opcode, 19, 16);
7993 wback = BitIsSet (opcode, 21);
7994 increment = false;
7995 wordhigher = false;
7996
7997 // if n == 15 then UNPREDICTABLE;
7998 if (n == 15)
7999 return false;
8000
8001 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8002 if (InITBlock() && !LastInITBlock())
8003 return false;
8004
8005 break;
8006
8007 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008008 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008009 n = Bits32 (opcode, 19, 16);
8010 wback = BitIsSet (opcode, 21);
8011 increment = true;
8012 wordhigher = false;
8013
8014 // if n == 15 then UNPREDICTABLE;
8015 if (n == 15)
8016 return false;
8017
8018 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8019 if (InITBlock() && !LastInITBlock())
8020 return false;
8021
8022 break;
8023
8024 case eEncodingA1:
8025 // n = UInt(Rn);
8026 n = Bits32 (opcode, 19, 16);
8027
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008028 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008029 wback = BitIsSet (opcode, 21);
8030 increment = BitIsSet (opcode, 23);
8031 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8032
8033 // if n == 15 then UNPREDICTABLE;
8034 if (n == 15)
8035 return false;
8036
8037 break;
8038
8039 default:
8040 return false;
8041 }
8042
8043 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8044 if (!CurrentModeIsPrivileged ())
8045 // UNPREDICTABLE;
8046 return false;
8047 else
8048 {
8049 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8050 if (!success)
8051 return false;
8052
8053 addr_t address;
8054 // address = if increment then R[n] else R[n]-8;
8055 if (increment)
8056 address = Rn;
8057 else
8058 address = Rn - 8;
8059
8060 // if wordhigher then address = address+4;
8061 if (wordhigher)
8062 address = address + 4;
8063
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008064 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Greg Claytonc07d4512011-04-26 23:48:45 +00008065 RegisterInfo base_reg;
8066 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008067
8068 EmulateInstruction::Context context;
8069 context.type = eContextReturnFromException;
8070 context.SetRegisterPlusOffset (base_reg, address - Rn);
8071
8072 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8073 if (!success)
8074 return false;
8075
8076 CPSRWriteByInstr (data, 15, true);
8077
8078 // BranchWritePC(MemA[address,4]);
8079 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8080 if (!success)
8081 return false;
8082
8083 BranchWritePC (context, data2);
8084
8085 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8086 if (wback)
8087 {
8088 context.type = eContextAdjustBaseRegister;
8089 if (increment)
8090 {
8091 context.SetOffset (8);
8092 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8093 return false;
8094 }
8095 else
8096 {
8097 context.SetOffset (-8);
8098 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8099 return false;
8100 }
8101 } // if wback
8102 }
8103 } // if ConditionPassed()
8104 return true;
8105}
Caroline Tice11555f22011-03-03 18:48:58 +00008106
Johnny Chen2115b412011-02-21 23:42:44 +00008107// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8108// and writes the result to the destination register. It can optionally update the condition flags based on
8109// the result.
8110bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008111EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008112{
8113#if 0
8114 // ARM pseudo code...
8115 if ConditionPassed() then
8116 EncodingSpecificOperations();
8117 result = R[n] EOR imm32;
8118 if d == 15 then // Can only occur for ARM encoding
8119 ALUWritePC(result); // setflags is always FALSE here
8120 else
8121 R[d] = result;
8122 if setflags then
8123 APSR.N = result<31>;
8124 APSR.Z = IsZeroBit(result);
8125 APSR.C = carry;
8126 // APSR.V unchanged
8127#endif
8128
8129 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008130
Greg Clayton7bc39082011-03-24 23:53:38 +00008131 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008132 {
8133 uint32_t Rd, Rn;
8134 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8135 bool setflags;
8136 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8137 switch (encoding)
8138 {
8139 case eEncodingT1:
8140 Rd = Bits32(opcode, 11, 8);
8141 Rn = Bits32(opcode, 19, 16);
8142 setflags = BitIsSet(opcode, 20);
8143 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8144 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8145 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008146 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008147 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8148 return false;
8149 break;
8150 case eEncodingA1:
8151 Rd = Bits32(opcode, 15, 12);
8152 Rn = Bits32(opcode, 19, 16);
8153 setflags = BitIsSet(opcode, 20);
8154 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008155
Johnny Chen2115b412011-02-21 23:42:44 +00008156 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008157 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008158 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008159 break;
8160 default:
8161 return false;
8162 }
8163
8164 // Read the first operand.
8165 uint32_t val1 = ReadCoreReg(Rn, &success);
8166 if (!success)
8167 return false;
8168
8169 uint32_t result = val1 ^ imm32;
8170
8171 EmulateInstruction::Context context;
8172 context.type = EmulateInstruction::eContextImmediate;
8173 context.SetNoArgs ();
8174
8175 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8176 return false;
8177 }
8178 return true;
8179}
8180
8181// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8182// optionally-shifted register value, and writes the result to the destination register.
8183// It can optionally update the condition flags based on the result.
8184bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008185EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008186{
8187#if 0
8188 // ARM pseudo code...
8189 if ConditionPassed() then
8190 EncodingSpecificOperations();
8191 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8192 result = R[n] EOR shifted;
8193 if d == 15 then // Can only occur for ARM encoding
8194 ALUWritePC(result); // setflags is always FALSE here
8195 else
8196 R[d] = result;
8197 if setflags then
8198 APSR.N = result<31>;
8199 APSR.Z = IsZeroBit(result);
8200 APSR.C = carry;
8201 // APSR.V unchanged
8202#endif
8203
8204 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008205
Greg Clayton7bc39082011-03-24 23:53:38 +00008206 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008207 {
8208 uint32_t Rd, Rn, Rm;
8209 ARM_ShifterType shift_t;
8210 uint32_t shift_n; // the shift applied to the value read from Rm
8211 bool setflags;
8212 uint32_t carry;
8213 switch (encoding)
8214 {
8215 case eEncodingT1:
8216 Rd = Rn = Bits32(opcode, 2, 0);
8217 Rm = Bits32(opcode, 5, 3);
8218 setflags = !InITBlock();
8219 shift_t = SRType_LSL;
8220 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008221 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008222 case eEncodingT2:
8223 Rd = Bits32(opcode, 11, 8);
8224 Rn = Bits32(opcode, 19, 16);
8225 Rm = Bits32(opcode, 3, 0);
8226 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008227 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8228 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008229 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008230 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008231 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8232 return false;
8233 break;
8234 case eEncodingA1:
8235 Rd = Bits32(opcode, 15, 12);
8236 Rn = Bits32(opcode, 19, 16);
8237 Rm = Bits32(opcode, 3, 0);
8238 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008239 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008240
Johnny Chen2115b412011-02-21 23:42:44 +00008241 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008242 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008243 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008244 break;
8245 default:
8246 return false;
8247 }
8248
8249 // Read the first operand.
8250 uint32_t val1 = ReadCoreReg(Rn, &success);
8251 if (!success)
8252 return false;
8253
8254 // Read the second operand.
8255 uint32_t val2 = ReadCoreReg(Rm, &success);
8256 if (!success)
8257 return false;
8258
8259 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8260 uint32_t result = val1 ^ shifted;
8261
8262 EmulateInstruction::Context context;
8263 context.type = EmulateInstruction::eContextImmediate;
8264 context.SetNoArgs ();
8265
8266 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8267 return false;
8268 }
8269 return true;
8270}
8271
Johnny Chen7c5234d2011-02-18 23:41:11 +00008272// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8273// writes the result to the destination register. It can optionally update the condition flags based
8274// on the result.
8275bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008276EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008277{
8278#if 0
8279 // ARM pseudo code...
8280 if ConditionPassed() then
8281 EncodingSpecificOperations();
8282 result = R[n] OR imm32;
8283 if d == 15 then // Can only occur for ARM encoding
8284 ALUWritePC(result); // setflags is always FALSE here
8285 else
8286 R[d] = result;
8287 if setflags then
8288 APSR.N = result<31>;
8289 APSR.Z = IsZeroBit(result);
8290 APSR.C = carry;
8291 // APSR.V unchanged
8292#endif
8293
8294 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008295
Greg Clayton7bc39082011-03-24 23:53:38 +00008296 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008297 {
8298 uint32_t Rd, Rn;
8299 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8300 bool setflags;
8301 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8302 switch (encoding)
8303 {
8304 case eEncodingT1:
8305 Rd = Bits32(opcode, 11, 8);
8306 Rn = Bits32(opcode, 19, 16);
8307 setflags = BitIsSet(opcode, 20);
8308 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008309 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008310 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008311 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008312 if (BadReg(Rd) || Rn == 13)
8313 return false;
8314 break;
8315 case eEncodingA1:
8316 Rd = Bits32(opcode, 15, 12);
8317 Rn = Bits32(opcode, 19, 16);
8318 setflags = BitIsSet(opcode, 20);
8319 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008320
Johnny Chen7c5234d2011-02-18 23:41:11 +00008321 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008322 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008323 break;
8324 default:
8325 return false;
8326 }
8327
8328 // Read the first operand.
8329 uint32_t val1 = ReadCoreReg(Rn, &success);
8330 if (!success)
8331 return false;
8332
8333 uint32_t result = val1 | imm32;
8334
8335 EmulateInstruction::Context context;
8336 context.type = EmulateInstruction::eContextImmediate;
8337 context.SetNoArgs ();
8338
8339 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8340 return false;
8341 }
8342 return true;
8343}
8344
8345// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8346// value, and writes the result to the destination register. It can optionally update the condition flags based
8347// on the result.
8348bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008349EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008350{
8351#if 0
8352 // ARM pseudo code...
8353 if ConditionPassed() then
8354 EncodingSpecificOperations();
8355 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8356 result = R[n] OR shifted;
8357 if d == 15 then // Can only occur for ARM encoding
8358 ALUWritePC(result); // setflags is always FALSE here
8359 else
8360 R[d] = result;
8361 if setflags then
8362 APSR.N = result<31>;
8363 APSR.Z = IsZeroBit(result);
8364 APSR.C = carry;
8365 // APSR.V unchanged
8366#endif
8367
8368 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008369
Greg Clayton7bc39082011-03-24 23:53:38 +00008370 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008371 {
8372 uint32_t Rd, Rn, Rm;
8373 ARM_ShifterType shift_t;
8374 uint32_t shift_n; // the shift applied to the value read from Rm
8375 bool setflags;
8376 uint32_t carry;
8377 switch (encoding)
8378 {
8379 case eEncodingT1:
8380 Rd = Rn = Bits32(opcode, 2, 0);
8381 Rm = Bits32(opcode, 5, 3);
8382 setflags = !InITBlock();
8383 shift_t = SRType_LSL;
8384 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008385 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008386 case eEncodingT2:
8387 Rd = Bits32(opcode, 11, 8);
8388 Rn = Bits32(opcode, 19, 16);
8389 Rm = Bits32(opcode, 3, 0);
8390 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008391 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8392 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008393 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008394 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008395 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8396 return false;
8397 break;
8398 case eEncodingA1:
8399 Rd = Bits32(opcode, 15, 12);
8400 Rn = Bits32(opcode, 19, 16);
8401 Rm = Bits32(opcode, 3, 0);
8402 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008403 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008404
Johnny Chen7c5234d2011-02-18 23:41:11 +00008405 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008406 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008407 break;
8408 default:
8409 return false;
8410 }
8411
8412 // Read the first operand.
8413 uint32_t val1 = ReadCoreReg(Rn, &success);
8414 if (!success)
8415 return false;
8416
8417 // Read the second operand.
8418 uint32_t val2 = ReadCoreReg(Rm, &success);
8419 if (!success)
8420 return false;
8421
8422 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008423 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008424
8425 EmulateInstruction::Context context;
8426 context.type = EmulateInstruction::eContextImmediate;
8427 context.SetNoArgs ();
8428
8429 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8430 return false;
8431 }
8432 return true;
8433}
8434
Johnny Chened32e7c2011-02-22 23:42:58 +00008435// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8436// the destination register. It can optionally update the condition flags based on the result.
8437bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008438EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008439{
8440#if 0
8441 // ARM pseudo code...
8442 if ConditionPassed() then
8443 EncodingSpecificOperations();
8444 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8445 if d == 15 then // Can only occur for ARM encoding
8446 ALUWritePC(result); // setflags is always FALSE here
8447 else
8448 R[d] = result;
8449 if setflags then
8450 APSR.N = result<31>;
8451 APSR.Z = IsZeroBit(result);
8452 APSR.C = carry;
8453 APSR.V = overflow;
8454#endif
8455
8456 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008457
8458 uint32_t Rd; // the destination register
8459 uint32_t Rn; // the first operand
8460 bool setflags;
8461 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8462 switch (encoding) {
8463 case eEncodingT1:
8464 Rd = Bits32(opcode, 2, 0);
8465 Rn = Bits32(opcode, 5, 3);
8466 setflags = !InITBlock();
8467 imm32 = 0;
8468 break;
8469 case eEncodingT2:
8470 Rd = Bits32(opcode, 11, 8);
8471 Rn = Bits32(opcode, 19, 16);
8472 setflags = BitIsSet(opcode, 20);
8473 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8474 if (BadReg(Rd) || BadReg(Rn))
8475 return false;
8476 break;
8477 case eEncodingA1:
8478 Rd = Bits32(opcode, 15, 12);
8479 Rn = Bits32(opcode, 19, 16);
8480 setflags = BitIsSet(opcode, 20);
8481 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008482
Johnny Chened32e7c2011-02-22 23:42:58 +00008483 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008484 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008485 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008486 break;
8487 default:
8488 return false;
8489 }
8490 // Read the register value from the operand register Rn.
8491 uint32_t reg_val = ReadCoreReg(Rn, &success);
8492 if (!success)
8493 return false;
8494
8495 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8496
8497 EmulateInstruction::Context context;
8498 context.type = EmulateInstruction::eContextImmediate;
8499 context.SetNoArgs ();
8500
8501 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8502 return false;
8503
8504 return true;
8505}
8506
8507// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8508// result to the destination register. It can optionally update the condition flags based on the result.
8509bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008510EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008511{
8512#if 0
8513 // ARM pseudo code...
8514 if ConditionPassed() then
8515 EncodingSpecificOperations();
8516 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8517 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8518 if d == 15 then // Can only occur for ARM encoding
8519 ALUWritePC(result); // setflags is always FALSE here
8520 else
8521 R[d] = result;
8522 if setflags then
8523 APSR.N = result<31>;
8524 APSR.Z = IsZeroBit(result);
8525 APSR.C = carry;
8526 APSR.V = overflow;
8527#endif
8528
8529 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008530
8531 uint32_t Rd; // the destination register
8532 uint32_t Rn; // the first operand
8533 uint32_t Rm; // the second operand
8534 bool setflags;
8535 ARM_ShifterType shift_t;
8536 uint32_t shift_n; // the shift applied to the value read from Rm
8537 switch (encoding) {
8538 case eEncodingT1:
8539 Rd = Bits32(opcode, 11, 8);
8540 Rn = Bits32(opcode, 19, 16);
8541 Rm = Bits32(opcode, 3, 0);
8542 setflags = BitIsSet(opcode, 20);
8543 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8544 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8545 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8546 return false;
8547 break;
8548 case eEncodingA1:
8549 Rd = Bits32(opcode, 15, 12);
8550 Rn = Bits32(opcode, 19, 16);
8551 Rm = Bits32(opcode, 3, 0);
8552 setflags = BitIsSet(opcode, 20);
8553 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008554
Johnny Chened32e7c2011-02-22 23:42:58 +00008555 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008556 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008557 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008558 break;
8559 default:
8560 return false;
8561 }
8562 // Read the register value from register Rn.
8563 uint32_t val1 = ReadCoreReg(Rn, &success);
8564 if (!success)
8565 return false;
8566
8567 // Read the register value from register Rm.
8568 uint32_t val2 = ReadCoreReg(Rm, &success);
8569 if (!success)
8570 return false;
8571
8572 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8573 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8574
8575 EmulateInstruction::Context context;
8576 context.type = EmulateInstruction::eContextImmediate;
8577 context.SetNoArgs();
8578 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8579 return false;
8580
8581 return true;
8582}
8583
Johnny Chen90e607b2011-02-23 00:07:09 +00008584// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8585// an immediate value, and writes the result to the destination register. It can optionally update the condition
8586// flags based on the result.
8587bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008588EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008589{
8590#if 0
8591 // ARM pseudo code...
8592 if ConditionPassed() then
8593 EncodingSpecificOperations();
8594 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8595 if d == 15 then
8596 ALUWritePC(result); // setflags is always FALSE here
8597 else
8598 R[d] = result;
8599 if setflags then
8600 APSR.N = result<31>;
8601 APSR.Z = IsZeroBit(result);
8602 APSR.C = carry;
8603 APSR.V = overflow;
8604#endif
8605
8606 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008607
8608 uint32_t Rd; // the destination register
8609 uint32_t Rn; // the first operand
8610 bool setflags;
8611 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8612 switch (encoding) {
8613 case eEncodingA1:
8614 Rd = Bits32(opcode, 15, 12);
8615 Rn = Bits32(opcode, 19, 16);
8616 setflags = BitIsSet(opcode, 20);
8617 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008618
Johnny Chen90e607b2011-02-23 00:07:09 +00008619 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008620 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008621 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008622 break;
8623 default:
8624 return false;
8625 }
8626 // Read the register value from the operand register Rn.
8627 uint32_t reg_val = ReadCoreReg(Rn, &success);
8628 if (!success)
8629 return false;
8630
8631 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8632
8633 EmulateInstruction::Context context;
8634 context.type = EmulateInstruction::eContextImmediate;
8635 context.SetNoArgs ();
8636
8637 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8638 return false;
8639
8640 return true;
8641}
8642
8643// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8644// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8645// condition flags based on the result.
8646bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008647EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008648{
8649#if 0
8650 // ARM pseudo code...
8651 if ConditionPassed() then
8652 EncodingSpecificOperations();
8653 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8654 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8655 if d == 15 then
8656 ALUWritePC(result); // setflags is always FALSE here
8657 else
8658 R[d] = result;
8659 if setflags then
8660 APSR.N = result<31>;
8661 APSR.Z = IsZeroBit(result);
8662 APSR.C = carry;
8663 APSR.V = overflow;
8664#endif
8665
8666 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008667
8668 uint32_t Rd; // the destination register
8669 uint32_t Rn; // the first operand
8670 uint32_t Rm; // the second operand
8671 bool setflags;
8672 ARM_ShifterType shift_t;
8673 uint32_t shift_n; // the shift applied to the value read from Rm
8674 switch (encoding) {
8675 case eEncodingA1:
8676 Rd = Bits32(opcode, 15, 12);
8677 Rn = Bits32(opcode, 19, 16);
8678 Rm = Bits32(opcode, 3, 0);
8679 setflags = BitIsSet(opcode, 20);
8680 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008681
Johnny Chen90e607b2011-02-23 00:07:09 +00008682 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008683 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008684 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008685 break;
8686 default:
8687 return false;
8688 }
8689 // Read the register value from register Rn.
8690 uint32_t val1 = ReadCoreReg(Rn, &success);
8691 if (!success)
8692 return false;
8693
8694 // Read the register value from register Rm.
8695 uint32_t val2 = ReadCoreReg(Rm, &success);
8696 if (!success)
8697 return false;
8698
8699 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8700 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8701
8702 EmulateInstruction::Context context;
8703 context.type = EmulateInstruction::eContextImmediate;
8704 context.SetNoArgs();
8705 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8706 return false;
8707
8708 return true;
8709}
8710
Johnny Chen9b381772011-02-23 01:01:21 +00008711// Subtract with Carry (immediate) subtracts an immediate value and the value of
8712// NOT (Carry flag) from a register value, and writes the result to the destination register.
8713// It can optionally update the condition flags based on the result.
8714bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008715EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008716{
8717#if 0
8718 // ARM pseudo code...
8719 if ConditionPassed() then
8720 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008721 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008722 if d == 15 then // Can only occur for ARM encoding
8723 ALUWritePC(result); // setflags is always FALSE here
8724 else
8725 R[d] = result;
8726 if setflags then
8727 APSR.N = result<31>;
8728 APSR.Z = IsZeroBit(result);
8729 APSR.C = carry;
8730 APSR.V = overflow;
8731#endif
8732
8733 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008734
8735 uint32_t Rd; // the destination register
8736 uint32_t Rn; // the first operand
8737 bool setflags;
8738 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8739 switch (encoding) {
8740 case eEncodingT1:
8741 Rd = Bits32(opcode, 11, 8);
8742 Rn = Bits32(opcode, 19, 16);
8743 setflags = BitIsSet(opcode, 20);
8744 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8745 if (BadReg(Rd) || BadReg(Rn))
8746 return false;
8747 break;
8748 case eEncodingA1:
8749 Rd = Bits32(opcode, 15, 12);
8750 Rn = Bits32(opcode, 19, 16);
8751 setflags = BitIsSet(opcode, 20);
8752 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008753
Johnny Chen9b381772011-02-23 01:01:21 +00008754 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008755 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008756 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008757 break;
8758 default:
8759 return false;
8760 }
8761 // Read the register value from the operand register Rn.
8762 uint32_t reg_val = ReadCoreReg(Rn, &success);
8763 if (!success)
8764 return false;
8765
8766 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8767
8768 EmulateInstruction::Context context;
8769 context.type = EmulateInstruction::eContextImmediate;
8770 context.SetNoArgs ();
8771
8772 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8773 return false;
8774
8775 return true;
8776}
8777
8778// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8779// NOT (Carry flag) from a register value, and writes the result to the destination register.
8780// It can optionally update the condition flags based on the result.
8781bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008782EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008783{
8784#if 0
8785 // ARM pseudo code...
8786 if ConditionPassed() then
8787 EncodingSpecificOperations();
8788 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8789 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8790 if d == 15 then // Can only occur for ARM encoding
8791 ALUWritePC(result); // setflags is always FALSE here
8792 else
8793 R[d] = result;
8794 if setflags then
8795 APSR.N = result<31>;
8796 APSR.Z = IsZeroBit(result);
8797 APSR.C = carry;
8798 APSR.V = overflow;
8799#endif
8800
8801 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008802
8803 uint32_t Rd; // the destination register
8804 uint32_t Rn; // the first operand
8805 uint32_t Rm; // the second operand
8806 bool setflags;
8807 ARM_ShifterType shift_t;
8808 uint32_t shift_n; // the shift applied to the value read from Rm
8809 switch (encoding) {
8810 case eEncodingT1:
8811 Rd = Rn = Bits32(opcode, 2, 0);
8812 Rm = Bits32(opcode, 5, 3);
8813 setflags = !InITBlock();
8814 shift_t = SRType_LSL;
8815 shift_n = 0;
8816 break;
8817 case eEncodingT2:
8818 Rd = Bits32(opcode, 11, 8);
8819 Rn = Bits32(opcode, 19, 16);
8820 Rm = Bits32(opcode, 3, 0);
8821 setflags = BitIsSet(opcode, 20);
8822 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8823 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8824 return false;
8825 break;
8826 case eEncodingA1:
8827 Rd = Bits32(opcode, 15, 12);
8828 Rn = Bits32(opcode, 19, 16);
8829 Rm = Bits32(opcode, 3, 0);
8830 setflags = BitIsSet(opcode, 20);
8831 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008832
Johnny Chen9b381772011-02-23 01:01:21 +00008833 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008834 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008835 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008836 break;
8837 default:
8838 return false;
8839 }
8840 // Read the register value from register Rn.
8841 uint32_t val1 = ReadCoreReg(Rn, &success);
8842 if (!success)
8843 return false;
8844
8845 // Read the register value from register Rm.
8846 uint32_t val2 = ReadCoreReg(Rm, &success);
8847 if (!success)
8848 return false;
8849
8850 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8851 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8852
8853 EmulateInstruction::Context context;
8854 context.type = EmulateInstruction::eContextImmediate;
8855 context.SetNoArgs();
8856 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8857 return false;
8858
8859 return true;
8860}
8861
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008862// This instruction subtracts an immediate value from a register value, and writes the result
8863// to the destination register. It can optionally update the condition flags based on the result.
8864bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008865EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008866{
8867#if 0
8868 // ARM pseudo code...
8869 if ConditionPassed() then
8870 EncodingSpecificOperations();
8871 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8872 R[d] = result;
8873 if setflags then
8874 APSR.N = result<31>;
8875 APSR.Z = IsZeroBit(result);
8876 APSR.C = carry;
8877 APSR.V = overflow;
8878#endif
8879
8880 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008881
8882 uint32_t Rd; // the destination register
8883 uint32_t Rn; // the first operand
8884 bool setflags;
8885 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8886 switch (encoding) {
8887 case eEncodingT1:
8888 Rd = Bits32(opcode, 2, 0);
8889 Rn = Bits32(opcode, 5, 3);
8890 setflags = !InITBlock();
8891 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8892 break;
8893 case eEncodingT2:
8894 Rd = Rn = Bits32(opcode, 10, 8);
8895 setflags = !InITBlock();
8896 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8897 break;
8898 case eEncodingT3:
8899 Rd = Bits32(opcode, 11, 8);
8900 Rn = Bits32(opcode, 19, 16);
8901 setflags = BitIsSet(opcode, 20);
8902 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8903
8904 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8905 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008906 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008907
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008908 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008909 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008910 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008911
8912 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8913 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8914 return false;
8915 break;
8916 case eEncodingT4:
8917 Rd = Bits32(opcode, 11, 8);
8918 Rn = Bits32(opcode, 19, 16);
8919 setflags = BitIsSet(opcode, 20);
8920 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8921
8922 // if Rn == '1111' then SEE ADR;
8923 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008924 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008925
8926 // if Rn == '1101' then SEE SUB (SP minus immediate);
8927 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008928 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008929
8930 if (BadReg(Rd))
8931 return false;
8932 break;
8933 default:
8934 return false;
8935 }
8936 // Read the register value from the operand register Rn.
8937 uint32_t reg_val = ReadCoreReg(Rn, &success);
8938 if (!success)
8939 return false;
8940
8941 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8942
8943 EmulateInstruction::Context context;
8944 context.type = EmulateInstruction::eContextImmediate;
8945 context.SetNoArgs ();
8946
8947 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8948 return false;
8949
8950 return true;
8951}
8952
8953// This instruction subtracts an immediate value from a register value, and writes the result
8954// to the destination register. It can optionally update the condition flags based on the result.
8955bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008956EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008957{
8958#if 0
8959 // ARM pseudo code...
8960 if ConditionPassed() then
8961 EncodingSpecificOperations();
8962 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8963 if d == 15 then
8964 ALUWritePC(result); // setflags is always FALSE here
8965 else
8966 R[d] = result;
8967 if setflags then
8968 APSR.N = result<31>;
8969 APSR.Z = IsZeroBit(result);
8970 APSR.C = carry;
8971 APSR.V = overflow;
8972#endif
8973
8974 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008975
8976 uint32_t Rd; // the destination register
8977 uint32_t Rn; // the first operand
8978 bool setflags;
8979 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8980 switch (encoding) {
8981 case eEncodingA1:
8982 Rd = Bits32(opcode, 15, 12);
8983 Rn = Bits32(opcode, 19, 16);
8984 setflags = BitIsSet(opcode, 20);
8985 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8986
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008987 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008988 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008989 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008990
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008991 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008992 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008993 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008994
8995 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008996 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008997 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008998 break;
8999 default:
9000 return false;
9001 }
9002 // Read the register value from the operand register Rn.
9003 uint32_t reg_val = ReadCoreReg(Rn, &success);
9004 if (!success)
9005 return false;
9006
9007 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9008
9009 EmulateInstruction::Context context;
9010 context.type = EmulateInstruction::eContextImmediate;
9011 context.SetNoArgs ();
9012
9013 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9014 return false;
9015
9016 return true;
9017}
9018
Johnny Chen2115b412011-02-21 23:42:44 +00009019// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9020// immediate value. It updates the condition flags based on the result, and discards the result.
9021bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009022EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009023{
9024#if 0
9025 // ARM pseudo code...
9026 if ConditionPassed() then
9027 EncodingSpecificOperations();
9028 result = R[n] EOR imm32;
9029 APSR.N = result<31>;
9030 APSR.Z = IsZeroBit(result);
9031 APSR.C = carry;
9032 // APSR.V unchanged
9033#endif
9034
9035 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009036
Greg Clayton7bc39082011-03-24 23:53:38 +00009037 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009038 {
9039 uint32_t Rn;
9040 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9041 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9042 switch (encoding)
9043 {
9044 case eEncodingT1:
9045 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009046 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009047 if (BadReg(Rn))
9048 return false;
9049 break;
9050 case eEncodingA1:
9051 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009052 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009053 break;
9054 default:
9055 return false;
9056 }
9057
9058 // Read the first operand.
9059 uint32_t val1 = ReadCoreReg(Rn, &success);
9060 if (!success)
9061 return false;
9062
9063 uint32_t result = val1 ^ imm32;
9064
9065 EmulateInstruction::Context context;
9066 context.type = EmulateInstruction::eContextImmediate;
9067 context.SetNoArgs ();
9068
9069 if (!WriteFlags(context, result, carry))
9070 return false;
9071 }
9072 return true;
9073}
9074
9075// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9076// optionally-shifted register value. It updates the condition flags based on the result, and discards
9077// the result.
9078bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009079EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009080{
9081#if 0
9082 // ARM pseudo code...
9083 if ConditionPassed() then
9084 EncodingSpecificOperations();
9085 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9086 result = R[n] EOR shifted;
9087 APSR.N = result<31>;
9088 APSR.Z = IsZeroBit(result);
9089 APSR.C = carry;
9090 // APSR.V unchanged
9091#endif
9092
9093 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009094
Greg Clayton7bc39082011-03-24 23:53:38 +00009095 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009096 {
9097 uint32_t Rn, Rm;
9098 ARM_ShifterType shift_t;
9099 uint32_t shift_n; // the shift applied to the value read from Rm
9100 uint32_t carry;
9101 switch (encoding)
9102 {
9103 case eEncodingT1:
9104 Rn = Bits32(opcode, 19, 16);
9105 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009106 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009107 if (BadReg(Rn) || BadReg(Rm))
9108 return false;
9109 break;
9110 case eEncodingA1:
9111 Rn = Bits32(opcode, 19, 16);
9112 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009113 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009114 break;
9115 default:
9116 return false;
9117 }
9118
9119 // Read the first operand.
9120 uint32_t val1 = ReadCoreReg(Rn, &success);
9121 if (!success)
9122 return false;
9123
9124 // Read the second operand.
9125 uint32_t val2 = ReadCoreReg(Rm, &success);
9126 if (!success)
9127 return false;
9128
9129 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9130 uint32_t result = val1 ^ shifted;
9131
9132 EmulateInstruction::Context context;
9133 context.type = EmulateInstruction::eContextImmediate;
9134 context.SetNoArgs ();
9135
9136 if (!WriteFlags(context, result, carry))
9137 return false;
9138 }
9139 return true;
9140}
9141
Johnny Chende3cce32011-02-21 21:24:49 +00009142// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9143// It updates the condition flags based on the result, and discards the result.
9144bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009145EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009146{
9147#if 0
9148 // ARM pseudo code...
9149 if ConditionPassed() then
9150 EncodingSpecificOperations();
9151 result = R[n] AND imm32;
9152 APSR.N = result<31>;
9153 APSR.Z = IsZeroBit(result);
9154 APSR.C = carry;
9155 // APSR.V unchanged
9156#endif
9157
9158 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009159
Greg Clayton7bc39082011-03-24 23:53:38 +00009160 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009161 {
9162 uint32_t Rn;
9163 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9164 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9165 switch (encoding)
9166 {
9167 case eEncodingT1:
9168 Rn = Bits32(opcode, 19, 16);
9169 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9170 if (BadReg(Rn))
9171 return false;
9172 break;
9173 case eEncodingA1:
9174 Rn = Bits32(opcode, 19, 16);
9175 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9176 break;
9177 default:
9178 return false;
9179 }
9180
9181 // Read the first operand.
9182 uint32_t val1 = ReadCoreReg(Rn, &success);
9183 if (!success)
9184 return false;
9185
9186 uint32_t result = val1 & imm32;
9187
9188 EmulateInstruction::Context context;
9189 context.type = EmulateInstruction::eContextImmediate;
9190 context.SetNoArgs ();
9191
9192 if (!WriteFlags(context, result, carry))
9193 return false;
9194 }
9195 return true;
9196}
9197
9198// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9199// It updates the condition flags based on the result, and discards the result.
9200bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009201EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009202{
9203#if 0
9204 // ARM pseudo code...
9205 if ConditionPassed() then
9206 EncodingSpecificOperations();
9207 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9208 result = R[n] AND shifted;
9209 APSR.N = result<31>;
9210 APSR.Z = IsZeroBit(result);
9211 APSR.C = carry;
9212 // APSR.V unchanged
9213#endif
9214
9215 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009216
Greg Clayton7bc39082011-03-24 23:53:38 +00009217 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009218 {
9219 uint32_t Rn, Rm;
9220 ARM_ShifterType shift_t;
9221 uint32_t shift_n; // the shift applied to the value read from Rm
9222 uint32_t carry;
9223 switch (encoding)
9224 {
9225 case eEncodingT1:
9226 Rn = Bits32(opcode, 2, 0);
9227 Rm = Bits32(opcode, 5, 3);
9228 shift_t = SRType_LSL;
9229 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009230 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009231 case eEncodingT2:
9232 Rn = Bits32(opcode, 19, 16);
9233 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009234 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009235 if (BadReg(Rn) || BadReg(Rm))
9236 return false;
9237 break;
9238 case eEncodingA1:
9239 Rn = Bits32(opcode, 19, 16);
9240 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009241 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009242 break;
9243 default:
9244 return false;
9245 }
9246
9247 // Read the first operand.
9248 uint32_t val1 = ReadCoreReg(Rn, &success);
9249 if (!success)
9250 return false;
9251
9252 // Read the second operand.
9253 uint32_t val2 = ReadCoreReg(Rm, &success);
9254 if (!success)
9255 return false;
9256
9257 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9258 uint32_t result = val1 & shifted;
9259
9260 EmulateInstruction::Context context;
9261 context.type = EmulateInstruction::eContextImmediate;
9262 context.SetNoArgs ();
9263
9264 if (!WriteFlags(context, result, carry))
9265 return false;
9266 }
9267 return true;
9268}
Caroline Ticed05b4902011-03-29 21:24:06 +00009269
9270// A8.6.216 SUB (SP minus register)
9271bool
9272EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9273{
9274#if 0
9275 if ConditionPassed() then
9276 EncodingSpecificOperations();
9277 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9278 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), 1’);
9279 if d == 15 then // Can only occur for ARM encoding
9280 ALUWritePC(result); // setflags is always FALSE here
9281 else
9282 R[d] = result;
9283 if setflags then
9284 APSR.N = result<31>;
9285 APSR.Z = IsZeroBit(result);
9286 APSR.C = carry;
9287 APSR.V = overflow;
9288#endif
9289
9290 bool success = false;
9291
9292 if (ConditionPassed(opcode))
9293 {
9294 uint32_t d;
9295 uint32_t m;
9296 bool setflags;
9297 ARM_ShifterType shift_t;
9298 uint32_t shift_n;
9299
9300 switch (encoding)
9301 {
9302 case eEncodingT1:
9303 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9304 d = Bits32 (opcode, 11, 8);
9305 m = Bits32 (opcode, 3, 0);
9306 setflags = BitIsSet (opcode, 20);
9307
9308 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9309 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9310
9311 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9312 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9313 return false;
9314
9315 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9316 if ((d == 15) || BadReg (m))
9317 return false;
9318 break;
9319
9320 case eEncodingA1:
Caroline Ticed05b4902011-03-29 21:24:06 +00009321 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9322 d = Bits32 (opcode, 15, 12);
9323 m = Bits32 (opcode, 3, 0);
9324 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009325
9326 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9327 if (d == 15 && setflags)
9328 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009329
9330 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9331 shift_n = DecodeImmShiftARM (opcode, shift_t);
9332 break;
9333
9334 default:
9335 return false;
9336 }
9337
9338 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9339 uint32_t Rm = ReadCoreReg (m, &success);
9340 if (!success)
9341 return false;
9342
9343 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9344
9345 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’);
9346 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9347 if (!success)
9348 return false;
9349
9350 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9351
9352 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009353 context.type = eContextArithmetic;
9354 RegisterInfo sp_reg;
9355 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9356 RegisterInfo dwarf_reg;
9357 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +00009358 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9359
Caroline Ticeef440002011-03-30 05:40:56 +00009360 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009361 return false;
9362 }
9363 return true;
9364}
9365
9366
9367// A8.6.7 ADD (register-shifted register)
9368bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009369EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009370{
9371#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009372 if ConditionPassed() then
9373 EncodingSpecificOperations();
9374 shift_n = UInt(R[s]<7:0>);
9375 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9376 (result, carry, overflow) = AddWithCarry(R[n], shifted, 0’);
9377 R[d] = result;
9378 if setflags then
9379 APSR.N = result<31>;
9380 APSR.Z = IsZeroBit(result);
9381 APSR.C = carry;
9382 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009383#endif
9384
Caroline Ticec08ed382011-03-29 23:03:16 +00009385 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009386
9387 if (ConditionPassed(opcode))
9388 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009389 uint32_t d;
9390 uint32_t n;
9391 uint32_t m;
9392 uint32_t s;
9393 bool setflags;
9394 ARM_ShifterType shift_t;
9395
Caroline Ticed05b4902011-03-29 21:24:06 +00009396 switch (encoding)
9397 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009398 case eEncodingA1:
9399 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9400 d = Bits32 (opcode, 15, 12);
9401 n = Bits32 (opcode, 19, 16);
9402 m = Bits32 (opcode, 3, 0);
9403 s = Bits32 (opcode, 11, 8);
9404
9405 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type);
9406 setflags = BitIsSet (opcode, 20);
9407 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9408
9409 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9410 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9411 return false;
9412 break;
9413
9414 default:
9415 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009416 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009417
9418 // shift_n = UInt(R[s]<7:0>);
9419 uint32_t Rs = ReadCoreReg (s, &success);
9420 if (!success)
9421 return false;
9422
9423 uint32_t shift_n = Bits32 (Rs, 7, 0);
9424
9425 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9426 uint32_t Rm = ReadCoreReg (m, &success);
9427 if (!success)
9428 return false;
9429
9430 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9431
9432 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’);
9433 uint32_t Rn = ReadCoreReg (n, &success);
9434 if (!success)
9435 return false;
9436
9437 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9438
9439 // R[d] = result;
9440 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009441 context.type = eContextArithmetic;
9442 RegisterInfo reg_n;
9443 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9444 RegisterInfo reg_m;
9445 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009446
9447 context.SetRegisterRegisterOperands (reg_n, reg_m);
9448
9449 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9450 return false;
9451
9452 // if setflags then
9453 // APSR.N = result<31>;
9454 // APSR.Z = IsZeroBit(result);
9455 // APSR.C = carry;
9456 // APSR.V = overflow;
9457 if (setflags)
9458 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009459 }
9460 return true;
9461}
9462
9463// A8.6.213 SUB (register)
9464bool
9465EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9466{
9467#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009468 if ConditionPassed() then
9469 EncodingSpecificOperations();
9470 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9471 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), 1’);
9472 if d == 15 then // Can only occur for ARM encoding
9473 ALUWritePC(result); // setflags is always FALSE here
9474 else
9475 R[d] = result;
9476 if setflags then
9477 APSR.N = result<31>;
9478 APSR.Z = IsZeroBit(result);
9479 APSR.C = carry;
9480 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009481#endif
9482
Caroline Tice4cccd532011-03-29 23:44:20 +00009483 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009484
9485 if (ConditionPassed(opcode))
9486 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009487 uint32_t d;
9488 uint32_t n;
9489 uint32_t m;
9490 bool setflags;
9491 ARM_ShifterType shift_t;
9492 uint32_t shift_n;
9493
Caroline Ticed05b4902011-03-29 21:24:06 +00009494 switch (encoding)
9495 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009496 case eEncodingT1:
9497 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9498 d = Bits32 (opcode, 2, 0);
9499 n = Bits32 (opcode, 5, 3);
9500 m = Bits32 (opcode, 8, 6);
9501 setflags = !InITBlock();
9502
9503 // (shift_t, shift_n) = (SRType_LSL, 0);
9504 shift_t = SRType_LSL;
9505 shift_n = 0;
9506
9507 break;
9508
9509 case eEncodingT2:
9510 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register);
9511 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9512 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9513 d = Bits32 (opcode, 11, 8);
9514 n = Bits32 (opcode, 19, 16);
9515 m = Bits32 (opcode, 3, 0);
9516 setflags = BitIsSet (opcode, 20);
9517
9518 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9519 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9520
9521 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9522 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9523 return false;
9524
9525 break;
9526
9527 case eEncodingA1:
Caroline Tice4cccd532011-03-29 23:44:20 +00009528 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9529 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9530 d = Bits32 (opcode, 15, 12);
9531 n = Bits32 (opcode, 19, 16);
9532 m = Bits32 (opcode, 3, 0);
9533 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009534
9535 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9536 if ((d == 15) && setflags)
9537 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009538
9539 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9540 shift_n = DecodeImmShiftARM (opcode, shift_t);
9541
9542 break;
9543
9544 default:
9545 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009546 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009547
9548 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9549 uint32_t Rm = ReadCoreReg (m, &success);
9550 if (!success)
9551 return false;
9552
9553 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9554
9555 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’);
9556 uint32_t Rn = ReadCoreReg (n, &success);
9557 if (!success)
9558 return false;
9559
9560 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9561
9562 // if d == 15 then // Can only occur for ARM encoding
9563 // ALUWritePC(result); // setflags is always FALSE here
9564 // else
9565 // R[d] = result;
9566 // if setflags then
9567 // APSR.N = result<31>;
9568 // APSR.Z = IsZeroBit(result);
9569 // APSR.C = carry;
9570 // APSR.V = overflow;
9571
9572 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009573 context.type = eContextArithmetic;
9574 RegisterInfo reg_n;
9575 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9576 RegisterInfo reg_m;
9577 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009578 context.SetRegisterRegisterOperands (reg_n, reg_m);
9579
Caroline Ticeef440002011-03-30 05:40:56 +00009580 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009581 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009582 }
9583 return true;
9584}
Caroline Tice4cccd532011-03-29 23:44:20 +00009585
Caroline Ticed05b4902011-03-29 21:24:06 +00009586// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009587// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9588// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009589bool
9590EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9591{
9592#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009593 if ConditionPassed() then
9594 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9595 address = R[n] + imm32;
9596 if ExclusiveMonitorsPass(address,4) then
9597 MemA[address,4] = R[t];
9598 R[d] = 0;
9599 else
9600 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009601#endif
9602
Caroline Tice5168b6c2011-03-30 05:15:46 +00009603 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009604
9605 if (ConditionPassed(opcode))
9606 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009607 uint32_t d;
9608 uint32_t t;
9609 uint32_t n;
9610 uint32_t imm32;
9611 const uint32_t addr_byte_size = GetAddressByteSize();
9612
Caroline Ticed05b4902011-03-29 21:24:06 +00009613 switch (encoding)
9614 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009615 case eEncodingT1:
9616 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9617 d = Bits32 (opcode, 11, 8);
9618 t = Bits32 (opcode, 15, 12);
9619 n = Bits32 (opcode, 19, 16);
9620 imm32 = Bits32 (opcode, 7, 0) << 2;
9621
9622 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9623 if (BadReg (d) || BadReg (t) || (n == 15))
9624 return false;
9625
9626 // if d == n || d == t then UNPREDICTABLE;
9627 if ((d == n) || (d == t))
9628 return false;
9629
9630 break;
9631
9632 case eEncodingA1:
9633 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9634 d = Bits32 (opcode, 15, 12);
9635 t = Bits32 (opcode, 3, 0);
9636 n = Bits32 (opcode, 19, 16);
9637 imm32 = 0;
9638
9639 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9640 if ((d == 15) || (t == 15) || (n == 15))
9641 return false;
9642
9643 // if d == n || d == t then UNPREDICTABLE;
9644 if ((d == n) || (d == t))
9645 return false;
9646
9647 break;
9648
9649 default:
9650 return false;
9651 }
9652
9653 // address = R[n] + imm32;
9654 uint32_t Rn = ReadCoreReg (n, &success);
9655 if (!success)
9656 return false;
9657
9658 addr_t address = Rn + imm32;
9659
Greg Claytonc07d4512011-04-26 23:48:45 +00009660 RegisterInfo base_reg;
9661 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9662 RegisterInfo data_reg;
9663 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009664 EmulateInstruction::Context context;
9665 context.type = eContextRegisterStore;
9666 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9667
9668 // if ExclusiveMonitorsPass(address,4) then
9669 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9670 // always return true.
9671 if (true)
9672 {
9673 // MemA[address,4] = R[t];
9674 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9675 if (!success)
9676 return false;
9677
9678 if (!MemAWrite (context, address, Rt, addr_byte_size))
9679 return false;
9680
9681 // R[d] = 0;
9682 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9683 return false;
9684 }
9685 else
9686 {
9687 // R[d] = 1;
9688 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9689 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009690 }
9691 }
9692 return true;
9693}
9694
9695// A8.6.197 STRB (immediate, ARM)
9696bool
9697EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9698{
9699#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009700 if ConditionPassed() then
9701 EncodingSpecificOperations();
9702 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9703 address = if index then offset_addr else R[n];
9704 MemU[address,1] = R[t]<7:0>;
9705 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009706#endif
9707
Caroline Ticeef440002011-03-30 05:40:56 +00009708 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009709
9710 if (ConditionPassed(opcode))
9711 {
Caroline Ticeef440002011-03-30 05:40:56 +00009712 uint32_t t;
9713 uint32_t n;
9714 uint32_t imm32;
9715 bool index;
9716 bool add;
9717 bool wback;
9718
Caroline Ticed05b4902011-03-29 21:24:06 +00009719 switch (encoding)
9720 {
Caroline Ticeef440002011-03-30 05:40:56 +00009721 case eEncodingA1:
9722 // if P == ‘0’ && W == ‘1’ then SEE STRBT;
9723 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9724 t = Bits32 (opcode, 15, 12);
9725 n = Bits32 (opcode, 19, 16);
9726 imm32 = Bits32 (opcode, 11, 0);
9727
9728 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9729 index = BitIsSet (opcode, 24);
9730 add = BitIsSet (opcode, 23);
9731 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9732
9733 // if t == 15 then UNPREDICTABLE;
9734 if (t == 15)
9735 return false;
9736
9737 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9738 if (wback && ((n == 15) || (n == t)))
9739 return false;
9740
9741 break;
9742
9743 default:
9744 return false;
9745 }
9746
9747 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9748 uint32_t Rn = ReadCoreReg (n, &success);
9749 if (!success)
9750 return false;
9751
9752 addr_t offset_addr;
9753 if (add)
9754 offset_addr = Rn + imm32;
9755 else
9756 offset_addr = Rn - imm32;
9757
9758 // address = if index then offset_addr else R[n];
9759 addr_t address;
9760 if (index)
9761 address = offset_addr;
9762 else
9763 address = Rn;
9764
9765 // MemU[address,1] = R[t]<7:0>;
9766 uint32_t Rt = ReadCoreReg (t, &success);
9767 if (!success)
9768 return false;
9769
Greg Claytonc07d4512011-04-26 23:48:45 +00009770 RegisterInfo base_reg;
9771 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9772 RegisterInfo data_reg;
9773 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticeef440002011-03-30 05:40:56 +00009774 EmulateInstruction::Context context;
9775 context.type = eContextRegisterStore;
9776 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9777
9778 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9779 return false;
9780
9781 // if wback then R[n] = offset_addr;
9782 if (wback)
9783 {
Caroline Tice523c5542011-04-13 00:42:12 +00009784 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009785 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009786 }
9787 }
9788 return true;
9789}
9790
9791// A8.6.194 STR (immediate, ARM)
9792bool
9793EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9794{
9795#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009796 if ConditionPassed() then
9797 EncodingSpecificOperations();
9798 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9799 address = if index then offset_addr else R[n];
9800 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9801 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009802#endif
9803
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009804 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009805
9806 if (ConditionPassed(opcode))
9807 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009808 uint32_t t;
9809 uint32_t n;
9810 uint32_t imm32;
9811 bool index;
9812 bool add;
9813 bool wback;
9814
9815 const uint32_t addr_byte_size = GetAddressByteSize();
9816
Caroline Ticed05b4902011-03-29 21:24:06 +00009817 switch (encoding)
9818 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009819 case eEncodingA1:
9820 // if P == ‘0’ && W == ‘1’ then SEE STRT;
9821 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH;
9822 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9823 t = Bits32 (opcode, 15, 12);
9824 n = Bits32 (opcode, 19, 16);
9825 imm32 = Bits32 (opcode, 11, 0);
9826
9827 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9828 index = BitIsSet (opcode, 24);
9829 add = BitIsSet (opcode, 23);
9830 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9831
9832 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9833 if (wback && ((n == 15) || (n == t)))
9834 return false;
9835
9836 break;
9837
9838 default:
9839 return false;
9840 }
9841
9842 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9843 uint32_t Rn = ReadCoreReg (n, &success);
9844 if (!success)
9845 return false;
9846
9847 addr_t offset_addr;
9848 if (add)
9849 offset_addr = Rn + imm32;
9850 else
9851 offset_addr = Rn - imm32;
9852
9853 // address = if index then offset_addr else R[n];
9854 addr_t address;
9855 if (index)
9856 address = offset_addr;
9857 else
9858 address = Rn;
9859
Greg Claytonc07d4512011-04-26 23:48:45 +00009860 RegisterInfo base_reg;
9861 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9862 RegisterInfo data_reg;
9863 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009864 EmulateInstruction::Context context;
9865 context.type = eContextRegisterStore;
9866 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9867
9868 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9869 uint32_t Rt = ReadCoreReg (t, &success);
9870 if (!success)
9871 return false;
9872
9873 if (t == 15)
9874 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009875 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009876 if (!success)
9877 return false;
9878
9879 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9880 return false;
9881 }
9882 else
9883 {
9884 if (!MemUWrite (context, address, Rt, addr_byte_size))
9885 return false;
9886 }
9887
9888 // if wback then R[n] = offset_addr;
9889 if (wback)
9890 {
9891 context.type = eContextAdjustBaseRegister;
9892 context.SetImmediate (offset_addr);
9893
9894 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9895 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009896 }
9897 }
9898 return true;
9899}
9900
Caroline Ticed05b4902011-03-29 21:24:06 +00009901// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009902// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9903// 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 +00009904bool
9905EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9906{
9907#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009908 if ConditionPassed() then
9909 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9910 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9911 address = if index then offset_addr else R[n];
9912 R[t] = MemA[address,4];
9913 R[t2] = MemA[address+4,4];
9914 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009915#endif
9916
Caroline Tice1697dd72011-03-30 17:11:45 +00009917 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009918
9919 if (ConditionPassed(opcode))
9920 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009921 uint32_t t;
9922 uint32_t t2;
9923 uint32_t n;
9924 uint32_t imm32;
9925 bool index;
9926 bool add;
9927 bool wback;
9928
Caroline Ticed05b4902011-03-29 21:24:06 +00009929 switch (encoding)
9930 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009931 case eEncodingT1:
9932 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
9933 //if Rn == ‘1111’ then SEE LDRD (literal);
9934 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9935 t = Bits32 (opcode, 15, 12);
9936 t2 = Bits32 (opcode, 11, 8);
9937 n = Bits32 (opcode, 19, 16);
9938 imm32 = Bits32 (opcode, 7, 0) << 2;
9939
9940 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
9941 index = BitIsSet (opcode, 24);
9942 add = BitIsSet (opcode, 23);
9943 wback = BitIsSet (opcode, 21);
9944
9945 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9946 if (wback && ((n == t) || (n == t2)))
9947 return false;
9948
9949 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9950 if (BadReg (t) || BadReg (t2) || (t == t2))
9951 return false;
9952
9953 break;
9954
9955 case eEncodingA1:
9956 //if Rn == ‘1111’ then SEE LDRD (literal);
9957 //if Rt<0> == ‘1’ then UNPREDICTABLE;
9958 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9959 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009960 if (BitIsSet (t, 0))
9961 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009962 t2 = t + 1;
9963 n = Bits32 (opcode, 19, 16);
9964 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9965
9966 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9967 index = BitIsSet (opcode, 24);
9968 add = BitIsSet (opcode, 23);
9969 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9970
9971 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
9972 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9973 return false;
9974
9975 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9976 if (wback && ((n == t) || (n == t2)))
9977 return false;
9978
9979 //if t2 == 15 then UNPREDICTABLE;
9980 if (t2 == 15)
9981 return false;
9982
9983 break;
9984
9985 default:
9986 return false;
9987 }
9988
9989 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9990 uint32_t Rn = ReadCoreReg (n, &success);
9991 if (!success)
9992 return false;
9993
9994 addr_t offset_addr;
9995 if (add)
9996 offset_addr = Rn + imm32;
9997 else
9998 offset_addr = Rn - imm32;
9999
10000 //address = if index then offset_addr else R[n];
10001 addr_t address;
10002 if (index)
10003 address = offset_addr;
10004 else
10005 address = Rn;
10006
10007 //R[t] = MemA[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +000010008 RegisterInfo base_reg;
10009 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1697dd72011-03-30 17:11:45 +000010010
10011 EmulateInstruction::Context context;
10012 context.type = eContextRegisterLoad;
10013 context.SetRegisterPlusOffset (base_reg, address - Rn);
10014
10015 const uint32_t addr_byte_size = GetAddressByteSize();
10016 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10017 if (!success)
10018 return false;
10019
10020 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10021 return false;
10022
10023 //R[t2] = MemA[address+4,4];
10024
10025 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10026 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10027 if (!success)
10028 return false;
10029
10030 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10031 return false;
10032
10033 //if wback then R[n] = offset_addr;
10034 if (wback)
10035 {
10036 context.type = eContextAdjustBaseRegister;
10037 context.SetAddress (offset_addr);
10038
10039 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10040 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010041 }
10042 }
10043 return true;
10044}
10045
Caroline Ticed05b4902011-03-29 21:24:06 +000010046// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010047// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10048// 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 +000010049bool
10050EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10051{
10052#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010053 if ConditionPassed() then
10054 EncodingSpecificOperations();
10055 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10056 address = if index then offset_addr else R[n];
10057 R[t] = MemA[address,4];
10058 R[t2] = MemA[address+4,4];
10059 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010060#endif
10061
Caroline Ticeeab301f2011-03-30 17:54:52 +000010062 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010063
10064 if (ConditionPassed(opcode))
10065 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010066 uint32_t t;
10067 uint32_t t2;
10068 uint32_t n;
10069 uint32_t m;
10070 bool index;
10071 bool add;
10072 bool wback;
10073
Caroline Ticed05b4902011-03-29 21:24:06 +000010074 switch (encoding)
10075 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010076 case eEncodingA1:
10077 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10078 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10079 t = Bits32 (opcode, 15, 12);
10080 if (BitIsSet (t, 0))
10081 return false;
10082 t2 = t + 1;
10083 n = Bits32 (opcode, 19, 16);
10084 m = Bits32 (opcode, 3, 0);
10085
10086 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10087 index = BitIsSet (opcode, 24);
10088 add = BitIsSet (opcode, 23);
10089 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10090
10091 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10092 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10093 return false;
10094
10095 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10096 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10097 return false;
10098
10099 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10100 if (wback && ((n == 15) || (n == t) || (n == t2)))
10101 return false;
10102
10103 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10104 if ((ArchVersion() < 6) && wback && (m == n))
10105 return false;
10106 break;
10107
10108 default:
10109 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010110 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010111
Caroline Ticeeab301f2011-03-30 17:54:52 +000010112 uint32_t Rn = ReadCoreReg (n, &success);
10113 if (!success)
10114 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010115 RegisterInfo base_reg;
10116 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010117
Caroline Ticeeab301f2011-03-30 17:54:52 +000010118 uint32_t Rm = ReadCoreReg (m, &success);
10119 if (!success)
10120 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010121 RegisterInfo offset_reg;
10122 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010123
Caroline Ticeeab301f2011-03-30 17:54:52 +000010124 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10125 addr_t offset_addr;
10126 if (add)
10127 offset_addr = Rn + Rm;
10128 else
10129 offset_addr = Rn - Rm;
10130
10131 // address = if index then offset_addr else R[n];
10132 addr_t address;
10133 if (index)
10134 address = offset_addr;
10135 else
10136 address = Rn;
10137
10138 EmulateInstruction::Context context;
10139 context.type = eContextRegisterLoad;
10140 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10141
10142 // R[t] = MemA[address,4];
10143 const uint32_t addr_byte_size = GetAddressByteSize();
10144 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10145 if (!success)
10146 return false;
10147
10148 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10149 return false;
10150
10151 // R[t2] = MemA[address+4,4];
10152
10153 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10154 if (!success)
10155 return false;
10156
10157 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10158 return false;
10159
10160 // if wback then R[n] = offset_addr;
10161 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010162 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010163 context.type = eContextAdjustBaseRegister;
10164 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010165
Caroline Ticeeab301f2011-03-30 17:54:52 +000010166 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10167 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010168 }
10169 }
10170 return true;
10171}
Caroline Ticed05b4902011-03-29 21:24:06 +000010172
10173// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010174// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10175// 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 +000010176bool
10177EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10178{
10179#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010180 if ConditionPassed() then
10181 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10182 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10183 address = if index then offset_addr else R[n];
10184 MemA[address,4] = R[t];
10185 MemA[address+4,4] = R[t2];
10186 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010187#endif
10188
Caroline Tice74467fe2011-03-30 19:02:56 +000010189 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010190
Caroline Tice74467fe2011-03-30 19:02:56 +000010191 if (ConditionPassed(opcode))
10192 {
10193 uint32_t t;
10194 uint32_t t2;
10195 uint32_t n;
10196 uint32_t imm32;
10197 bool index;
10198 bool add;
10199 bool wback;
10200
10201 switch (encoding)
10202 {
10203 case eEncodingT1:
10204 // if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10205 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10206 t = Bits32 (opcode, 15, 12);
10207 t2 = Bits32 (opcode, 11, 8);
10208 n = Bits32 (opcode, 19, 16);
10209 imm32 = Bits32 (opcode, 7, 0) << 2;
10210
10211 // index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
10212 index = BitIsSet (opcode, 24);
10213 add = BitIsSet (opcode, 23);
10214 wback = BitIsSet (opcode, 21);
10215
10216 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10217 if (wback && ((n == t) || (n == t2)))
10218 return false;
10219
10220 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10221 if ((n == 15) || BadReg (t) || BadReg (t2))
10222 return false;
10223
10224 break;
10225
10226 case eEncodingA1:
10227 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10228 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10229 t = Bits32 (opcode, 15, 12);
10230 if (BitIsSet (t, 0))
10231 return false;
10232
10233 t2 = t + 1;
10234 n = Bits32 (opcode, 19, 16);
10235 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10236
10237 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10238 index = BitIsSet (opcode, 24);
10239 add = BitIsSet (opcode, 23);
10240 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10241
10242 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10243 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10244 return false;
10245
10246 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10247 if (wback && ((n == 15) || (n == t) || (n == t2)))
10248 return false;
10249
10250 // if t2 == 15 then UNPREDICTABLE;
10251 if (t2 == 15)
10252 return false;
10253
10254 break;
10255
10256 default:
10257 return false;
10258 }
10259
Greg Claytonc07d4512011-04-26 23:48:45 +000010260 RegisterInfo base_reg;
10261 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010262
10263 uint32_t Rn = ReadCoreReg (n, &success);
10264 if (!success)
10265 return false;
10266
10267 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10268 addr_t offset_addr;
10269 if (add)
10270 offset_addr = Rn + imm32;
10271 else
10272 offset_addr = Rn - imm32;
10273
10274 //address = if index then offset_addr else R[n];
10275 addr_t address;
10276 if (index)
10277 address = offset_addr;
10278 else
10279 address = Rn;
10280
10281 //MemA[address,4] = R[t];
Greg Claytonc07d4512011-04-26 23:48:45 +000010282 RegisterInfo data_reg;
10283 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010284
10285 uint32_t data = ReadCoreReg (t, &success);
10286 if (!success)
10287 return false;
10288
10289 EmulateInstruction::Context context;
10290 context.type = eContextRegisterStore;
10291 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10292
10293 const uint32_t addr_byte_size = GetAddressByteSize();
10294
10295 if (!MemAWrite (context, address, data, addr_byte_size))
10296 return false;
10297
10298 //MemA[address+4,4] = R[t2];
Greg Claytonc07d4512011-04-26 23:48:45 +000010299 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010300 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10301
10302 data = ReadCoreReg (t2, &success);
10303 if (!success)
10304 return false;
10305
10306 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10307 return false;
10308
10309 //if wback then R[n] = offset_addr;
10310 if (wback)
10311 {
10312 context.type = eContextAdjustBaseRegister;
10313 context.SetAddress (offset_addr);
10314
10315 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10316 return false;
10317 }
10318 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010319 return true;
10320}
10321
10322
10323// A8.6.201 STRD (register)
10324bool
10325EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10326{
10327#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010328 if ConditionPassed() then
10329 EncodingSpecificOperations();
10330 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10331 address = if index then offset_addr else R[n];
10332 MemA[address,4] = R[t];
10333 MemA[address+4,4] = R[t2];
10334 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010335#endif
10336
Caroline Tice74467fe2011-03-30 19:02:56 +000010337 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010338
Caroline Tice74467fe2011-03-30 19:02:56 +000010339 if (ConditionPassed(opcode))
10340 {
10341 uint32_t t;
10342 uint32_t t2;
10343 uint32_t n;
10344 uint32_t m;
10345 bool index;
10346 bool add;
10347 bool wback;
10348
10349 switch (encoding)
10350 {
10351 case eEncodingA1:
10352 // if Rt<0> == ‘1’ then UNPREDICTABLE;
10353 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10354 t = Bits32 (opcode, 15, 12);
10355 if (BitIsSet (t, 0))
10356 return false;
10357
10358 t2 = t+1;
10359 n = Bits32 (opcode, 19, 16);
10360 m = Bits32 (opcode, 3, 0);
10361
10362 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
10363 index = BitIsSet (opcode, 24);
10364 add = BitIsSet (opcode, 23);
10365 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10366
10367 // if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
10368 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10369 return false;
10370
10371 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10372 if ((t2 == 15) || (m == 15))
10373 return false;
10374
10375 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10376 if (wback && ((n == 15) || (n == t) || (n == t2)))
10377 return false;
10378
10379 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010380 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010381 return false;
10382
10383 break;
10384
10385 default:
10386 return false;
10387 }
10388
Greg Claytonc07d4512011-04-26 23:48:45 +000010389 RegisterInfo base_reg;
10390 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10391 RegisterInfo offset_reg;
10392 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10393 RegisterInfo data_reg;
Caroline Tice74467fe2011-03-30 19:02:56 +000010394
10395 uint32_t Rn = ReadCoreReg (n, &success);
10396 if (!success)
10397 return false;
10398
10399 uint32_t Rm = ReadCoreReg (m, &success);
10400 if (!success)
10401 return false;
10402
10403 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10404 addr_t offset_addr;
10405 if (add)
10406 offset_addr = Rn + Rm;
10407 else
10408 offset_addr = Rn - Rm;
10409
10410 // address = if index then offset_addr else R[n];
10411 addr_t address;
10412 if (index)
10413 address = offset_addr;
10414 else
10415 address = Rn;
10416 // MemA[address,4] = R[t];
10417 uint32_t Rt = ReadCoreReg (t, &success);
10418 if (!success)
10419 return false;
10420
10421 EmulateInstruction::Context context;
10422 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +000010423 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010424 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10425
10426 const uint32_t addr_byte_size = GetAddressByteSize();
10427
10428 if (!MemAWrite (context, address, Rt, addr_byte_size))
10429 return false;
10430
10431 // MemA[address+4,4] = R[t2];
10432 uint32_t Rt2 = ReadCoreReg (t2, &success);
10433 if (!success)
10434 return false;
10435
Greg Claytonc07d4512011-04-26 23:48:45 +000010436 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010437
10438 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10439
10440 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10441 return false;
10442
10443 // if wback then R[n] = offset_addr;
10444 if (wback)
10445 {
10446 context.type = eContextAdjustBaseRegister;
10447 context.SetAddress (offset_addr);
10448
10449 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10450 return false;
10451
10452 }
10453 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010454 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010455}
10456
Caroline Tice4f605582011-03-31 00:02:51 +000010457// A8.6.319 VLDM
10458// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10459// an ARM core register.
10460bool
10461EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10462{
10463#if 0
10464 if ConditionPassed() then
10465 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10466 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010467 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010468 for r = 0 to regs-1
10469 if single_regs then
10470 S[d+r] = MemA[address,4]; address = address+4;
10471 else
10472 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10473 // Combine the word-aligned words in the correct order for current endianness.
10474 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10475#endif
10476
10477 bool success = false;
10478
10479 if (ConditionPassed(opcode))
10480 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010481 bool single_regs;
10482 bool add;
10483 bool wback;
10484 uint32_t d;
10485 uint32_t n;
10486 uint32_t imm32;
10487 uint32_t regs;
10488
Caroline Tice4f605582011-03-31 00:02:51 +000010489 switch (encoding)
10490 {
10491 case eEncodingT1:
10492 case eEncodingA1:
10493 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10494 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10495 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10496 // if P == U && W == ‘1’ then UNDEFINED;
10497 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10498 return false;
10499
10500 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10501 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10502 single_regs = false;
10503 add = BitIsSet (opcode, 23);
10504 wback = BitIsSet (opcode, 21);
10505
10506 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10507 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10508 n = Bits32 (opcode, 19, 16);
10509 imm32 = Bits32 (opcode, 7, 0) << 2;
10510
10511 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FLDMX”.
10512 regs = Bits32 (opcode, 7, 0) / 2;
10513
10514 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10515 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10516 return false;
10517
10518 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10519 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10520 return false;
10521
10522 break;
10523
10524 case eEncodingT2:
10525 case eEncodingA2:
10526 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10527 // if P == ‘0’ && U == ‘1’ && W == ‘1’ && Rn == ‘1101’ then SEE VPOP;
10528 // if P == ‘1’ && W == ‘0’ then SEE VLDR;
10529 // if P == U && W == ‘1’ then UNDEFINED;
10530 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10531 return false;
10532
10533 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10534 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10535 single_regs = true;
10536 add = BitIsSet (opcode, 23);
10537 wback = BitIsSet (opcode, 21);
10538 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10539 n = Bits32 (opcode, 19, 16);
10540
10541 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10542 imm32 = Bits32 (opcode, 7, 0) << 2;
10543 regs = Bits32 (opcode, 7, 0);
10544
10545 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10546 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10547 return false;
10548
10549 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10550 if ((regs == 0) || ((d + regs) > 32))
10551 return false;
10552 break;
10553
10554 default:
10555 return false;
10556 }
10557
Greg Claytonc07d4512011-04-26 23:48:45 +000010558 RegisterInfo base_reg;
10559 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4f605582011-03-31 00:02:51 +000010560
10561 uint32_t Rn = ReadCoreReg (n, &success);
10562 if (!success)
10563 return false;
10564
10565 // address = if add then R[n] else R[n]-imm32;
10566 addr_t address;
10567 if (add)
10568 address = Rn;
10569 else
10570 address = Rn - imm32;
10571
Greg Claytonc07d4512011-04-26 23:48:45 +000010572 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010573 EmulateInstruction::Context context;
10574
10575 if (wback)
10576 {
10577 uint32_t value;
10578 if (add)
10579 value = Rn + imm32;
10580 else
10581 value = Rn - imm32;
10582
10583 context.type = eContextAdjustBaseRegister;
10584 context.SetImmediateSigned (value - Rn);
10585 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10586 return false;
10587
10588 }
10589
10590 const uint32_t addr_byte_size = GetAddressByteSize();
10591 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10592
10593 context.type = eContextRegisterLoad;
10594
10595 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010596 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010597 {
10598 if (single_regs)
10599 {
10600 // S[d+r] = MemA[address,4]; address = address+4;
10601 context.SetRegisterPlusOffset (base_reg, address - Rn);
10602
10603 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10604 if (!success)
10605 return false;
10606
10607 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10608 return false;
10609
10610 address = address + 4;
10611 }
10612 else
10613 {
10614 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10615 context.SetRegisterPlusOffset (base_reg, address - Rn);
10616 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10617 if (!success)
10618 return false;
10619
10620 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10621 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10622 if (!success)
10623 return false;
10624
10625 address = address + 8;
10626 // // Combine the word-aligned words in the correct order for current endianness.
10627 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10628 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010629 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010630 {
10631 data = word1;
10632 data = (data << 32) | word2;
10633 }
10634 else
10635 {
10636 data = word2;
10637 data = (data << 32) | word1;
10638 }
10639
10640 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10641 return false;
10642 }
10643 }
10644 }
10645 return true;
10646}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010647
10648// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010649// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10650// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010651bool
10652EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10653{
10654#if 0
10655 if ConditionPassed() then
10656 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10657 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010658 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010659 for r = 0 to regs-1
10660 if single_regs then
10661 MemA[address,4] = S[d+r]; address = address+4;
10662 else
10663 // Store as two word-aligned words in the correct order for current endianness.
10664 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10665 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10666 address = address+8;
10667#endif
10668
10669 bool success = false;
10670
10671 if (ConditionPassed (opcode))
10672 {
10673 bool single_regs;
10674 bool add;
10675 bool wback;
10676 uint32_t d;
10677 uint32_t n;
10678 uint32_t imm32;
10679 uint32_t regs;
10680
10681 switch (encoding)
10682 {
10683 case eEncodingT1:
10684 case eEncodingA1:
10685 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10686 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10687 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10688 // if P == U && W == ‘1’ then UNDEFINED;
10689 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10690 return false;
10691
10692 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10693 // single_regs = FALSE; add = (U == ‘1’); wback = (W == ‘1’);
10694 single_regs = false;
10695 add = BitIsSet (opcode, 23);
10696 wback = BitIsSet (opcode, 21);
10697
10698 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
10699 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10700 n = Bits32 (opcode, 19, 16);
10701 imm32 = Bits32 (opcode, 7, 0) << 2;
10702
10703 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see “FSTMX”.
10704 regs = Bits32 (opcode, 7, 0) / 2;
10705
10706 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10707 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10708 return false;
10709
10710 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10711 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10712 return false;
10713
10714 break;
10715
10716 case eEncodingT2:
10717 case eEncodingA2:
10718 // if P == ‘0’ && U == ‘0’ && W == ‘0’ then SEE “Related encodings”;
10719 // if P == ‘1’ && U == ‘0’ && W == ‘1’ && Rn == ‘1101’ then SEE VPUSH;
10720 // if P == ‘1’ && W == ‘0’ then SEE VSTR;
10721 // if P == U && W == ‘1’ then UNDEFINED;
10722 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10723 return false;
10724
10725 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
10726 // single_regs = TRUE; add = (U == ‘1’); wback = (W == ‘1’); d = UInt(Vd:D); n = UInt(Rn);
10727 single_regs = true;
10728 add = BitIsSet (opcode, 23);
10729 wback = BitIsSet (opcode, 21);
10730 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10731 n = Bits32 (opcode, 19, 16);
10732
10733 // imm32 = ZeroExtend(imm8:’00’, 32); regs = UInt(imm8);
10734 imm32 = Bits32 (opcode, 7, 0) << 2;
10735 regs = Bits32 (opcode, 7, 0);
10736
10737 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10738 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10739 return false;
10740
10741 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10742 if ((regs == 0) || ((d + regs) > 32))
10743 return false;
10744
10745 break;
10746
10747 default:
10748 return false;
10749 }
10750
Greg Claytonc07d4512011-04-26 23:48:45 +000010751 RegisterInfo base_reg;
10752 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010753
10754 uint32_t Rn = ReadCoreReg (n, &success);
10755 if (!success)
10756 return false;
10757
10758 // address = if add then R[n] else R[n]-imm32;
10759 addr_t address;
10760 if (add)
10761 address = Rn;
10762 else
10763 address = Rn - imm32;
10764
10765 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +000010766 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010767 if (wback)
10768 {
10769 uint32_t value;
10770 if (add)
10771 value = Rn + imm32;
10772 else
10773 value = Rn - imm32;
10774
10775 context.type = eContextAdjustBaseRegister;
10776 context.SetRegisterPlusOffset (base_reg, value - Rn);
10777
10778 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10779 return false;
10780 }
10781
10782 const uint32_t addr_byte_size = GetAddressByteSize();
10783 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10784
10785 context.type = eContextRegisterStore;
10786 // for r = 0 to regs-1
10787 for (int r = 0; r < regs; ++r)
10788 {
Greg Claytonc07d4512011-04-26 23:48:45 +000010789
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010790 if (single_regs)
10791 {
10792 // MemA[address,4] = S[d+r]; address = address+4;
10793 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10794 if (!success)
10795 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010796
10797 RegisterInfo data_reg;
10798 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010799 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10800 if (!MemAWrite (context, address, data, addr_byte_size))
10801 return false;
10802
10803 address = address + 4;
10804 }
10805 else
10806 {
10807 // // Store as two word-aligned words in the correct order for current endianness.
10808 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10809 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10810 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10811 if (!success)
10812 return false;
10813
Greg Claytonc07d4512011-04-26 23:48:45 +000010814 RegisterInfo data_reg;
10815 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010816
Greg Clayton888a7332011-04-26 04:39:08 +000010817 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010818 {
10819 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10820 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10821 return false;
10822
10823 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10824 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10825 return false;
10826 }
10827 else
10828 {
10829 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10830 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10831 return false;
10832
10833 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10834 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10835 return false;
10836 }
10837 // address = address+8;
10838 address = address + 8;
10839 }
10840 }
10841 }
10842 return true;
10843}
10844
Caroline Tice917ad352011-03-31 05:05:30 +000010845// A8.6.320
10846// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10847// an optional offset.
10848bool
10849EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10850{
10851#if 0
10852 if ConditionPassed() then
10853 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10854 base = if n == 15 then Align(PC,4) else R[n];
10855 address = if add then (base + imm32) else (base - imm32);
10856 if single_reg then
10857 S[d] = MemA[address,4];
10858 else
10859 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10860 // Combine the word-aligned words in the correct order for current endianness.
10861 D[d] = if BigEndian() then word1:word2 else word2:word1;
10862#endif
10863
10864 bool success = false;
10865
10866 if (ConditionPassed (opcode))
10867 {
10868 bool single_reg;
10869 bool add;
10870 uint32_t imm32;
10871 uint32_t d;
10872 uint32_t n;
10873
10874 switch (encoding)
10875 {
10876 case eEncodingT1:
10877 case eEncodingA1:
10878 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10879 single_reg = false;
10880 add = BitIsSet (opcode, 23);
10881 imm32 = Bits32 (opcode, 7, 0) << 2;
10882
10883 // d = UInt(D:Vd); n = UInt(Rn);
10884 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10885 n = Bits32 (opcode, 19, 16);
10886
10887 break;
10888
10889 case eEncodingT2:
10890 case eEncodingA2:
10891 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
10892 single_reg = true;
10893 add = BitIsSet (opcode, 23);
10894 imm32 = Bits32 (opcode, 7, 0) << 2;
10895
10896 // d = UInt(Vd:D); n = UInt(Rn);
10897 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10898 n = Bits32 (opcode, 19, 16);
10899
10900 break;
10901
10902 default:
10903 return false;
10904 }
Greg Claytonc07d4512011-04-26 23:48:45 +000010905 RegisterInfo base_reg;
10906 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice917ad352011-03-31 05:05:30 +000010907
10908 uint32_t Rn = ReadCoreReg (n, &success);
10909 if (!success)
10910 return false;
10911
10912 // base = if n == 15 then Align(PC,4) else R[n];
10913 uint32_t base;
10914 if (n == 15)
10915 base = AlignPC (Rn);
10916 else
10917 base = Rn;
10918
10919 // address = if add then (base + imm32) else (base - imm32);
10920 addr_t address;
10921 if (add)
10922 address = base + imm32;
10923 else
10924 address = base - imm32;
10925
10926 const uint32_t addr_byte_size = GetAddressByteSize();
10927 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
10928
10929 EmulateInstruction::Context context;
10930 context.type = eContextRegisterLoad;
10931 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010932
Caroline Tice917ad352011-03-31 05:05:30 +000010933 if (single_reg)
10934 {
10935 // S[d] = MemA[address,4];
10936 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10937 if (!success)
10938 return false;
10939
10940 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
10941 return false;
10942 }
10943 else
10944 {
10945 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
10946 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10947 if (!success)
10948 return false;
10949
10950 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
10951 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10952 if (!success)
10953 return false;
10954 // // Combine the word-aligned words in the correct order for current endianness.
10955 // D[d] = if BigEndian() then word1:word2 else word2:word1;
10956 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000010957 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000010958 {
10959 data64 = word1;
10960 data64 = (data64 << 32) | word2;
10961 }
10962 else
10963 {
10964 data64 = word2;
10965 data64 = (data64 << 32) | word1;
10966 }
10967
10968 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
10969 return false;
10970 }
10971 }
10972 return true;
10973}
Caroline Tice424652f2011-03-31 05:38:36 +000010974
10975// A8.6.400 VSTR
10976// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
10977// optional offset.
10978bool
10979EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
10980{
10981#if 0
10982 if ConditionPassed() then
10983 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10984 address = if add then (R[n] + imm32) else (R[n] - imm32);
10985 if single_reg then
10986 MemA[address,4] = S[d];
10987 else
10988 // Store as two word-aligned words in the correct order for current endianness.
10989 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
10990 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
10991#endif
10992
10993 bool success = false;
10994
10995 if (ConditionPassed (opcode))
10996 {
10997 bool single_reg;
10998 bool add;
10999 uint32_t imm32;
11000 uint32_t d;
11001 uint32_t n;
11002
11003 switch (encoding)
11004 {
11005 case eEncodingT1:
11006 case eEncodingA1:
11007 // single_reg = FALSE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
11008 single_reg = false;
11009 add = BitIsSet (opcode, 23);
11010 imm32 = Bits32 (opcode, 7, 0) << 2;
11011
11012 // d = UInt(D:Vd); n = UInt(Rn);
11013 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11014 n = Bits32 (opcode, 19, 16);
11015
11016 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11017 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11018 return false;
11019
11020 break;
11021
11022 case eEncodingT2:
11023 case eEncodingA2:
11024 // single_reg = TRUE; add = (U == ‘1’); imm32 = ZeroExtend(imm8:’00’, 32);
11025 single_reg = true;
11026 add = BitIsSet (opcode, 23);
11027 imm32 = Bits32 (opcode, 7, 0) << 2;
11028
11029 // d = UInt(Vd:D); n = UInt(Rn);
11030 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11031 n = Bits32 (opcode, 19, 16);
11032
11033 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11034 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11035 return false;
11036
11037 break;
11038
11039 default:
11040 return false;
11041 }
11042
Greg Claytonc07d4512011-04-26 23:48:45 +000011043 RegisterInfo base_reg;
11044 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011045
11046 uint32_t Rn = ReadCoreReg (n, &success);
11047 if (!success)
11048 return false;
11049
11050 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11051 addr_t address;
11052 if (add)
11053 address = Rn + imm32;
11054 else
11055 address = Rn - imm32;
11056
11057 const uint32_t addr_byte_size = GetAddressByteSize();
11058 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11059
Greg Claytonc07d4512011-04-26 23:48:45 +000011060 RegisterInfo data_reg;
11061 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011062 EmulateInstruction::Context context;
11063 context.type = eContextRegisterStore;
11064 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11065
11066 if (single_reg)
11067 {
11068 // MemA[address,4] = S[d];
11069 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11070 if (!success)
11071 return false;
11072
11073 if (!MemAWrite (context, address, data, addr_byte_size))
11074 return false;
11075 }
11076 else
11077 {
11078 // // Store as two word-aligned words in the correct order for current endianness.
11079 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11080 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11081 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11082 if (!success)
11083 return false;
11084
Greg Clayton888a7332011-04-26 04:39:08 +000011085 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011086 {
11087 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11088 return false;
11089
11090 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11091 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11092 return false;
11093 }
11094 else
11095 {
11096 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11097 return false;
11098
11099 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11100 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11101 return false;
11102 }
11103 }
11104 }
11105 return true;
11106}
Caroline Tice9121b352011-03-31 16:41:19 +000011107
11108// A8.6.307 VLDI1 (multiple single elements)
11109// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11110// element of each register is loaded.
11111bool
11112EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11113{
11114#if 0
11115 if ConditionPassed() then
11116 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11117 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11118 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11119 for r = 0 to regs-1
11120 for e = 0 to elements-1
11121 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11122 address = address + ebytes;
11123#endif
11124
11125 bool success = false;
11126
11127 if (ConditionPassed (opcode))
11128 {
11129 uint32_t regs;
11130 uint32_t alignment;
11131 uint32_t ebytes;
11132 uint32_t esize;
11133 uint32_t elements;
11134 uint32_t d;
11135 uint32_t n;
11136 uint32_t m;
11137 bool wback;
11138 bool register_index;
11139
11140 switch (encoding)
11141 {
11142 case eEncodingT1:
11143 case eEncodingA1:
11144 {
11145 // case type of
11146 // when ‘0111’
11147 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11148 // when ‘1010’
11149 // regs = 2; if align == ‘11’ then UNDEFINED;
11150 // when ‘0110’
11151 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11152 // when ‘0010’
11153 // regs = 4;
11154 // otherwise
11155 // SEE “Related encodings”;
11156 uint32_t type = Bits32 (opcode, 11, 8);
11157 uint32_t align = Bits32 (opcode, 5, 4);
11158 if (type == 7) // '0111'
11159 {
11160 regs = 1;
11161 if (BitIsSet (align, 1))
11162 return false;
11163 }
11164 else if (type == 10) // '1010'
11165 {
11166 regs = 2;
11167 if (align == 3)
11168 return false;
11169
11170 }
11171 else if (type == 6) // '0110'
11172 {
11173 regs = 3;
11174 if (BitIsSet (align, 1))
11175 return false;
11176 }
11177 else if (type == 2) // '0010'
11178 {
11179 regs = 4;
11180 }
11181 else
11182 return false;
11183
11184 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11185 if (align == 0)
11186 alignment = 1;
11187 else
11188 alignment = 4 << align;
11189
11190 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11191 ebytes = 1 << Bits32 (opcode, 7, 6);
11192 esize = 8 * ebytes;
11193 elements = 8 / ebytes;
11194
11195 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11196 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11197 n = Bits32 (opcode, 19, 15);
11198 m = Bits32 (opcode, 3, 0);
11199
11200 // wback = (m != 15); register_index = (m != 15 && m != 13);
11201 wback = (m != 15);
11202 register_index = ((m != 15) && (m != 13));
11203
11204 // if d+regs > 32 then UNPREDICTABLE;
11205 if ((d + regs) > 32)
11206 return false;
11207 }
11208 break;
11209
11210 default:
11211 return false;
11212 }
11213
Greg Claytonc07d4512011-04-26 23:48:45 +000011214 RegisterInfo base_reg;
11215 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice9121b352011-03-31 16:41:19 +000011216
11217 uint32_t Rn = ReadCoreReg (n, &success);
11218 if (!success)
11219 return false;
11220
11221 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11222 addr_t address = Rn;
11223 if ((address % alignment) != 0)
11224 return false;
11225
11226 EmulateInstruction::Context context;
11227 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11228 if (wback)
11229 {
11230 uint32_t Rm = ReadCoreReg (m, &success);
11231 if (!success)
11232 return false;
11233
11234 uint32_t offset;
11235 if (register_index)
11236 offset = Rm;
11237 else
11238 offset = 8 * regs;
11239
11240 uint32_t value = Rn + offset;
11241 context.type = eContextAdjustBaseRegister;
11242 context.SetRegisterPlusOffset (base_reg, offset);
11243
11244 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11245 return false;
11246
11247 }
11248
11249 // for r = 0 to regs-1
11250 for (int r = 0; r < regs; ++r)
11251 {
11252 // for e = 0 to elements-1
11253 uint64_t assembled_data = 0;
11254 for (int e = 0; e < elements; ++e)
11255 {
11256 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11257 context.type = eContextRegisterLoad;
11258 context.SetRegisterPlusOffset (base_reg, address - Rn);
11259 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11260 if (!success)
11261 return false;
11262
11263 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11264
11265 // address = address + ebytes;
11266 address = address + ebytes;
11267 }
11268 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11269 return false;
11270 }
11271 }
11272 return true;
11273}
11274
Caroline Ticeb6281b12011-03-31 17:58:23 +000011275// A8.6.308 VLD1 (single element to one lane)
11276//
11277bool
11278EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11279{
11280#if 0
11281 if ConditionPassed() then
11282 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11283 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11284 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11285 Elem[D[d],index,esize] = MemU[address,ebytes];
11286#endif
11287
11288 bool success = false;
11289
11290 if (ConditionPassed (opcode))
11291 {
11292 uint32_t ebytes;
11293 uint32_t esize;
11294 uint32_t index;
11295 uint32_t alignment;
11296 uint32_t d;
11297 uint32_t n;
11298 uint32_t m;
11299 bool wback;
11300 bool register_index;
11301
11302 switch (encoding)
11303 {
11304 case eEncodingT1:
11305 case eEncodingA1:
11306 {
11307 uint32_t size = Bits32 (opcode, 11, 10);
11308 uint32_t index_align = Bits32 (opcode, 7, 4);
11309 // if size == ‘11’ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011310 if (size == 3)
11311 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011312 // case size of
11313 if (size == 0) // when '00'
11314 {
11315 // if index_align<0> != ‘0’ then UNDEFINED;
11316 if (BitIsClear (index_align, 0))
11317 return false;
11318
11319 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11320 ebytes = 1;
11321 esize = 8;
11322 index = Bits32 (index_align, 3, 1);
11323 alignment = 1;
11324 }
11325 else if (size == 1) // when ‘01’
11326 {
11327 // if index_align<1> != ‘0’ then UNDEFINED;
11328 if (BitIsClear (index_align, 1))
11329 return false;
11330
11331 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11332 ebytes = 2;
11333 esize = 16;
11334 index = Bits32 (index_align, 3, 2);
11335
11336 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11337 if (BitIsClear (index_align, 0))
11338 alignment = 1;
11339 else
11340 alignment = 2;
11341 }
11342 else if (size == 2) // when ‘10’
11343 {
11344 // if index_align<2> != ‘0’ then UNDEFINED;
11345 if (BitIsClear (index_align, 2))
11346 return false;
11347
11348 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11349 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11350 return false;
11351
11352 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11353 ebytes = 4;
11354 esize = 32;
11355 index = Bit32 (index_align, 3);
11356
11357 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11358 if (Bits32 (index_align, 1, 0) == 0)
11359 alignment = 1;
11360 else
11361 alignment = 4;
11362 }
11363 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11364 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11365 n = Bits32 (opcode, 19, 16);
11366 m = Bits32 (opcode, 3, 0);
11367
11368 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11369 wback = (m != 15);
11370 register_index = ((m != 15) && (m != 13));
11371
11372 if (n == 15)
11373 return false;
11374
11375 }
11376 break;
11377
11378 default:
11379 return false;
11380 }
11381
Greg Claytonc07d4512011-04-26 23:48:45 +000011382 RegisterInfo base_reg;
11383 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011384
11385 uint32_t Rn = ReadCoreReg (n, &success);
11386 if (!success)
11387 return false;
11388
11389 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11390 addr_t address = Rn;
11391 if ((address % alignment) != 0)
11392 return false;
11393
11394 EmulateInstruction::Context context;
11395 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11396 if (wback)
11397 {
11398 uint32_t Rm = ReadCoreReg (m, &success);
11399 if (!success)
11400 return false;
11401
11402 uint32_t offset;
11403 if (register_index)
11404 offset = Rm;
11405 else
11406 offset = ebytes;
11407
11408 uint32_t value = Rn + offset;
11409
11410 context.type = eContextAdjustBaseRegister;
11411 context.SetRegisterPlusOffset (base_reg, offset);
11412
11413 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11414 return false;
11415 }
11416
11417 // Elem[D[d],index,esize] = MemU[address,ebytes];
11418 uint32_t element = MemURead (context, address, esize, 0, &success);
11419 if (!success)
11420 return false;
11421
11422 element = element << (index * esize);
11423
11424 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11425 if (!success)
11426 return false;
11427
11428 uint64_t all_ones = -1;
11429 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11430 // at element & to the right of element.
11431 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011432 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 +000011433 // now mask should be 0's where element goes & 1's
11434 // everywhere else.
11435
11436 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11437 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11438
11439 context.type = eContextRegisterLoad;
11440 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11441 return false;
11442 }
11443 return true;
11444}
11445
Caroline Tice1e542e32011-03-31 18:44:04 +000011446// A8.6.391 VST1 (multiple single elements)
11447// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11448// interleaving. Every element of each register is stored.
11449bool
11450EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11451{
11452#if 0
11453 if ConditionPassed() then
11454 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11455 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11456 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11457 for r = 0 to regs-1
11458 for e = 0 to elements-1
11459 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11460 address = address + ebytes;
11461#endif
11462
11463 bool success = false;
11464
11465 if (ConditionPassed (opcode))
11466 {
11467 uint32_t regs;
11468 uint32_t alignment;
11469 uint32_t ebytes;
11470 uint32_t esize;
11471 uint32_t elements;
11472 uint32_t d;
11473 uint32_t n;
11474 uint32_t m;
11475 bool wback;
11476 bool register_index;
11477
11478 switch (encoding)
11479 {
11480 case eEncodingT1:
11481 case eEncodingA1:
11482 {
11483 uint32_t type = Bits32 (opcode, 11, 8);
11484 uint32_t align = Bits32 (opcode, 5, 4);
11485
11486 // case type of
11487 if (type == 7) // when ‘0111’
11488 {
11489 // regs = 1; if align<1> == ‘1’ then UNDEFINED;
11490 regs = 1;
11491 if (BitIsSet (align, 1))
11492 return false;
11493 }
11494 else if (type == 10) // when ‘1010’
11495 {
11496 // regs = 2; if align == ‘11’ then UNDEFINED;
11497 regs = 2;
11498 if (align == 3)
11499 return false;
11500 }
11501 else if (type == 6) // when ‘0110’
11502 {
11503 // regs = 3; if align<1> == ‘1’ then UNDEFINED;
11504 regs = 3;
11505 if (BitIsSet (align, 1))
11506 return false;
11507 }
11508 else if (type == 2) // when ‘0010’
11509 // regs = 4;
11510 regs = 4;
11511 else // otherwise
11512 // SEE “Related encodings”;
11513 return false;
11514
11515 // alignment = if align == ‘00’ then 1 else 4 << UInt(align);
11516 if (align == 0)
11517 alignment = 0;
11518 else
11519 alignment = 4 << align;
11520
11521 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11522 ebytes = 1 << Bits32 (opcode,7, 6);
11523 esize = 8 * ebytes;
11524 elements = 8 / ebytes;
11525
11526 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11527 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11528 n = Bits32 (opcode, 19, 16);
11529 m = Bits32 (opcode, 3, 0);
11530
11531 // wback = (m != 15); register_index = (m != 15 && m != 13);
11532 wback = (m != 15);
11533 register_index = ((m != 15) && (m != 13));
11534
11535 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11536 if ((d + regs) > 32)
11537 return false;
11538
11539 if (n == 15)
11540 return false;
11541
11542 }
11543 break;
11544
11545 default:
11546 return false;
11547 }
11548
Greg Claytonc07d4512011-04-26 23:48:45 +000011549 RegisterInfo base_reg;
11550 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011551
11552 uint32_t Rn = ReadCoreReg (n, &success);
11553 if (!success)
11554 return false;
11555
11556 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11557 addr_t address = Rn;
11558 if ((address % alignment) != 0)
11559 return false;
11560
11561 EmulateInstruction::Context context;
11562 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11563 if (wback)
11564 {
11565 uint32_t Rm = ReadCoreReg (m, &success);
11566 if (!success)
11567 return false;
11568
11569 uint32_t offset;
11570 if (register_index)
11571 offset = Rm;
11572 else
11573 offset = 8 * regs;
11574
11575 context.type = eContextAdjustBaseRegister;
11576 context.SetRegisterPlusOffset (base_reg, offset);
11577
11578 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11579 return false;
11580 }
11581
Greg Claytonc07d4512011-04-26 23:48:45 +000011582 RegisterInfo data_reg;
Caroline Tice1e542e32011-03-31 18:44:04 +000011583 context.type = eContextRegisterStore;
Caroline Tice1e542e32011-03-31 18:44:04 +000011584 // for r = 0 to regs-1
11585 for (int r = 0; r < regs; ++r)
11586 {
Greg Claytonc07d4512011-04-26 23:48:45 +000011587 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011588 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11589 if (!success)
11590 return false;
11591
11592 // for e = 0 to elements-1
11593 for (int e = 0; e < elements; ++e)
11594 {
11595 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011596 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011597
11598 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11599 if (!MemUWrite (context, address, word, ebytes))
11600 return false;
11601
11602 // address = address + ebytes;
11603 address = address + ebytes;
11604 }
11605 }
11606 }
11607 return true;
11608}
11609
Caroline Tice7b880942011-03-31 19:17:12 +000011610// A8.6.392 VST1 (single element from one lane)
11611// This instruction stores one element to memory from one element of a register.
11612bool
11613EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11614{
11615#if 0
11616 if ConditionPassed() then
11617 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11618 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11619 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11620 MemU[address,ebytes] = Elem[D[d],index,esize];
11621#endif
11622
11623 bool success = false;
11624
11625 if (ConditionPassed (opcode))
11626 {
11627 uint32_t ebytes;
11628 uint32_t esize;
11629 uint32_t index;
11630 uint32_t alignment;
11631 uint32_t d;
11632 uint32_t n;
11633 uint32_t m;
11634 bool wback;
11635 bool register_index;
11636
11637 switch (encoding)
11638 {
11639 case eEncodingT1:
11640 case eEncodingA1:
11641 {
11642 uint32_t size = Bits32 (opcode, 11, 10);
11643 uint32_t index_align = Bits32 (opcode, 7, 4);
11644
11645 // if size == ‘11’ then UNDEFINED;
11646 if (size == 3)
11647 return false;
11648
11649 // case size of
11650 if (size == 0) // when ‘00’
11651 {
11652 // if index_align<0> != ‘0’ then UNDEFINED;
11653 if (BitIsClear (index_align, 0))
11654 return false;
11655 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11656 ebytes = 1;
11657 esize = 8;
11658 index = Bits32 (index_align, 3, 1);
11659 alignment = 1;
11660 }
11661 else if (size == 1) // when ‘01’
11662 {
11663 // if index_align<1> != ‘0’ then UNDEFINED;
11664 if (BitIsClear (index_align, 1))
11665 return false;
11666
11667 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11668 ebytes = 2;
11669 esize = 16;
11670 index = Bits32 (index_align, 3, 2);
11671
11672 // alignment = if index_align<0> == ‘0’ then 1 else 2;
11673 if (BitIsClear (index_align, 0))
11674 alignment = 1;
11675 else
11676 alignment = 2;
11677 }
11678 else if (size == 2) // when ‘10’
11679 {
11680 // if index_align<2> != ‘0’ then UNDEFINED;
11681 if (BitIsClear (index_align, 2))
11682 return false;
11683
11684 // if index_align<1:0> != ‘00’ && index_align<1:0> != ‘11’ then UNDEFINED;
11685 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11686 return false;
11687
11688 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11689 ebytes = 4;
11690 esize = 32;
11691 index = Bit32 (index_align, 3);
11692
11693 // alignment = if index_align<1:0> == ‘00’ then 1 else 4;
11694 if (Bits32 (index_align, 1, 0) == 0)
11695 alignment = 1;
11696 else
11697 alignment = 4;
11698 }
11699 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11700 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11701 n = Bits32 (opcode, 19, 16);
11702 m = Bits32 (opcode, 3, 0);
11703
11704 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11705 wback = (m != 15);
11706 register_index = ((m != 15) && (m != 13));
11707
11708 if (n == 15)
11709 return false;
11710 }
11711 break;
11712
11713 default:
11714 return false;
11715 }
11716
Greg Claytonc07d4512011-04-26 23:48:45 +000011717 RegisterInfo base_reg;
11718 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011719
11720 uint32_t Rn = ReadCoreReg (n, &success);
11721 if (!success)
11722 return false;
11723
11724 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11725 addr_t address = Rn;
11726 if ((address % alignment) != 0)
11727 return false;
11728
11729 EmulateInstruction::Context context;
11730 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11731 if (wback)
11732 {
11733 uint32_t Rm = ReadCoreReg (m, &success);
11734 if (!success)
11735 return false;
11736
11737 uint32_t offset;
11738 if (register_index)
11739 offset = Rm;
11740 else
11741 offset = ebytes;
11742
11743 context.type = eContextAdjustBaseRegister;
11744 context.SetRegisterPlusOffset (base_reg, offset);
11745
11746 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11747 return false;
11748 }
11749
11750 // MemU[address,ebytes] = Elem[D[d],index,esize];
11751 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11752 if (!success)
11753 return false;
11754
11755 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11756
Greg Claytonc07d4512011-04-26 23:48:45 +000011757 RegisterInfo data_reg;
11758 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011759 context.type = eContextRegisterStore;
11760 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11761
11762 if (!MemUWrite (context, address, word, ebytes))
11763 return false;
11764 }
11765 return true;
11766}
11767
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011768// A8.6.309 VLD1 (single element to all lanes)
11769// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011770bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011771EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011772{
11773#if 0
11774 if ConditionPassed() then
11775 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11776 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11777 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11778 replicated_element = Replicate(MemU[address,ebytes], elements);
11779 for r = 0 to regs-1
11780 D[d+r] = replicated_element;
11781#endif
11782
11783 bool success = false;
11784
11785 if (ConditionPassed (opcode))
11786 {
11787 uint32_t ebytes;
11788 uint32_t elements;
11789 uint32_t regs;
11790 uint32_t alignment;
11791 uint32_t d;
11792 uint32_t n;
11793 uint32_t m;
11794 bool wback;
11795 bool register_index;
11796
11797 switch (encoding)
11798 {
11799 case eEncodingT1:
11800 case eEncodingA1:
11801 {
11802 //if size == ‘11’ || (size == ‘00’ && a == ‘1’) then UNDEFINED;
11803 uint32_t size = Bits32 (opcode, 7, 6);
11804 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11805 return false;
11806
11807 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == ‘0’ then 1 else 2;
11808 ebytes = 1 << size;
11809 elements = 8 / ebytes;
11810 if (BitIsClear (opcode, 5))
11811 regs = 1;
11812 else
11813 regs = 2;
11814
11815 //alignment = if a == ‘0’ then 1 else ebytes;
11816 if (BitIsClear (opcode, 4))
11817 alignment = 1;
11818 else
11819 alignment = ebytes;
11820
11821 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11822 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11823 n = Bits32 (opcode, 19, 16);
11824 m = Bits32 (opcode, 3, 0);
11825
11826 //wback = (m != 15); register_index = (m != 15 && m != 13);
11827 wback = (m != 15);
11828 register_index = ((m != 15) && (m != 13));
11829
11830 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11831 if ((d + regs) > 32)
11832 return false;
11833
11834 if (n == 15)
11835 return false;
11836 }
11837 break;
11838
11839 default:
11840 break;
11841 }
11842
Greg Claytonc07d4512011-04-26 23:48:45 +000011843 RegisterInfo base_reg;
11844 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice93767b82011-03-31 21:15:29 +000011845
11846 uint32_t Rn = ReadCoreReg (n, &success);
11847 if (!success)
11848 return false;
11849
11850 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11851 addr_t address = Rn;
11852 if ((address % alignment) != 0)
11853 return false;
11854
11855 EmulateInstruction::Context context;
11856 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11857 if (wback)
11858 {
11859 uint32_t Rm = ReadCoreReg (m, &success);
11860 if (!success)
11861 return false;
11862
11863 uint32_t offset;
11864 if (register_index)
11865 offset = Rm;
11866 else
11867 offset = ebytes;
11868
11869 context.type = eContextAdjustBaseRegister;
11870 context.SetRegisterPlusOffset (base_reg, offset);
11871
11872 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11873 return false;
11874 }
11875
11876 // replicated_element = Replicate(MemU[address,ebytes], elements);
11877
11878 context.type = eContextRegisterLoad;
11879 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11880 if (!success)
11881 return false;
11882
11883 uint64_t replicated_element;
11884 uint32_t esize = ebytes * 8;
11885 for (int e = 0; e < elements; ++e)
11886 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11887
11888 // for r = 0 to regs-1
11889 for (int r = 0; r < regs; ++r)
11890 {
11891 // D[d+r] = replicated_element;
11892 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11893 return false;
11894 }
11895 }
11896 return true;
11897}
11898
Caroline Tice1f954f52011-04-11 15:51:10 +000011899// B6.2.13 SUBS PC, LR and related instructions
11900//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
11901// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
11902bool
11903EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
11904{
11905#if 0
11906 if ConditionPassed() then
11907 EncodingSpecificOperations();
11908 if CurrentInstrSet() == InstrSet_ThumbEE then
11909 UNPREDICTABLE;
11910 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11911 case opcode of
11912 when 0000 result = R[n] AND operand2; // AND
11913 when 0001 result = R[n] EOR operand2; // EOR
11914 when 0010 (result, -, -) = AddWithCarry(R[n], NOT(operand2), 1’); // SUB
11915 when 0011 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, 1’); // RSB
11916 when 0100 (result, -, -) = AddWithCarry(R[n], operand2, 0’); // ADD
11917 when 0101 (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
11918 when 0110 (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
11919 when 0111 (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
11920 when 1100 result = R[n] OR operand2; // ORR
11921 when 1101 result = operand2; // MOV
11922 when 1110 result = R[n] AND NOT(operand2); // BIC
11923 when 1111 result = NOT(operand2); // MVN
11924 CPSRWriteByInstr(SPSR[], 1111’, TRUE);
11925 BranchWritePC(result);
11926#endif
11927
11928 bool success = false;
11929
11930 if (ConditionPassed (opcode))
11931 {
11932 uint32_t n;
11933 uint32_t m;
11934 uint32_t imm32;
11935 bool register_form;
11936 ARM_ShifterType shift_t;
11937 uint32_t shift_n;
11938 uint32_t code;
11939
11940 switch (encoding)
11941 {
11942 case eEncodingT1:
11943 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
11944 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = ‘0010’; // = SUB
11945 n = 14;
11946 imm32 = Bits32 (opcode, 7, 0);
11947 register_form = false;
11948 code = 2;
11949
11950 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
11951 if (InITBlock() && !LastInITBlock())
11952 return false;
11953
11954 break;
11955
11956 case eEncodingA1:
11957 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
11958 n = Bits32 (opcode, 19, 16);
11959 imm32 = ARMExpandImm (opcode);
11960 register_form = false;
11961 code = Bits32 (opcode, 24, 21);
11962
11963 break;
11964
11965 case eEncodingA2:
11966 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
11967 n = Bits32 (opcode, 19, 16);
11968 m = Bits32 (opcode, 3, 0);
11969 register_form = true;
11970
11971 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
11972 shift_n = DecodeImmShiftARM (opcode, shift_t);
11973
11974 break;
11975
11976 default:
11977 return false;
11978 }
11979
11980 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11981 uint32_t operand2;
11982 if (register_form)
11983 {
11984 uint32_t Rm = ReadCoreReg (m, &success);
11985 if (!success)
11986 return false;
11987
11988 operand2 = Shift (Rm, shift_t, shift_n, APSR_C);
11989
11990 }
11991 else
11992 {
11993 operand2 = imm32;
11994 }
11995
11996 uint32_t Rn = ReadCoreReg (n, &success);
11997 if (!success)
11998 return false;
11999
12000 AddWithCarryResult result;
12001
12002 // case opcode of
12003 switch (code)
12004 {
12005 case 0: // when ‘0000’
12006 // result = R[n] AND operand2; // AND
12007 result.result = Rn & operand2;
12008 break;
12009
12010 case 1: // when ‘0001’
12011 // result = R[n] EOR operand2; // EOR
12012 result.result = Rn ^ operand2;
12013 break;
12014
12015 case 2: // when ‘0010’
12016 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), ‘1’); // SUB
12017 result = AddWithCarry (Rn, ~(operand2), 1);
12018 break;
12019
12020 case 3: // when ‘0011’
12021 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, ‘1’); // RSB
12022 result = AddWithCarry (~(Rn), operand2, 1);
12023 break;
12024
12025 case 4: // when ‘0100’
12026 // (result, -, -) = AddWithCarry(R[n], operand2, ‘0’); // ADD
12027 result = AddWithCarry (Rn, operand2, 0);
12028 break;
12029
12030 case 5: // when ‘0101’
12031 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12032 result = AddWithCarry (Rn, operand2, APSR_C);
12033 break;
12034
12035 case 6: // when ‘0110’
12036 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12037 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12038 break;
12039
12040 case 7: // when ‘0111’
12041 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12042 result = AddWithCarry (~(Rn), operand2, APSR_C);
12043 break;
12044
12045 case 10: // when ‘1100’
12046 // result = R[n] OR operand2; // ORR
12047 result.result = Rn | operand2;
12048 break;
12049
12050 case 11: // when ‘1101’
12051 // result = operand2; // MOV
12052 result.result = operand2;
12053 break;
12054
12055 case 12: // when ‘1110’
12056 // result = R[n] AND NOT(operand2); // BIC
12057 result.result = Rn & ~(operand2);
12058 break;
12059
12060 case 15: // when ‘1111’
12061 // result = NOT(operand2); // MVN
12062 result.result = ~(operand2);
12063 break;
12064
12065 default:
12066 return false;
12067 }
12068 // CPSRWriteByInstr(SPSR[], ‘1111’, TRUE);
12069
12070 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12071 // the best.
12072 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12073 if (!success)
12074 return false;
12075
12076 CPSRWriteByInstr (spsr, 15, true);
12077
12078 // BranchWritePC(result);
12079 EmulateInstruction::Context context;
12080 context.type = eContextAdjustPC;
12081 context.SetImmediate (result.result);
12082
12083 BranchWritePC (context, result.result);
12084 }
12085 return true;
12086}
12087
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012088EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012089EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012090{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012091 static ARMOpcode
12092 g_arm_opcodes[] =
12093 {
12094 //----------------------------------------------------------------------
12095 // Prologue instructions
12096 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012097
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012098 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012099 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12100 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012101
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012102 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012103 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12104 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012105 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012106 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12107 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12108 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012109
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012110 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012111 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12112 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012113
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012114 // push one register
12115 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012116 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012117
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012118 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012119 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12120 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012121
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012122 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012123 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012124 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012125
Caroline Tice4f605582011-03-31 00:02:51 +000012126 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12127 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12128 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12129 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012130
12131 //----------------------------------------------------------------------
12132 // Supervisor Call (previously Software Interrupt)
12133 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012134 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012135
12136 //----------------------------------------------------------------------
12137 // Branch instructions
12138 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012139 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012140 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012141 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12142 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12143 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012144 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012145 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012146 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012147 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012148
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012149 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012150 // Data-processing instructions
12151 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012152 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012153 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012154 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012155 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012156 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012157 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012158 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012159 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012160 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012161 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012162 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012163 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12164 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012165 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012166 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012167 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012168 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012169 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012170 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012171 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012172 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012173 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012174 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012175 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012176 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012177 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012178 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012179 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012180 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012181 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012182 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012183 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012184 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012185 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012186 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012187 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012188 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012189 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012190 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012191 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012192 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012193 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012194 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012195 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012196 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012197 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012198 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012199 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012200 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012201 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012202 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012203 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012204 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012205 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012206 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012207
Caroline Tice89c6d582011-03-29 19:53:44 +000012208 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012209 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12210 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012211 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012212 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012213 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012214 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012215 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012216 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012217 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012218 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012219 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012220 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012221 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012222 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012223 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012224 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012225 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012226 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012227 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012228 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012229 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012230 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012231 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012232 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012233 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012234 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012235 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012236 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012237 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012238 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012239 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012240 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012241 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012242 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012243 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012244 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012245
12246 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012247 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12248 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012249
12250 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012251 // Load instructions
12252 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012253 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12254 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12255 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12256 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12257 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12258 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12259 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12260 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12261 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12262 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12263 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12264 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12265 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12266 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12267 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12268 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12269 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12270 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012271 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12272 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12273 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12274 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012275 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12276 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012277 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012278
12279 //----------------------------------------------------------------------
12280 // Store instructions
12281 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012282 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12283 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12284 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12285 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12286 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12287 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12288 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12289 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12290 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012291 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012292 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012293 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12294 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12295 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12296 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12297 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012298 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012299
Caroline Tice6bf65162011-03-03 17:42:58 +000012300 //----------------------------------------------------------------------
12301 // Other instructions
12302 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012303 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12304 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12305 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12306 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12307 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012308
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012309 };
12310 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12311
12312 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12313 {
Greg Clayton888a7332011-04-26 04:39:08 +000012314 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12315 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012316 return &g_arm_opcodes[i];
12317 }
12318 return NULL;
12319}
Greg Clayton64c84432011-01-21 22:02:52 +000012320
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012321
12322EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012323EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012324{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012325
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012326 static ARMOpcode
12327 g_thumb_opcodes[] =
12328 {
12329 //----------------------------------------------------------------------
12330 // Prologue instructions
12331 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012332
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012333 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012334 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12335 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12336 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012337
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012338 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012339 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012340 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012341 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012342 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012343 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012344
Johnny Chen864a8e82011-02-18 00:07:39 +000012345 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012346 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012347
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012348 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012349 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12350 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12351 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12352 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12353 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012354
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012355 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012356 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12357 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012358
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012359 //----------------------------------------------------------------------
12360 // Epilogue instructions
12361 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012362
Caroline Tice4f605582011-03-31 00:02:51 +000012363 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12364 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12365 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12366 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12367 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12368 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12369 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012370
12371 //----------------------------------------------------------------------
12372 // Supervisor Call (previously Software Interrupt)
12373 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012374 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012375
12376 //----------------------------------------------------------------------
12377 // If Then makes up to four following instructions conditional.
12378 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012379 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012380
12381 //----------------------------------------------------------------------
12382 // Branch instructions
12383 //----------------------------------------------------------------------
12384 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012385 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12386 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12387 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12388 { 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 +000012389 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012390 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012391 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012392 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12393 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012394 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012395 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012396 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012397 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012398 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012399 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012400 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012401 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012402 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012403 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012404
12405 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012406 // Data-processing instructions
12407 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012408 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012409 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012410 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012411 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12412 { 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 +000012413 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012414 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012415 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012416 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012417 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012418 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12419 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12420 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012421 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012422 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012423 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012424 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12425 { 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 +000012426 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012427 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012428 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012429 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12430 { 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 +000012431 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012432 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012433 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012434 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12435 { 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 +000012436 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012437 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012438 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012439 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12440 { 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 +000012441 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012442 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12443 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012444 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012445 { 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 +000012446 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012447 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012448 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012449 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12450 { 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 +000012451 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012452 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12453 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12454 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12455 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012456 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012457 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12458 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12459 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12460 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012461 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012462 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12463 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012464 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012465 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12466 { 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 +000012467 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012468 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012469 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012470 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012471 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012472 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012473 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012474 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12475 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012476
Johnny Chen7c5234d2011-02-18 23:41:11 +000012477
Johnny Chen338bf542011-02-10 19:29:03 +000012478 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012479 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012480 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012481 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012482 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012483 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012484 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012485 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12486 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12487 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012488 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012489 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012490 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012491 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12492 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012493 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012494 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012495 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012496 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12497 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012498 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012499 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12500 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012501 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012502 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012503 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012504 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012505 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012506 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12507 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012508 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012509 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12510 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012511 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012512 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12513 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012514 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012515 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12516 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012517 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012518 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12519 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012520 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012521 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12522 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012523 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012524 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012525 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012526 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012527 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012528 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12529 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012530 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012531 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012532 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012533 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012534
12535 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012536 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012537
12538 //----------------------------------------------------------------------
12539 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12540 // otherwise the wrong instructions will be selected.
12541 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012542
Caroline Tice080bf612011-04-05 18:46:00 +000012543 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12544 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12545
Johnny Chen26863dc2011-02-09 23:43:29 +000012546 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012547 // Load instructions
12548 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012549 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12550 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12551 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12552 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12553 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12554 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12555 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012556 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012557 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12558 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12559 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12560 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12561 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012562 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012563 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12564 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12565 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12566 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12567 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12568 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12569 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12570 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12571 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12572 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12573 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12574 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12575 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12576 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12577 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12578 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12579 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12580 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12581 { 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 +000012582 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012583 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12584 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12585 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12586 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012587 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12588 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012589 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012590
12591 //----------------------------------------------------------------------
12592 // Store instructions
12593 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012594 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12595 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12596 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12597 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12598 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12599 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12600 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12601 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12602 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12603 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12604 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12605 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12606 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12607 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12608 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12609 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012610 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12611 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12612 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12613 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12614 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012615 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012616
12617 //----------------------------------------------------------------------
12618 // Other instructions
12619 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012620 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12621 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12622 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12623 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12624 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12625 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12626 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12627 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012628 };
12629
12630 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12631 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12632 {
Greg Clayton888a7332011-04-26 04:39:08 +000012633 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12634 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012635 return &g_thumb_opcodes[i];
12636 }
12637 return NULL;
12638}
Greg Clayton64c84432011-01-21 22:02:52 +000012639
Greg Clayton31e2a382011-01-30 20:03:56 +000012640bool
Greg Clayton395fc332011-02-15 21:59:32 +000012641EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012642{
Caroline Tice080bf612011-04-05 18:46:00 +000012643 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012644 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012645 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012646 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012647 {
Greg Clayton395fc332011-02-15 21:59:32 +000012648 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12649 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12650 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12651 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12652 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12653 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12654 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12655 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12656 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12657 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Johnny Chen1d29a852011-04-26 18:51:57 +000012658 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12659 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
Greg Clayton31e2a382011-01-30 20:03:56 +000012660 }
12661 return m_arm_isa != 0;
12662}
12663
Caroline Tice080bf612011-04-05 18:46:00 +000012664bool
Greg Clayton888a7332011-04-26 04:39:08 +000012665EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012666{
Greg Clayton888a7332011-04-26 04:39:08 +000012667 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12668 {
12669 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12670 m_opcode_mode = eModeThumb;
12671 else
12672 {
12673 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012674
Greg Clayton888a7332011-04-26 04:39:08 +000012675 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12676 m_opcode_mode = eModeARM;
12677 else if (addr_class == eAddressClassCodeAlternateISA)
12678 m_opcode_mode = eModeThumb;
12679 else
12680 return false;
12681 }
12682 if (m_opcode_mode == eModeThumb)
12683 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12684 else
12685 m_opcode_cpsr = CPSR_MODE_USR;
12686 return true;
12687 }
12688 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012689}
Greg Clayton31e2a382011-01-30 20:03:56 +000012690
Greg Clayton64c84432011-01-21 22:02:52 +000012691bool
12692EmulateInstructionARM::ReadInstruction ()
12693{
12694 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012695 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012696 if (success)
12697 {
12698 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12699 if (success)
12700 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012701 Context read_inst_context;
12702 read_inst_context.type = eContextReadOpcode;
12703 read_inst_context.SetNoArgs ();
12704
Greg Claytonb3448432011-03-24 21:19:54 +000012705 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012706 {
Greg Claytonb3448432011-03-24 21:19:54 +000012707 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012708 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012709
12710 if (success)
12711 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012712 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012713 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012714 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012715 }
12716 else
12717 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012718 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012719 }
12720 }
12721 }
12722 else
12723 {
Greg Claytonb3448432011-03-24 21:19:54 +000012724 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012725 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012726 }
12727 }
12728 }
12729 if (!success)
12730 {
Greg Claytonb3448432011-03-24 21:19:54 +000012731 m_opcode_mode = eModeInvalid;
12732 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012733 }
12734 return success;
12735}
12736
Johnny Chenee9b1f72011-02-09 01:00:31 +000012737uint32_t
12738EmulateInstructionARM::ArchVersion ()
12739{
12740 return m_arm_isa;
12741}
12742
Greg Clayton64c84432011-01-21 22:02:52 +000012743bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012744EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012745{
Greg Clayton888a7332011-04-26 04:39:08 +000012746 // If we are ignoring conditions, then always return true.
12747 // this allows us to iterate over disassembly code and still
12748 // emulate an instruction even if we don't have all the right
12749 // bits set in the CPSR register...
12750 if (m_ignore_conditions)
12751 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000012752
Greg Clayton7bc39082011-03-24 23:53:38 +000012753 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012754
12755 if (cond == UINT32_MAX)
12756 return false;
12757
12758 bool result = false;
12759 switch (UnsignedBits(cond, 3, 1))
12760 {
Caroline Tice080bf612011-04-05 18:46:00 +000012761 case 0:
12762 if (m_opcode_cpsr == 0)
12763 return true;
12764 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12765 break;
12766 case 1:
12767 if (m_opcode_cpsr == 0)
12768 return true;
12769 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12770 break;
12771 case 2:
12772 if (m_opcode_cpsr == 0)
12773 return true;
12774 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12775 break;
12776 case 3:
12777 if (m_opcode_cpsr == 0)
12778 return true;
12779 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12780 break;
12781 case 4:
12782 if (m_opcode_cpsr == 0)
12783 return true;
12784 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12785 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012786 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012787 if (m_opcode_cpsr == 0)
12788 return true;
12789 else
12790 {
Greg Claytonb3448432011-03-24 21:19:54 +000012791 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12792 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012793 result = n == v;
12794 }
12795 break;
12796 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012797 if (m_opcode_cpsr == 0)
12798 return true;
12799 else
12800 {
Greg Claytonb3448432011-03-24 21:19:54 +000012801 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12802 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12803 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012804 }
12805 break;
12806 case 7:
12807 result = true;
12808 break;
12809 }
12810
12811 if (cond & 1)
12812 result = !result;
12813 return result;
12814}
12815
Johnny Chen9ee056b2011-02-08 00:06:35 +000012816uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012817EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012818{
Greg Claytonb3448432011-03-24 21:19:54 +000012819 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012820 {
12821 default:
12822 case eModeInvalid:
12823 break;
12824
12825 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012826 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012827
12828 case eModeThumb:
12829 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12830 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012831 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012832 const uint32_t byte_size = m_opcode.GetByteSize();
12833 if (byte_size == 2)
12834 {
12835 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12836 return Bits32(opcode, 11, 7);
12837 }
12838 else
12839 {
12840 assert (byte_size == 4);
12841 if (Bits32(opcode, 31, 27) == 0x1e &&
12842 Bits32(opcode, 15, 14) == 0x02 &&
12843 Bits32(opcode, 12, 12) == 0x00 &&
12844 Bits32(opcode, 25, 22) <= 0x0d)
12845 {
12846 return Bits32(opcode, 25, 22);
12847 }
12848 }
12849
12850 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012851 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012852 }
12853 return UINT32_MAX; // Return invalid value
12854}
12855
Johnny Chen9ee056b2011-02-08 00:06:35 +000012856bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012857EmulateInstructionARM::InITBlock()
12858{
12859 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12860}
12861
12862bool
12863EmulateInstructionARM::LastInITBlock()
12864{
12865 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12866}
12867
Caroline Ticeb27771d2011-03-03 22:37:46 +000012868bool
12869EmulateInstructionARM::BadMode (uint32_t mode)
12870{
12871
12872 switch (mode)
12873 {
12874 case 16: return false; // '10000'
12875 case 17: return false; // '10001'
12876 case 18: return false; // '10010'
12877 case 19: return false; // '10011'
12878 case 22: return false; // '10110'
12879 case 23: return false; // '10111'
12880 case 27: return false; // '11011'
12881 case 31: return false; // '11111'
12882 default: return true;
12883 }
12884 return true;
12885}
12886
12887bool
12888EmulateInstructionARM::CurrentModeIsPrivileged ()
12889{
Greg Claytonb3448432011-03-24 21:19:54 +000012890 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012891
12892 if (BadMode (mode))
12893 return false;
12894
12895 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000012896 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012897
12898 return true;
12899}
12900
12901void
12902EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
12903{
12904 bool privileged = CurrentModeIsPrivileged();
12905
12906 uint32_t tmp_cpsr = 0;
12907
Greg Claytonb3448432011-03-24 21:19:54 +000012908 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012909
12910 if (BitIsSet (bytemask, 3))
12911 {
12912 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
12913 if (affect_execstate)
12914 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
12915 }
12916
12917 if (BitIsSet (bytemask, 2))
12918 {
12919 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
12920 }
12921
12922 if (BitIsSet (bytemask, 1))
12923 {
12924 if (affect_execstate)
12925 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
12926 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
12927 if (privileged)
12928 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
12929 }
12930
12931 if (BitIsSet (bytemask, 0))
12932 {
12933 if (privileged)
12934 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
12935 if (affect_execstate)
12936 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
12937 if (privileged)
12938 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
12939 }
12940
Greg Claytonb3448432011-03-24 21:19:54 +000012941 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012942}
12943
12944
Johnny Chen098ae2d2011-02-12 00:50:05 +000012945bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000012946EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
12947{
12948 addr_t target;
12949
Johnny Chenee9b1f72011-02-09 01:00:31 +000012950 // Check the current instruction set.
12951 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012952 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012953 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000012954 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012955
Johnny Chen9ee056b2011-02-08 00:06:35 +000012956 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012957 return false;
12958
12959 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012960}
12961
12962// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
12963bool
Johnny Chen668b4512011-02-15 21:08:58 +000012964EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012965{
12966 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000012967 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
12968 // we want to record it and issue a WriteRegister callback so the clients
12969 // can track the mode changes accordingly.
12970 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012971
12972 if (BitIsSet(addr, 0))
12973 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012974 if (CurrentInstrSet() != eModeThumb)
12975 {
12976 SelectInstrSet(eModeThumb);
12977 cpsr_changed = true;
12978 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012979 target = addr & 0xfffffffe;
Greg Claytonc07d4512011-04-26 23:48:45 +000012980 context.SetISA (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012981 }
12982 else if (BitIsClear(addr, 1))
12983 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012984 if (CurrentInstrSet() != eModeARM)
12985 {
12986 SelectInstrSet(eModeARM);
12987 cpsr_changed = true;
12988 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012989 target = addr & 0xfffffffc;
Greg Claytonc07d4512011-04-26 23:48:45 +000012990 context.SetISA (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012991 }
12992 else
12993 return false; // address<1:0> == '10' => UNPREDICTABLE
12994
Johnny Chen0f309db2011-02-09 19:11:32 +000012995 if (cpsr_changed)
12996 {
Johnny Chen558133b2011-02-09 23:59:17 +000012997 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000012998 return false;
12999 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013000 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013001 return false;
13002
13003 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013004}
Greg Clayton64c84432011-01-21 22:02:52 +000013005
Johnny Chenee9b1f72011-02-09 01:00:31 +000013006// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13007bool
Johnny Chen668b4512011-02-15 21:08:58 +000013008EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000013009{
13010 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000013011 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000013012 else
13013 return BranchWritePC((const Context)context, addr);
13014}
13015
Johnny Chen26863dc2011-02-09 23:43:29 +000013016// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13017bool
Johnny Chen668b4512011-02-15 21:08:58 +000013018EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000013019{
13020 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013021 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013022 else
13023 return BranchWritePC((const Context)context, addr);
13024}
13025
Johnny Chenee9b1f72011-02-09 01:00:31 +000013026EmulateInstructionARM::Mode
13027EmulateInstructionARM::CurrentInstrSet ()
13028{
Greg Claytonb3448432011-03-24 21:19:54 +000013029 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013030}
13031
Greg Claytonb3448432011-03-24 21:19:54 +000013032// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013033// ReadInstruction() is performed. This function has a side effect of updating
13034// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013035bool
13036EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13037{
Greg Claytonb3448432011-03-24 21:19:54 +000013038 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013039 switch (arm_or_thumb)
13040 {
13041 default:
13042 return false;
13043 eModeARM:
13044 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013045 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013046 break;
13047 eModeThumb:
13048 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013049 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013050 break;
13051 }
13052 return true;
13053}
13054
Johnny Chenef21b592011-02-10 01:52:38 +000013055// This function returns TRUE if the processor currently provides support for
13056// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13057// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13058bool
13059EmulateInstructionARM::UnalignedSupport()
13060{
13061 return (ArchVersion() >= ARMv7);
13062}
13063
Johnny Chenbf6ad172011-02-11 01:29:53 +000013064// The main addition and subtraction instructions can produce status information
13065// about both unsigned carry and signed overflow conditions. This status
13066// information can be used to synthesize multi-word additions and subtractions.
13067EmulateInstructionARM::AddWithCarryResult
13068EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13069{
13070 uint32_t result;
13071 uint8_t carry_out;
13072 uint8_t overflow;
13073
13074 uint64_t unsigned_sum = x + y + carry_in;
13075 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13076
13077 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013078// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013079 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013080
13081 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013082 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013083 else
13084 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013085
13086 AddWithCarryResult res = { result, carry_out, overflow };
13087 return res;
13088}
13089
Johnny Chen157b9592011-02-18 21:13:05 +000013090uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013091EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013092{
Johnny Chene39f22d2011-02-19 01:36:13 +000013093 uint32_t reg_kind, reg_num;
13094 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013095 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013096 case SP_REG:
13097 reg_kind = eRegisterKindGeneric;
13098 reg_num = LLDB_REGNUM_GENERIC_SP;
13099 break;
13100 case LR_REG:
13101 reg_kind = eRegisterKindGeneric;
13102 reg_num = LLDB_REGNUM_GENERIC_RA;
13103 break;
13104 case PC_REG:
13105 reg_kind = eRegisterKindGeneric;
13106 reg_num = LLDB_REGNUM_GENERIC_PC;
13107 break;
13108 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013109 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013110 {
13111 reg_kind = eRegisterKindDWARF;
13112 reg_num = dwarf_r0 + num;
13113 }
Johnny Chen157b9592011-02-18 21:13:05 +000013114 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013115 {
13116 assert(0 && "Invalid register number");
13117 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013118 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013119 }
13120 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013121 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013122
13123 // Read our register.
13124 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13125
13126 // When executing an ARM instruction , PC reads as the address of the current
13127 // instruction plus 8.
13128 // When executing a Thumb instruction , PC reads as the address of the current
13129 // instruction plus 4.
13130 if (num == 15)
13131 {
13132 if (CurrentInstrSet() == eModeARM)
13133 val += 8;
13134 else
13135 val += 4;
13136 }
Johnny Chen157b9592011-02-18 21:13:05 +000013137
13138 return val;
13139}
13140
Johnny Chenca67d1c2011-02-17 01:35:27 +000013141// Write the result to the ARM core register Rd, and optionally update the
13142// condition flags based on the result.
13143//
13144// This helper method tries to encapsulate the following pseudocode from the
13145// ARM Architecture Reference Manual:
13146//
13147// if d == 15 then // Can only occur for encoding A1
13148// ALUWritePC(result); // setflags is always FALSE here
13149// else
13150// R[d] = result;
13151// if setflags then
13152// APSR.N = result<31>;
13153// APSR.Z = IsZeroBit(result);
13154// APSR.C = carry;
13155// // APSR.V unchanged
13156//
13157// In the above case, the API client does not pass in the overflow arg, which
13158// defaults to ~0u.
13159bool
Johnny Chen10530c22011-02-17 22:37:12 +000013160EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13161 const uint32_t result,
13162 const uint32_t Rd,
13163 bool setflags,
13164 const uint32_t carry,
13165 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013166{
13167 if (Rd == 15)
13168 {
13169 if (!ALUWritePC (context, result))
13170 return false;
13171 }
13172 else
13173 {
Johnny Chena695f952011-02-23 21:24:25 +000013174 uint32_t reg_kind, reg_num;
13175 switch (Rd)
13176 {
13177 case SP_REG:
13178 reg_kind = eRegisterKindGeneric;
13179 reg_num = LLDB_REGNUM_GENERIC_SP;
13180 break;
13181 case LR_REG:
13182 reg_kind = eRegisterKindGeneric;
13183 reg_num = LLDB_REGNUM_GENERIC_RA;
13184 break;
13185 default:
13186 reg_kind = eRegisterKindDWARF;
13187 reg_num = dwarf_r0 + Rd;
13188 }
13189 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013190 return false;
13191 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013192 return WriteFlags (context, result, carry, overflow);
13193 }
13194 return true;
13195}
13196
13197// This helper method tries to encapsulate the following pseudocode from the
13198// ARM Architecture Reference Manual:
13199//
13200// APSR.N = result<31>;
13201// APSR.Z = IsZeroBit(result);
13202// APSR.C = carry;
13203// APSR.V = overflow
13204//
13205// Default arguments can be specified for carry and overflow parameters, which means
13206// not to update the respective flags.
13207bool
13208EmulateInstructionARM::WriteFlags (Context &context,
13209 const uint32_t result,
13210 const uint32_t carry,
13211 const uint32_t overflow)
13212{
Greg Claytonb3448432011-03-24 21:19:54 +000013213 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013214 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13215 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013216 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013217 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013218 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013219 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013220 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013221 {
13222 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13223 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013224 }
13225 return true;
13226}
13227
Greg Clayton64c84432011-01-21 22:02:52 +000013228bool
Greg Clayton888a7332011-04-26 04:39:08 +000013229EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013230{
Johnny Chenc315f862011-02-05 00:46:10 +000013231 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013232 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013233 m_it_session.ITAdvance();
13234
Greg Clayton888a7332011-04-26 04:39:08 +000013235 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013236
13237 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013238 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013239 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013240 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13241
13242 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013243 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013244
Greg Clayton888a7332011-04-26 04:39:08 +000013245 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13246 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013247
Greg Clayton888a7332011-04-26 04:39:08 +000013248 bool success = false;
13249 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013250 {
Greg Clayton888a7332011-04-26 04:39:08 +000013251 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
13252 dwarf_cpsr,
13253 0,
13254 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013255 }
13256
Greg Clayton888a7332011-04-26 04:39:08 +000013257 // Only return false if we are unable to read the CPSR if we care about conditions
13258 if (success == false && m_ignore_conditions == false)
13259 return false;
13260
13261 uint32_t orig_pc_value = 0;
13262 if (auto_advance_pc)
13263 {
13264 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13265 if (!success)
13266 return false;
13267 }
13268
13269 // Call the Emulate... function.
13270 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13271 if (!success)
13272 return false;
13273
13274 if (auto_advance_pc)
13275 {
13276 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13277 if (!success)
13278 return false;
13279
13280 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13281 {
13282 if (opcode_data->size == eSize32)
13283 after_pc_value += 4;
13284 else if (opcode_data->size == eSize16)
13285 after_pc_value += 2;
13286
13287 EmulateInstruction::Context context;
13288 context.type = eContextAdvancePC;
13289 context.SetNoArgs();
13290 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13291 return false;
13292
13293 }
13294 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013295 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013296}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013297
13298bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013299EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013300{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013301 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013302 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013303 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013304 return false;
13305 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013306
13307 static ConstString opcode_key ("opcode");
13308 static ConstString before_key ("before_state");
13309 static ConstString after_key ("after_state");
13310
13311 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013312
13313 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013314 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013315 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013316 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013317 return false;
13318 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013319 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013320
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013321 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13322 {
13323 m_opcode_mode = eModeARM;
13324 m_opcode.SetOpcode32 (test_opcode);
13325 }
13326 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13327 {
13328 m_opcode_mode = eModeThumb;
13329 if (test_opcode < 0x10000)
13330 m_opcode.SetOpcode16 (test_opcode);
13331 else
13332 m_opcode.SetOpcode32 (test_opcode);
13333
13334 }
13335 else
13336 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013337 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013338 return false;
13339 }
13340
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013341 EmulationStateARM before_state;
13342 EmulationStateARM after_state;
13343
Caroline Ticedfb2e202011-04-22 05:08:45 +000013344 value_sp = test_data->GetValueForKey (before_key);
13345 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013346 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013347 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013348 return false;
13349 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013350
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013351 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013352 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013353 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013354 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013355 return false;
13356 }
13357
Caroline Ticedfb2e202011-04-22 05:08:45 +000013358 value_sp = test_data->GetValueForKey (after_key);
13359 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013360 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013361 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013362 return false;
13363 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013364
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013365 state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013366 if (!after_state.LoadStateFromDictionary (state_dictionary))
13367 {
13368 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13369 return false;
13370 }
13371
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013372 SetBaton ((void *) &before_state);
13373 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13374 &EmulationStateARM::WritePseudoMemory,
13375 &EmulationStateARM::ReadPseudoRegister,
13376 &EmulationStateARM::WritePseudoRegister);
13377
Greg Clayton888a7332011-04-26 04:39:08 +000013378 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013379 if (!success)
13380 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013381 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013382 return false;
13383 }
13384
13385 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013386 if (!success)
13387 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13388
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013389 return success;
13390}
Greg Claytonc07d4512011-04-26 23:48:45 +000013391//
13392//
13393//const char *
13394//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13395//{
13396// if (reg_kind == eRegisterKindGeneric)
13397// {
13398// switch (reg_num)
13399// {
13400// case LLDB_REGNUM_GENERIC_PC: return "pc";
13401// case LLDB_REGNUM_GENERIC_SP: return "sp";
13402// case LLDB_REGNUM_GENERIC_FP: return "fp";
13403// case LLDB_REGNUM_GENERIC_RA: return "lr";
13404// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13405// default: return NULL;
13406// }
13407// }
13408// else if (reg_kind == eRegisterKindDWARF)
13409// {
13410// return GetARMDWARFRegisterName (reg_num);
13411// }
13412// return NULL;
13413//}
13414//
13415bool
13416EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
Greg Clayton888a7332011-04-26 04:39:08 +000013417{
Greg Claytonc07d4512011-04-26 23:48:45 +000013418 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13419
13420 UnwindPlan::Row row;
13421 UnwindPlan::Row::RegisterLocation regloc;
13422
13423 // Our previous Call Frame Address is the stack pointer
13424 row.SetCFARegister (dwarf_sp);
13425
13426 // Our previous PC is in the LR
13427 regloc.SetInRegister(dwarf_lr);
13428 row.SetRegisterInfo (dwarf_pc, regloc);
13429 unwind_plan.AppendRow (row);
13430
13431 // All other registers are the same.
13432
13433 unwind_plan.SetSourceName ("EmulateInstructionARM");
13434 return true;
Greg Clayton888a7332011-04-26 04:39:08 +000013435}
13436
Greg Claytonc07d4512011-04-26 23:48:45 +000013437
13438
13439