blob: a08adc866c9f97df034d841472f872784132cd6f [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013#include "EmulationStateARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000014#include "lldb/Core/ArchSpec.h"
Caroline Tice080bf612011-04-05 18:46:00 +000015#include "lldb/Core/Address.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000016#include "lldb/Core/ConstString.h"
Caroline Tice080bf612011-04-05 18:46:00 +000017#include "lldb/Core/PluginManager.h"
Caroline Tice6b8d3b52011-04-19 23:30:03 +000018#include "lldb/Core/Stream.h"
Greg Claytonc07d4512011-04-26 23:48:45 +000019#include "lldb/Symbol/UnwindPlan.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000020
Greg Claytonf29a08f2011-02-09 17:41:27 +000021#include "Plugins/Process/Utility/ARMDefines.h"
22#include "Plugins/Process/Utility/ARMUtils.h"
23#include "Utility/ARM_DWARF_Registers.h"
24
Johnny Chen9b8d7832011-02-02 01:13:56 +000025#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000026 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000027
28using namespace lldb;
29using namespace lldb_private;
30
Johnny Chene97c0d52011-02-18 19:32:20 +000031// Convenient macro definitions.
Greg Claytonb3448432011-03-24 21:19:54 +000032#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
33#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000034
Caroline Ticef55261f2011-02-18 22:24:22 +000035#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
36
Johnny Chen0e00af22011-02-10 19:40:42 +000037//----------------------------------------------------------------------
38//
39// ITSession implementation
40//
41//----------------------------------------------------------------------
42
Johnny Chen93070472011-02-04 23:02:47 +000043// A8.6.50
44// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
45static unsigned short CountITSize(unsigned ITMask) {
46 // First count the trailing zeros of the IT mask.
47 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
48 if (TZ > 3)
49 {
50 printf("Encoding error: IT Mask '0000'\n");
51 return 0;
52 }
53 return (4 - TZ);
54}
55
56// Init ITState. Note that at least one bit is always 1 in mask.
57bool ITSession::InitIT(unsigned short bits7_0)
58{
59 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
60 if (ITCounter == 0)
61 return false;
62
63 // A8.6.50 IT
64 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
65 if (FirstCond == 0xF)
66 {
67 printf("Encoding error: IT FirstCond '1111'\n");
68 return false;
69 }
70 if (FirstCond == 0xE && ITCounter != 1)
71 {
72 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
73 return false;
74 }
75
76 ITState = bits7_0;
77 return true;
78}
79
80// Update ITState if necessary.
81void ITSession::ITAdvance()
82{
83 assert(ITCounter);
84 --ITCounter;
85 if (ITCounter == 0)
86 ITState = 0;
87 else
88 {
89 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
90 SetBits32(ITState, 4, 0, NewITState4_0);
91 }
92}
93
94// Return true if we're inside an IT Block.
95bool ITSession::InITBlock()
96{
97 return ITCounter != 0;
98}
99
Johnny Chenc315f862011-02-05 00:46:10 +0000100// Return true if we're the last instruction inside an IT Block.
101bool ITSession::LastInITBlock()
102{
103 return ITCounter == 1;
104}
105
Johnny Chen93070472011-02-04 23:02:47 +0000106// Get condition bits for the current thumb instruction.
107uint32_t ITSession::GetCond()
108{
Johnny Chenc315f862011-02-05 00:46:10 +0000109 if (InITBlock())
110 return Bits32(ITState, 7, 4);
111 else
112 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000113}
114
Greg Clayton64c84432011-01-21 22:02:52 +0000115// ARM constants used during decoding
116#define REG_RD 0
117#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000118#define SP_REG 13
119#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000120#define PC_REG 15
121#define PC_REGLIST_BIT 0x8000
122
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMv4T (1u << 1)
125#define ARMv5T (1u << 2)
126#define ARMv5TE (1u << 3)
127#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000128#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000129#define ARMv6K (1u << 6)
130#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000131#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000132#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000133#define ARMvAll (0xffffffffu)
134
Johnny Chen9b8d7832011-02-02 01:13:56 +0000135#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
136#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice1697dd72011-03-30 17:11:45 +0000137#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000138#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000139#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000140#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000141
Caroline Tice4f605582011-03-31 00:02:51 +0000142#define No_VFP 0
143#define VFPv1 (1u << 1)
144#define VFPv2 (1u << 2)
145#define VFPv3 (1u << 3)
146#define AdvancedSIMD (1u << 4)
147
148#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
149#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
150#define VFPv2v3 (VFPv2 | VFPv3)
151
Johnny Chen0e00af22011-02-10 19:40:42 +0000152//----------------------------------------------------------------------
153//
154// EmulateInstructionARM implementation
155//
156//----------------------------------------------------------------------
157
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000158void
159EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000160{
Caroline Tice080bf612011-04-05 18:46:00 +0000161 PluginManager::RegisterPlugin (GetPluginNameStatic (),
162 GetPluginDescriptionStatic (),
163 CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000164}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000165
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000166void
167EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000168{
Caroline Tice080bf612011-04-05 18:46:00 +0000169 PluginManager::UnregisterPlugin (CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000170}
171
Caroline Tice080bf612011-04-05 18:46:00 +0000172const char *
173EmulateInstructionARM::GetPluginNameStatic ()
174{
175 return "lldb.emulate-instruction.arm";
176}
177
178const char *
179EmulateInstructionARM::GetPluginDescriptionStatic ()
180{
181 return "Emulate instructions for the ARM architecture.";
182}
183
184EmulateInstruction *
Greg Clayton888a7332011-04-26 04:39:08 +0000185EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
Caroline Tice080bf612011-04-05 18:46:00 +0000186{
Greg Clayton888a7332011-04-26 04:39:08 +0000187 if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
Caroline Tice080bf612011-04-05 18:46:00 +0000188 {
Greg Clayton888a7332011-04-26 04:39:08 +0000189 if (arch.GetTriple().getArch() == llvm::Triple::arm)
190 {
191 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
192
193 if (emulate_insn_ap.get())
194 return emulate_insn_ap.release();
195 }
196 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
197 {
198 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
199
200 if (emulate_insn_ap.get())
201 return emulate_insn_ap.release();
202 }
Caroline Tice080bf612011-04-05 18:46:00 +0000203 }
204
205 return NULL;
206}
207
208bool
209EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
210{
211 if (arch.GetTriple().getArch () == llvm::Triple::arm)
212 return true;
213 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
214 return true;
215
216 return false;
217}
218
Caroline Ticefa172202011-02-11 22:49:54 +0000219// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
220bool
221EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
222{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000223 EmulateInstruction::Context context;
224 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
225 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000226
227 uint32_t random_data = rand ();
228 const uint32_t addr_byte_size = GetAddressByteSize();
229
Caroline Ticecc96eb52011-02-17 19:20:40 +0000230 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000231 return false;
232
233 return true;
234}
235
Caroline Tice713c2662011-02-11 17:59:55 +0000236// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
237bool
238EmulateInstructionARM::WriteBits32Unknown (int n)
239{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000240 EmulateInstruction::Context context;
241 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
242 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000243
Johnny Chen62ff6f52011-02-11 18:11:22 +0000244 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000245 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
246
247 if (!success)
248 return false;
249
250 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
251 return false;
252
253 return true;
254}
255
Greg Claytonc07d4512011-04-26 23:48:45 +0000256bool
257EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
258{
259 if (reg_kind == eRegisterKindGeneric)
260 {
261 switch (reg_num)
262 {
263 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break;
264 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break;
265 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break;
266 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break;
267 case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break;
268 default: return false;
269 }
270 }
271
272 if (reg_kind == eRegisterKindDWARF)
273 return GetARMDWARFRegisterInfo(reg_num, reg_info);
274 return false;
275}
276
Johnny Chen08c25e82011-01-31 18:02:28 +0000277// Push Multiple Registers stores multiple registers to the stack, storing to
278// consecutive memory locations ending just below the address in SP, and updates
279// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000280bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000281EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000282{
283#if 0
284 // ARM pseudo code...
285 if (ConditionPassed())
286 {
287 EncodingSpecificOperations();
288 NullCheckIfThumbEE(13);
289 address = SP - 4*BitCount(registers);
290
291 for (i = 0 to 14)
292 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000293 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000294 {
295 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
296 MemA[address,4] = bits(32) UNKNOWN;
297 else
298 MemA[address,4] = R[i];
299 address = address + 4;
300 }
301 }
302
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000303 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000304 MemA[address,4] = PCStoreValue();
305
306 SP = SP - 4*BitCount(registers);
307 }
308#endif
309
310 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000311 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000312 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000313 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000314 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000315 if (!success)
316 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000317 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000318 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000319 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000320 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000321 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000322 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000323 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000324 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000325 // if BitCount(registers) < 1 then UNPREDICTABLE;
326 if (BitCount(registers) < 1)
327 return false;
328 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000329 case eEncodingT2:
330 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000331 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000332 // if BitCount(registers) < 2 then UNPREDICTABLE;
333 if (BitCount(registers) < 2)
334 return false;
335 break;
336 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000337 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000338 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000339 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000340 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000341 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000342 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000343 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000344 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000345 // Instead of return false, let's handle the following case as well,
346 // which amounts to pushing one reg onto the full descending stacks.
347 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000348 break;
349 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000350 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000351 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000352 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000353 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000354 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000355 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000356 default:
357 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000358 }
Johnny Chence1ca772011-01-25 01:13:00 +0000359 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000360 addr_t addr = sp - sp_offset;
361 uint32_t i;
362
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000363 EmulateInstruction::Context context;
364 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000365 RegisterInfo reg_info;
366 RegisterInfo sp_reg;
367 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Clayton64c84432011-01-21 22:02:52 +0000368 for (i=0; i<15; ++i)
369 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000370 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000371 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000372 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
373 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000374 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000375 if (!success)
376 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000377 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000378 return false;
379 addr += addr_byte_size;
380 }
381 }
382
Johnny Chen7c1bf922011-02-08 23:49:37 +0000383 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000384 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000385 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info);
386 context.SetRegisterPlusOffset (reg_info, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000387 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000388 if (!success)
389 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000390 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000391 return false;
392 }
393
394 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000395 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000396
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000397 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000398 return false;
399 }
400 return true;
401}
402
Johnny Chenef85e912011-01-31 23:07:40 +0000403// Pop Multiple Registers loads multiple registers from the stack, loading from
404// consecutive memory locations staring at the address in SP, and updates
405// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000406bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000407EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000408{
409#if 0
410 // ARM pseudo code...
411 if (ConditionPassed())
412 {
413 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
414 address = SP;
415 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000416 if registers<i> == '1' then
Greg Claytonc07d4512011-04-26 23:48:45 +0000417 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000418 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000419 if UnalignedAllowed then
420 LoadWritePC(MemU[address,4]);
421 else
422 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000423 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
424 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000425 }
426#endif
427
428 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000429
Greg Claytonc07d4512011-04-26 23:48:45 +0000430 if (ConditionPassed(opcode)) {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000431 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000432 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000433 if (!success)
434 return false;
435 uint32_t registers = 0;
436 uint32_t Rt; // the destination register
437 switch (encoding) {
438 case eEncodingT1:
439 registers = Bits32(opcode, 7, 0);
440 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000441 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000442 registers |= (1u << 15);
443 // if BitCount(registers) < 1 then UNPREDICTABLE;
444 if (BitCount(registers) < 1)
445 return false;
446 break;
447 case eEncodingT2:
448 // Ignore bit 13.
449 registers = Bits32(opcode, 15, 0) & ~0x2000;
450 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000451 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000452 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000453 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
454 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
455 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000456 break;
457 case eEncodingT3:
458 Rt = Bits32(opcode, 15, 12);
459 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000460 if (Rt == 13)
461 return false;
462 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000463 return false;
464 registers = (1u << Rt);
465 break;
466 case eEncodingA1:
467 registers = Bits32(opcode, 15, 0);
468 // Instead of return false, let's handle the following case as well,
469 // which amounts to popping one reg from the full descending stacks.
470 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
471
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000472 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000473 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000474 return false;
475 break;
476 case eEncodingA2:
477 Rt = Bits32(opcode, 15, 12);
478 // if t == 13 then UNPREDICTABLE;
479 if (Rt == dwarf_sp)
480 return false;
481 registers = (1u << Rt);
482 break;
483 default:
484 return false;
485 }
486 addr_t sp_offset = addr_byte_size * BitCount (registers);
487 addr_t addr = sp;
488 uint32_t i, data;
489
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000490 EmulateInstruction::Context context;
491 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000492
493 RegisterInfo sp_reg;
494 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
495
Johnny Chenef85e912011-01-31 23:07:40 +0000496 for (i=0; i<15; ++i)
497 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000498 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000499 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000500 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000501 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000502 if (!success)
503 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +0000504 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000505 return false;
506 addr += addr_byte_size;
507 }
508 }
509
Johnny Chen7c1bf922011-02-08 23:49:37 +0000510 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000511 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000512 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000513 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000514 if (!success)
515 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000516 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000517 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000518 return false;
519 addr += addr_byte_size;
520 }
521
522 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000523 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000524
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000525 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000526 return false;
527 }
528 return true;
529}
530
Johnny Chen5b442b72011-01-27 19:34:30 +0000531// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000532// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000533bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000534EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000535{
536#if 0
537 // ARM pseudo code...
538 if (ConditionPassed())
539 {
540 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000541 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000542 if d == 15 then
543 ALUWritePC(result); // setflags is always FALSE here
544 else
545 R[d] = result;
546 if setflags then
547 APSR.N = result<31>;
548 APSR.Z = IsZeroBit(result);
549 APSR.C = carry;
550 APSR.V = overflow;
551 }
552#endif
553
554 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000555
Greg Clayton7bc39082011-03-24 23:53:38 +0000556 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000557 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000558 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000559 if (!success)
560 return false;
561 uint32_t Rd; // the destination register
562 uint32_t imm32;
563 switch (encoding) {
564 case eEncodingT1:
565 Rd = 7;
566 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
567 break;
568 case eEncodingA1:
569 Rd = Bits32(opcode, 15, 12);
570 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
571 break;
572 default:
573 return false;
574 }
575 addr_t sp_offset = imm32;
576 addr_t addr = sp + sp_offset; // a pointer to the stack area
577
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000578 EmulateInstruction::Context context;
Greg Clayton75906e42011-05-11 18:39:18 +0000579 context.type = eContextSetFramePointer;
Greg Claytonc07d4512011-04-26 23:48:45 +0000580 RegisterInfo sp_reg;
581 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000582 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000583
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000584 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000585 return false;
586 }
587 return true;
588}
589
Johnny Chen2ccad832011-01-28 19:57:25 +0000590// Set r7 or ip to the current stack pointer.
591// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000592bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000593EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000594{
595#if 0
596 // ARM pseudo code...
597 if (ConditionPassed())
598 {
599 EncodingSpecificOperations();
600 result = R[m];
601 if d == 15 then
602 ALUWritePC(result); // setflags is always FALSE here
603 else
604 R[d] = result;
605 if setflags then
606 APSR.N = result<31>;
607 APSR.Z = IsZeroBit(result);
608 // APSR.C unchanged
609 // APSR.V unchanged
610 }
611#endif
612
613 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000614
Greg Clayton7bc39082011-03-24 23:53:38 +0000615 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000616 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000617 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000618 if (!success)
619 return false;
620 uint32_t Rd; // the destination register
621 switch (encoding) {
622 case eEncodingT1:
623 Rd = 7;
624 break;
625 case eEncodingA1:
626 Rd = 12;
627 break;
628 default:
629 return false;
630 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000631
632 EmulateInstruction::Context context;
633 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +0000634 RegisterInfo sp_reg;
635 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000636 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000637
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000638 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000639 return false;
640 }
641 return true;
642}
643
Johnny Chen1c13b622011-01-29 00:11:15 +0000644// Move from high register (r8-r15) to low register (r0-r7).
645// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000646bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000647EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000648{
Greg Clayton7bc39082011-03-24 23:53:38 +0000649 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000650}
651
652// Move from register to register.
653// MOV (register)
654bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000655EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000656{
Johnny Chen1c13b622011-01-29 00:11:15 +0000657#if 0
658 // ARM pseudo code...
659 if (ConditionPassed())
660 {
661 EncodingSpecificOperations();
662 result = R[m];
663 if d == 15 then
664 ALUWritePC(result); // setflags is always FALSE here
665 else
666 R[d] = result;
667 if setflags then
668 APSR.N = result<31>;
669 APSR.Z = IsZeroBit(result);
670 // APSR.C unchanged
671 // APSR.V unchanged
672 }
673#endif
674
675 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000676
Greg Clayton7bc39082011-03-24 23:53:38 +0000677 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000678 {
679 uint32_t Rm; // the source register
680 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000681 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000682 switch (encoding) {
683 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000684 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000685 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000686 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000687 if (Rd == 15 && InITBlock() && !LastInITBlock())
688 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000689 break;
690 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000691 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000692 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000693 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000694 if (InITBlock())
695 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000696 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000697 case eEncodingT3:
698 Rd = Bits32(opcode, 11, 8);
699 Rm = Bits32(opcode, 3, 0);
700 setflags = BitIsSet(opcode, 20);
701 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
702 if (setflags && (BadReg(Rd) || BadReg(Rm)))
703 return false;
704 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
705 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
706 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000707 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000708 case eEncodingA1:
709 Rd = Bits32(opcode, 15, 12);
710 Rm = Bits32(opcode, 3, 0);
711 setflags = BitIsSet(opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +0000712
Johnny Chen01d61572011-02-25 00:23:25 +0000713 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000714 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000715 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000716 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000717 default:
718 return false;
719 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000720 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000721 if (!success)
722 return false;
723
724 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000725 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000726 context.type = EmulateInstruction::eContextRegisterLoad;
Greg Claytonc07d4512011-04-26 23:48:45 +0000727 RegisterInfo dwarf_reg;
728 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000729 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000730
Johnny Chen10530c22011-02-17 22:37:12 +0000731 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000732 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000733 }
734 return true;
735}
736
Johnny Chen357c30f2011-02-14 22:04:25 +0000737// Move (immediate) writes an immediate value to the destination register. It
738// can optionally update the condition flags based on the value.
739// MOV (immediate)
740bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000741EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000742{
743#if 0
744 // ARM pseudo code...
745 if (ConditionPassed())
746 {
747 EncodingSpecificOperations();
748 result = imm32;
749 if d == 15 then // Can only occur for ARM encoding
750 ALUWritePC(result); // setflags is always FALSE here
751 else
752 R[d] = result;
753 if setflags then
754 APSR.N = result<31>;
755 APSR.Z = IsZeroBit(result);
756 APSR.C = carry;
757 // APSR.V unchanged
758 }
759#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000760
Greg Clayton7bc39082011-03-24 23:53:38 +0000761 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000762 {
763 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000764 uint32_t imm32; // the immediate value to be written to Rd
765 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
766 bool setflags;
767 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000768 case eEncodingT1:
769 Rd = Bits32(opcode, 10, 8);
770 setflags = !InITBlock();
771 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
772 carry = APSR_C;
773
774 break;
775
776 case eEncodingT2:
777 Rd = Bits32(opcode, 11, 8);
778 setflags = BitIsSet(opcode, 20);
779 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
780 if (BadReg(Rd))
781 return false;
782
783 break;
784
785 case eEncodingT3:
786 {
787 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
788 Rd = Bits32 (opcode, 11, 8);
789 setflags = false;
790 uint32_t imm4 = Bits32 (opcode, 19, 16);
791 uint32_t imm3 = Bits32 (opcode, 14, 12);
792 uint32_t i = Bit32 (opcode, 26);
793 uint32_t imm8 = Bits32 (opcode, 7, 0);
794 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
795
796 // if BadReg(d) then UNPREDICTABLE;
797 if (BadReg (Rd))
798 return false;
799 }
800 break;
801
802 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +0000803 // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
Caroline Tice89c6d582011-03-29 19:53:44 +0000804 Rd = Bits32 (opcode, 15, 12);
805 setflags = BitIsSet (opcode, 20);
806 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000807
Greg Clayton061b79d2011-05-09 20:18:18 +0000808 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +0000809 if ((Rd == 15) && setflags)
810 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000811
812 break;
813
814 case eEncodingA2:
815 {
816 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
817 Rd = Bits32 (opcode, 15, 12);
818 setflags = false;
819 uint32_t imm4 = Bits32 (opcode, 19, 16);
820 uint32_t imm12 = Bits32 (opcode, 11, 0);
821 imm32 = (imm4 << 12) | imm12;
822
823 // if d == 15 then UNPREDICTABLE;
824 if (Rd == 15)
825 return false;
826 }
827 break;
828
829 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000830 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000831 }
832 uint32_t result = imm32;
833
834 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000835 EmulateInstruction::Context context;
836 context.type = EmulateInstruction::eContextImmediate;
837 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000838
Johnny Chen10530c22011-02-17 22:37:12 +0000839 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000840 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000841 }
842 return true;
843}
844
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000845// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
846// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
847// unsigned values.
848//
849// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
850// limited to only a few forms of the instruction.
851bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000852EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000853{
854#if 0
855 if ConditionPassed() then
856 EncodingSpecificOperations();
857 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
858 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
859 result = operand1 * operand2;
860 R[d] = result<31:0>;
861 if setflags then
862 APSR.N = result<31>;
863 APSR.Z = IsZeroBit(result);
864 if ArchVersion() == 4 then
865 APSR.C = bit UNKNOWN;
866 // else APSR.C unchanged
867 // APSR.V always unchanged
868#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000869
Greg Clayton7bc39082011-03-24 23:53:38 +0000870 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000871 {
872 uint32_t d;
873 uint32_t n;
874 uint32_t m;
875 bool setflags;
876
877 // EncodingSpecificOperations();
878 switch (encoding)
879 {
880 case eEncodingT1:
881 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
882 d = Bits32 (opcode, 2, 0);
883 n = Bits32 (opcode, 5, 3);
884 m = Bits32 (opcode, 2, 0);
885 setflags = !InITBlock();
886
887 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
888 if ((ArchVersion() < ARMv6) && (d == n))
889 return false;
890
891 break;
892
893 case eEncodingT2:
894 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
895 d = Bits32 (opcode, 11, 8);
896 n = Bits32 (opcode, 19, 16);
897 m = Bits32 (opcode, 3, 0);
898 setflags = false;
899
900 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
901 if (BadReg (d) || BadReg (n) || BadReg (m))
902 return false;
903
904 break;
905
906 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000907 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000908 d = Bits32 (opcode, 19, 16);
909 n = Bits32 (opcode, 3, 0);
910 m = Bits32 (opcode, 11, 8);
911 setflags = BitIsSet (opcode, 20);
912
913 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
914 if ((d == 15) || (n == 15) || (m == 15))
915 return false;
916
917 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
918 if ((ArchVersion() < ARMv6) && (d == n))
919 return false;
920
921 break;
922
923 default:
924 return false;
925 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000926
927 bool success = false;
928
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000929 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
930 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
931 if (!success)
932 return false;
933
934 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
935 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
936 if (!success)
937 return false;
938
939 // result = operand1 * operand2;
940 uint64_t result = operand1 * operand2;
941
942 // R[d] = result<31:0>;
Greg Claytonc07d4512011-04-26 23:48:45 +0000943 RegisterInfo op1_reg;
944 RegisterInfo op2_reg;
945 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
946 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000947
948 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +0000949 context.type = eContextArithmetic;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000950 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
951
952 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
953 return false;
954
955 // if setflags then
956 if (setflags)
957 {
958 // APSR.N = result<31>;
959 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000960 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000961 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
962 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000963 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000964 {
965 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
966 return false;
967 }
968
969 // if ArchVersion() == 4 then
970 // APSR.C = bit UNKNOWN;
971 }
972 }
973 return true;
974}
975
Johnny Chend642a6a2011-02-22 01:01:03 +0000976// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
977// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000978bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000979EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000980{
981#if 0
982 // ARM pseudo code...
983 if (ConditionPassed())
984 {
985 EncodingSpecificOperations();
986 result = NOT(imm32);
987 if d == 15 then // Can only occur for ARM encoding
988 ALUWritePC(result); // setflags is always FALSE here
989 else
990 R[d] = result;
991 if setflags then
992 APSR.N = result<31>;
993 APSR.Z = IsZeroBit(result);
994 APSR.C = carry;
995 // APSR.V unchanged
996 }
997#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000998
Greg Clayton7bc39082011-03-24 23:53:38 +0000999 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001000 {
1001 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +00001002 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1003 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001004 bool setflags;
1005 switch (encoding) {
1006 case eEncodingT1:
1007 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001008 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001009 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001010 break;
1011 case eEncodingA1:
1012 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001013 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001014 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +00001015
Johnny Chend642a6a2011-02-22 01:01:03 +00001016 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +00001017 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001018 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001019 break;
1020 default:
1021 return false;
1022 }
1023 uint32_t result = ~imm32;
1024
1025 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001026 EmulateInstruction::Context context;
1027 context.type = EmulateInstruction::eContextImmediate;
1028 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001029
Johnny Chen10530c22011-02-17 22:37:12 +00001030 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001031 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001032 }
1033 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001034}
1035
Johnny Chend642a6a2011-02-22 01:01:03 +00001036// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1037// It can optionally update the condition flags based on the result.
1038bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001039EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001040{
1041#if 0
1042 // ARM pseudo code...
1043 if (ConditionPassed())
1044 {
1045 EncodingSpecificOperations();
1046 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1047 result = NOT(shifted);
1048 if d == 15 then // Can only occur for ARM encoding
1049 ALUWritePC(result); // setflags is always FALSE here
1050 else
1051 R[d] = result;
1052 if setflags then
1053 APSR.N = result<31>;
1054 APSR.Z = IsZeroBit(result);
1055 APSR.C = carry;
1056 // APSR.V unchanged
1057 }
1058#endif
1059
Greg Clayton7bc39082011-03-24 23:53:38 +00001060 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001061 {
1062 uint32_t Rm; // the source register
1063 uint32_t Rd; // the destination register
1064 ARM_ShifterType shift_t;
1065 uint32_t shift_n; // the shift applied to the value read from Rm
1066 bool setflags;
1067 uint32_t carry; // the carry bit after the shift operation
1068 switch (encoding) {
1069 case eEncodingT1:
1070 Rd = Bits32(opcode, 2, 0);
1071 Rm = Bits32(opcode, 5, 3);
1072 setflags = !InITBlock();
1073 shift_t = SRType_LSL;
1074 shift_n = 0;
1075 if (InITBlock())
1076 return false;
1077 break;
1078 case eEncodingT2:
1079 Rd = Bits32(opcode, 11, 8);
1080 Rm = Bits32(opcode, 3, 0);
1081 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001082 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001083 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001084 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001085 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001086 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001087 case eEncodingA1:
1088 Rd = Bits32(opcode, 15, 12);
1089 Rm = Bits32(opcode, 3, 0);
1090 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001091 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001092 break;
1093 default:
1094 return false;
1095 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001096 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001097 uint32_t value = ReadCoreReg(Rm, &success);
1098 if (!success)
1099 return false;
1100
1101 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1102 uint32_t result = ~shifted;
1103
1104 // The context specifies that an immediate is to be moved into Rd.
1105 EmulateInstruction::Context context;
1106 context.type = EmulateInstruction::eContextImmediate;
1107 context.SetNoArgs ();
1108
1109 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1110 return false;
1111 }
1112 return true;
1113}
1114
Johnny Chen788e0552011-01-27 22:52:23 +00001115// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1116// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001117bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001118EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001119{
1120#if 0
1121 // ARM pseudo code...
1122 if (ConditionPassed())
1123 {
1124 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1125 base = Align(PC,4);
1126 address = if add then (base + imm32) else (base - imm32);
1127 data = MemU[address,4];
1128 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001129 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1130 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001131 R[t] = data;
1132 else // Can only apply before ARMv7
1133 if CurrentInstrSet() == InstrSet_ARM then
1134 R[t] = ROR(data, 8*UInt(address<1:0>));
1135 else
1136 R[t] = bits(32) UNKNOWN;
1137 }
1138#endif
1139
Greg Clayton7bc39082011-03-24 23:53:38 +00001140 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001141 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001142 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001143 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001144 if (!success)
1145 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001146
1147 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001148 EmulateInstruction::Context context;
1149 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001150 RegisterInfo pc_reg;
1151 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001152 context.SetRegisterPlusOffset (pc_reg, 0);
1153
Johnny Chenc9de9102011-02-11 19:12:30 +00001154 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001155 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001156 bool add; // +imm32 or -imm32?
1157 addr_t base; // the base address
1158 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001159 uint32_t data; // the literal data value from the PC relative load
1160 switch (encoding) {
1161 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001162 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001163 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001164 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001165 break;
1166 case eEncodingT2:
1167 Rt = Bits32(opcode, 15, 12);
1168 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1169 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001170 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001171 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001172 break;
1173 default:
1174 return false;
1175 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001176
Johnny Chene39f22d2011-02-19 01:36:13 +00001177 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001178 if (add)
1179 address = base + imm32;
1180 else
1181 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001182
1183 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001184 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001185 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001186 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001187
1188 if (Rt == 15)
1189 {
1190 if (Bits32(address, 1, 0) == 0)
1191 {
1192 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001193 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001194 return false;
1195 }
1196 else
1197 return false;
1198 }
1199 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1200 {
1201 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1202 return false;
1203 }
1204 else // We don't handle ARM for now.
1205 return false;
1206
Johnny Chen788e0552011-01-27 22:52:23 +00001207 }
1208 return true;
1209}
1210
Johnny Chen5b442b72011-01-27 19:34:30 +00001211// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001212// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001213bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001214EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001215{
1216#if 0
1217 // ARM pseudo code...
1218 if (ConditionPassed())
1219 {
1220 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001221 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001222 if d == 15 then // Can only occur for ARM encoding
1223 ALUWritePC(result); // setflags is always FALSE here
1224 else
1225 R[d] = result;
1226 if setflags then
1227 APSR.N = result<31>;
1228 APSR.Z = IsZeroBit(result);
1229 APSR.C = carry;
1230 APSR.V = overflow;
1231 }
1232#endif
1233
1234 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001235
Greg Clayton7bc39082011-03-24 23:53:38 +00001236 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001237 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001238 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001239 if (!success)
1240 return false;
1241 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001242 uint32_t d;
1243 bool setflags;
1244 switch (encoding)
1245 {
1246 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001247 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001248 d = Bits32 (opcode, 10, 8);
1249 setflags = false;
1250 imm32 = (Bits32 (opcode, 7, 0) << 2);
1251
1252 break;
1253
1254 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001255 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001256 d = 13;
1257 setflags = false;
1258 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1259
1260 break;
1261
1262 default:
1263 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001264 }
1265 addr_t sp_offset = imm32;
1266 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1267
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001268 EmulateInstruction::Context context;
1269 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +00001270 RegisterInfo sp_reg;
1271 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001272 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001273
Caroline Ticee2212882011-03-22 22:38:28 +00001274 if (d == 15)
1275 {
1276 if (!ALUWritePC (context, addr))
1277 return false;
1278 }
1279 else
1280 {
1281 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1282 return false;
1283 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001284 }
1285 return true;
1286}
1287
1288// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001289// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001290bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001291EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001292{
1293#if 0
1294 // ARM pseudo code...
1295 if (ConditionPassed())
1296 {
1297 EncodingSpecificOperations();
1298 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001299 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001300 if d == 15 then
1301 ALUWritePC(result); // setflags is always FALSE here
1302 else
1303 R[d] = result;
1304 if setflags then
1305 APSR.N = result<31>;
1306 APSR.Z = IsZeroBit(result);
1307 APSR.C = carry;
1308 APSR.V = overflow;
1309 }
1310#endif
1311
1312 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001313
Greg Clayton7bc39082011-03-24 23:53:38 +00001314 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001315 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001316 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001317 if (!success)
1318 return false;
1319 uint32_t Rm; // the second operand
1320 switch (encoding) {
1321 case eEncodingT2:
1322 Rm = Bits32(opcode, 6, 3);
1323 break;
1324 default:
1325 return false;
1326 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001327 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001328 if (!success)
1329 return false;
1330
1331 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1332
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001333 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00001334 context.type = eContextArithmetic;
1335 RegisterInfo sp_reg;
1336 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1337
1338 RegisterInfo other_reg;
1339 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001340 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001341
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001342 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001343 return false;
1344 }
1345 return true;
1346}
1347
Johnny Chen9b8d7832011-02-02 01:13:56 +00001348// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1349// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1350// from Thumb to ARM.
1351// BLX (immediate)
1352bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001353EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001354{
1355#if 0
1356 // ARM pseudo code...
1357 if (ConditionPassed())
1358 {
1359 EncodingSpecificOperations();
1360 if CurrentInstrSet() == InstrSet_ARM then
1361 LR = PC - 4;
1362 else
1363 LR = PC<31:1> : '1';
1364 if targetInstrSet == InstrSet_ARM then
1365 targetAddress = Align(PC,4) + imm32;
1366 else
1367 targetAddress = PC + imm32;
1368 SelectInstrSet(targetInstrSet);
1369 BranchWritePC(targetAddress);
1370 }
1371#endif
1372
Greg Clayton7bc39082011-03-24 23:53:38 +00001373 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001374
Greg Clayton7bc39082011-03-24 23:53:38 +00001375 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001376 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001377 EmulateInstruction::Context context;
1378 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001379 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001380 if (!success)
1381 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001382 addr_t lr; // next instruction address
1383 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001384 int32_t imm32; // PC-relative offset
1385 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001386 case eEncodingT1:
1387 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001388 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001389 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001390 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001391 uint32_t J1 = Bit32(opcode, 13);
1392 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001393 uint32_t imm11 = Bits32(opcode, 10, 0);
1394 uint32_t I1 = !(J1 ^ S);
1395 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001396 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001397 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001398 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001399 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001400 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001401 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001402 break;
1403 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001404 case eEncodingT2:
1405 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001406 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001407 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001408 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001409 uint32_t J1 = Bit32(opcode, 13);
1410 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001411 uint32_t imm10L = Bits32(opcode, 10, 1);
1412 uint32_t I1 = !(J1 ^ S);
1413 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001414 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001415 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001416 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001417 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001418 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001419 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001420 break;
1421 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001422 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001423 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001424 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001425 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001426 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001427 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001428 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001429 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001430 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001431 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001432 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001433 break;
1434 default:
1435 return false;
1436 }
1437 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1438 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001439 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001440 return false;
1441 }
1442 return true;
1443}
1444
1445// Branch with Link and Exchange (register) calls a subroutine at an address and
1446// instruction set specified by a register.
1447// BLX (register)
1448bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001449EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001450{
1451#if 0
1452 // ARM pseudo code...
1453 if (ConditionPassed())
1454 {
1455 EncodingSpecificOperations();
1456 target = R[m];
1457 if CurrentInstrSet() == InstrSet_ARM then
1458 next_instr_addr = PC - 4;
1459 LR = next_instr_addr;
1460 else
1461 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001462 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001463 BXWritePC(target);
1464 }
1465#endif
1466
1467 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001468
Greg Clayton7bc39082011-03-24 23:53:38 +00001469 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001470 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001471 EmulateInstruction::Context context;
1472 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001473 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001474 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001475 if (!success)
1476 return false;
1477 uint32_t Rm; // the register with the target address
1478 switch (encoding) {
1479 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001480 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001481 Rm = Bits32(opcode, 6, 3);
1482 // if m == 15 then UNPREDICTABLE;
1483 if (Rm == 15)
1484 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001485 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001486 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001487 break;
1488 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001489 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001490 Rm = Bits32(opcode, 3, 0);
1491 // if m == 15 then UNPREDICTABLE;
1492 if (Rm == 15)
1493 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001494 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001495 default:
1496 return false;
1497 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001498 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001499 if (!success)
1500 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001501 RegisterInfo dwarf_reg;
1502 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001503 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001504 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1505 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001506 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001507 return false;
1508 }
1509 return true;
1510}
1511
Johnny Chenab3b3512011-02-12 00:10:51 +00001512// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001513bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001514EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001515{
1516#if 0
1517 // ARM pseudo code...
1518 if (ConditionPassed())
1519 {
1520 EncodingSpecificOperations();
1521 BXWritePC(R[m]);
1522 }
1523#endif
1524
Greg Clayton7bc39082011-03-24 23:53:38 +00001525 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001526 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001527 EmulateInstruction::Context context;
1528 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001529 uint32_t Rm; // the register with the target address
1530 switch (encoding) {
1531 case eEncodingT1:
1532 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001533 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001534 return false;
1535 break;
1536 case eEncodingA1:
1537 Rm = Bits32(opcode, 3, 0);
1538 break;
1539 default:
1540 return false;
1541 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001542 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001543 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001544 if (!success)
1545 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001546
1547 RegisterInfo dwarf_reg;
1548 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen668b4512011-02-15 21:08:58 +00001549 context.SetRegister (dwarf_reg);
1550 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001551 return false;
1552 }
1553 return true;
1554}
1555
Johnny Chen59e6ab72011-02-24 21:01:20 +00001556// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1557// address and instruction set specified by a register as though it were a BX instruction.
1558//
1559// TODO: Emulate Jazelle architecture?
1560// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1561bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001562EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001563{
1564#if 0
1565 // ARM pseudo code...
1566 if (ConditionPassed())
1567 {
1568 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001569 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001570 BXWritePC(R[m]);
1571 else
1572 if JazelleAcceptsExecution() then
1573 SwitchToJazelleExecution();
1574 else
1575 SUBARCHITECTURE_DEFINED handler call;
1576 }
1577#endif
1578
Greg Clayton7bc39082011-03-24 23:53:38 +00001579 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001580 {
1581 EmulateInstruction::Context context;
1582 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1583 uint32_t Rm; // the register with the target address
1584 switch (encoding) {
1585 case eEncodingT1:
1586 Rm = Bits32(opcode, 19, 16);
1587 if (BadReg(Rm))
1588 return false;
1589 if (InITBlock() && !LastInITBlock())
1590 return false;
1591 break;
1592 case eEncodingA1:
1593 Rm = Bits32(opcode, 3, 0);
1594 if (Rm == 15)
1595 return false;
1596 break;
1597 default:
1598 return false;
1599 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001600 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001601 addr_t target = ReadCoreReg (Rm, &success);
1602 if (!success)
1603 return false;
1604
Greg Claytonc07d4512011-04-26 23:48:45 +00001605 RegisterInfo dwarf_reg;
1606 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen59e6ab72011-02-24 21:01:20 +00001607 context.SetRegister (dwarf_reg);
1608 if (!BXWritePC(context, target))
1609 return false;
1610 }
1611 return true;
1612}
1613
Johnny Chen0d0148e2011-01-28 02:26:08 +00001614// Set r7 to point to some ip offset.
1615// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001616bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001617EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001618{
1619#if 0
1620 // ARM pseudo code...
1621 if (ConditionPassed())
1622 {
1623 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001624 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001625 if d == 15 then // Can only occur for ARM encoding
1626 ALUWritePC(result); // setflags is always FALSE here
1627 else
1628 R[d] = result;
1629 if setflags then
1630 APSR.N = result<31>;
1631 APSR.Z = IsZeroBit(result);
1632 APSR.C = carry;
1633 APSR.V = overflow;
1634 }
1635#endif
1636
Greg Clayton7bc39082011-03-24 23:53:38 +00001637 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001638 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001639 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001640 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001641 if (!success)
1642 return false;
1643 uint32_t imm32;
1644 switch (encoding) {
1645 case eEncodingA1:
1646 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1647 break;
1648 default:
1649 return false;
1650 }
1651 addr_t ip_offset = imm32;
1652 addr_t addr = ip - ip_offset; // the adjusted ip value
1653
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001654 EmulateInstruction::Context context;
1655 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001656 RegisterInfo dwarf_reg;
1657 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001658 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001659
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001660 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001661 return false;
1662 }
1663 return true;
1664}
1665
1666// Set ip to point to some stack offset.
1667// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001668bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001669EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001670{
1671#if 0
1672 // ARM pseudo code...
1673 if (ConditionPassed())
1674 {
1675 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001676 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001677 if d == 15 then // Can only occur for ARM encoding
1678 ALUWritePC(result); // setflags is always FALSE here
1679 else
1680 R[d] = result;
1681 if setflags then
1682 APSR.N = result<31>;
1683 APSR.Z = IsZeroBit(result);
1684 APSR.C = carry;
1685 APSR.V = overflow;
1686 }
1687#endif
1688
Greg Clayton7bc39082011-03-24 23:53:38 +00001689 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001690 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001691 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001692 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001693 if (!success)
1694 return false;
1695 uint32_t imm32;
1696 switch (encoding) {
1697 case eEncodingA1:
1698 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1699 break;
1700 default:
1701 return false;
1702 }
1703 addr_t sp_offset = imm32;
1704 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1705
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001706 EmulateInstruction::Context context;
1707 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001708 RegisterInfo dwarf_reg;
1709 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001710 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001711
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001712 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001713 return false;
1714 }
1715 return true;
1716}
1717
Johnny Chenc9e747f2011-02-23 01:55:07 +00001718// This instruction subtracts an immediate value from the SP value, and writes
1719// the result to the destination register.
1720//
1721// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001722bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001723EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001724{
1725#if 0
1726 // ARM pseudo code...
1727 if (ConditionPassed())
1728 {
1729 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001730 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001731 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001732 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001733 else
1734 R[d] = result;
1735 if setflags then
1736 APSR.N = result<31>;
1737 APSR.Z = IsZeroBit(result);
1738 APSR.C = carry;
1739 APSR.V = overflow;
1740 }
1741#endif
1742
1743 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001744 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001745 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001746 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001747 if (!success)
1748 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001749
1750 uint32_t Rd;
1751 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001752 uint32_t imm32;
1753 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001754 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001755 Rd = 13;
1756 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001757 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001758 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001759 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001760 Rd = Bits32(opcode, 11, 8);
1761 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001762 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001763 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001764 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001765 if (Rd == 15 && !setflags)
1766 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001767 break;
1768 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001769 Rd = Bits32(opcode, 11, 8);
1770 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001771 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001772 if (Rd == 15)
1773 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001774 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001775 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001776 Rd = Bits32(opcode, 15, 12);
1777 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001778 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001779
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001780 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001781 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001782 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001783 break;
1784 default:
1785 return false;
1786 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001787 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1788
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001789 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001790 if (Rd == 13)
1791 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001792 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1793 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001794 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001795 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001796 }
1797 else
1798 {
1799 context.type = EmulateInstruction::eContextImmediate;
1800 context.SetNoArgs ();
1801 }
1802
1803 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001804 return false;
1805 }
1806 return true;
1807}
1808
Johnny Chen08c25e82011-01-31 18:02:28 +00001809// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001810bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001811EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001812{
1813#if 0
1814 // ARM pseudo code...
1815 if (ConditionPassed())
1816 {
1817 EncodingSpecificOperations();
1818 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1819 address = if index then offset_addr else R[n];
1820 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1821 if wback then R[n] = offset_addr;
1822 }
1823#endif
1824
1825 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001826
Greg Clayton7bc39082011-03-24 23:53:38 +00001827 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001828 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001829 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001830 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001831 if (!success)
1832 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001833 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001834 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001835 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1836
1837 bool index;
1838 bool add;
1839 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001840 switch (encoding) {
1841 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001842 Rt = Bits32(opcode, 15, 12);
1843 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001844 Rn = Bits32 (opcode, 19, 16);
1845
1846 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1847 return false;
1848
1849 index = BitIsSet (opcode, 24);
1850 add = BitIsSet (opcode, 23);
1851 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1852
1853 if (wback && ((Rn == 15) || (Rn == Rt)))
1854 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001855 break;
1856 default:
1857 return false;
1858 }
Caroline Tice3e407972011-03-18 19:41:00 +00001859 addr_t offset_addr;
1860 if (add)
1861 offset_addr = sp + imm12;
1862 else
1863 offset_addr = sp - imm12;
1864
1865 addr_t addr;
1866 if (index)
1867 addr = offset_addr;
1868 else
1869 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001870
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001871 EmulateInstruction::Context context;
1872 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001873 RegisterInfo sp_reg;
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001874 RegisterInfo dwarf_reg;
1875
Greg Claytonc07d4512011-04-26 23:48:45 +00001876 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001877 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1878 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001879 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001880 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001881 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001882 if (!success)
1883 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001884 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001885 return false;
1886 }
1887 else
1888 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001889 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001890 if (!success)
1891 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001892 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001893 return false;
1894 }
1895
Caroline Tice3e407972011-03-18 19:41:00 +00001896
1897 if (wback)
1898 {
1899 context.type = EmulateInstruction::eContextAdjustStackPointer;
1900 context.SetImmediateSigned (addr - sp);
1901 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1902 return false;
1903 }
Johnny Chence1ca772011-01-25 01:13:00 +00001904 }
1905 return true;
1906}
1907
Johnny Chen08c25e82011-01-31 18:02:28 +00001908// Vector Push stores multiple extension registers to the stack.
1909// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001910bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001911EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001912{
1913#if 0
1914 // ARM pseudo code...
1915 if (ConditionPassed())
1916 {
1917 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1918 address = SP - imm32;
1919 SP = SP - imm32;
1920 if single_regs then
1921 for r = 0 to regs-1
1922 MemA[address,4] = S[d+r]; address = address+4;
1923 else
1924 for r = 0 to regs-1
1925 // Store as two word-aligned words in the correct order for current endianness.
1926 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1927 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1928 address = address+8;
1929 }
1930#endif
1931
1932 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001933
Greg Clayton7bc39082011-03-24 23:53:38 +00001934 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001935 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001936 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001937 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001938 if (!success)
1939 return false;
1940 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001941 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001942 uint32_t imm32; // stack offset
1943 uint32_t regs; // number of registers
1944 switch (encoding) {
1945 case eEncodingT1:
1946 case eEncodingA1:
1947 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001948 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001949 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1950 // If UInt(imm8) is odd, see "FSTMX".
1951 regs = Bits32(opcode, 7, 0) / 2;
1952 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1953 if (regs == 0 || regs > 16 || (d + regs) > 32)
1954 return false;
1955 break;
1956 case eEncodingT2:
1957 case eEncodingA2:
1958 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001959 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001960 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1961 regs = Bits32(opcode, 7, 0);
1962 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1963 if (regs == 0 || regs > 16 || (d + regs) > 32)
1964 return false;
1965 break;
1966 default:
1967 return false;
1968 }
1969 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1970 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1971 addr_t sp_offset = imm32;
1972 addr_t addr = sp - sp_offset;
1973 uint32_t i;
1974
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001975 EmulateInstruction::Context context;
1976 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001977 RegisterInfo dwarf_reg;
1978 RegisterInfo sp_reg;
1979 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001980 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001981 {
Greg Claytonc07d4512011-04-26 23:48:45 +00001982 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001983 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001984 // uint64_t to accommodate 64-bit registers.
Greg Clayton061b79d2011-05-09 20:18:18 +00001985 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001986 if (!success)
1987 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001988 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001989 return false;
1990 addr += reg_byte_size;
1991 }
1992
1993 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001994 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001995
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001996 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001997 return false;
1998 }
1999 return true;
2000}
2001
Johnny Chen587a0a42011-02-01 18:35:28 +00002002// Vector Pop loads multiple extension registers from the stack.
2003// It also updates SP to point just above the loaded data.
2004bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002005EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00002006{
2007#if 0
2008 // ARM pseudo code...
2009 if (ConditionPassed())
2010 {
2011 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2012 address = SP;
2013 SP = SP + imm32;
2014 if single_regs then
2015 for r = 0 to regs-1
2016 S[d+r] = MemA[address,4]; address = address+4;
2017 else
2018 for r = 0 to regs-1
2019 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2020 // Combine the word-aligned words in the correct order for current endianness.
2021 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2022 }
2023#endif
2024
2025 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00002026
Greg Clayton7bc39082011-03-24 23:53:38 +00002027 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00002028 {
2029 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002030 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002031 if (!success)
2032 return false;
2033 bool single_regs;
2034 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2035 uint32_t imm32; // stack offset
2036 uint32_t regs; // number of registers
2037 switch (encoding) {
2038 case eEncodingT1:
2039 case eEncodingA1:
2040 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002041 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002042 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2043 // If UInt(imm8) is odd, see "FLDMX".
2044 regs = Bits32(opcode, 7, 0) / 2;
2045 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2046 if (regs == 0 || regs > 16 || (d + regs) > 32)
2047 return false;
2048 break;
2049 case eEncodingT2:
2050 case eEncodingA2:
2051 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002052 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002053 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2054 regs = Bits32(opcode, 7, 0);
2055 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2056 if (regs == 0 || regs > 16 || (d + regs) > 32)
2057 return false;
2058 break;
2059 default:
2060 return false;
2061 }
2062 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2063 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2064 addr_t sp_offset = imm32;
2065 addr_t addr = sp;
2066 uint32_t i;
2067 uint64_t data; // uint64_t to accomodate 64-bit registers.
2068
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002069 EmulateInstruction::Context context;
2070 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002071 RegisterInfo dwarf_reg;
2072 RegisterInfo sp_reg;
2073 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002074 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002075 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002076 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002077 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002078 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002079 if (!success)
2080 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +00002081 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002082 return false;
2083 addr += reg_byte_size;
2084 }
2085
2086 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002087 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002088
2089 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2090 return false;
2091 }
2092 return true;
2093}
2094
Johnny Chenb77be412011-02-04 00:40:18 +00002095// SVC (previously SWI)
2096bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002097EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002098{
2099#if 0
2100 // ARM pseudo code...
2101 if (ConditionPassed())
2102 {
2103 EncodingSpecificOperations();
2104 CallSupervisor();
2105 }
2106#endif
2107
2108 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002109
Greg Clayton7bc39082011-03-24 23:53:38 +00002110 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002111 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002112 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002113 addr_t lr; // next instruction address
2114 if (!success)
2115 return false;
2116 uint32_t imm32; // the immediate constant
2117 uint32_t mode; // ARM or Thumb mode
2118 switch (encoding) {
2119 case eEncodingT1:
2120 lr = (pc + 2) | 1u; // return address
2121 imm32 = Bits32(opcode, 7, 0);
2122 mode = eModeThumb;
2123 break;
2124 case eEncodingA1:
2125 lr = pc + 4; // return address
2126 imm32 = Bits32(opcode, 23, 0);
2127 mode = eModeARM;
2128 break;
2129 default:
2130 return false;
2131 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002132
2133 EmulateInstruction::Context context;
2134 context.type = EmulateInstruction::eContextSupervisorCall;
Greg Claytonc07d4512011-04-26 23:48:45 +00002135 context.SetISAAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002136 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2137 return false;
2138 }
2139 return true;
2140}
2141
Johnny Chenc315f862011-02-05 00:46:10 +00002142// If Then makes up to four following instructions (the IT block) conditional.
2143bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002144EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002145{
2146#if 0
2147 // ARM pseudo code...
2148 EncodingSpecificOperations();
2149 ITSTATE.IT<7:0> = firstcond:mask;
2150#endif
2151
Johnny Chenc315f862011-02-05 00:46:10 +00002152 m_it_session.InitIT(Bits32(opcode, 7, 0));
2153 return true;
2154}
2155
Johnny Chen3b620b32011-02-07 20:11:47 +00002156// Branch causes a branch to a target address.
2157bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002158EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002159{
2160#if 0
2161 // ARM pseudo code...
2162 if (ConditionPassed())
2163 {
2164 EncodingSpecificOperations();
2165 BranchWritePC(PC + imm32);
2166 }
2167#endif
2168
2169 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002170
Greg Clayton7bc39082011-03-24 23:53:38 +00002171 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002172 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002173 EmulateInstruction::Context context;
2174 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002175 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002176 if (!success)
2177 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002178 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002179 int32_t imm32; // PC-relative offset
2180 switch (encoding) {
2181 case eEncodingT1:
2182 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2183 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002184 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002185 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002186 break;
2187 case eEncodingT2:
2188 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002189 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002190 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002191 break;
2192 case eEncodingT3:
2193 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2194 {
Johnny Chenbd599902011-02-10 21:39:01 +00002195 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002196 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002197 uint32_t J1 = Bit32(opcode, 13);
2198 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002199 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002200 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002201 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002202 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002203 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002204 break;
2205 }
2206 case eEncodingT4:
2207 {
Johnny Chenbd599902011-02-10 21:39:01 +00002208 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002209 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002210 uint32_t J1 = Bit32(opcode, 13);
2211 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002212 uint32_t imm11 = Bits32(opcode, 10, 0);
2213 uint32_t I1 = !(J1 ^ S);
2214 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002215 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002216 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002217 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002218 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002219 break;
2220 }
2221 case eEncodingA1:
2222 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002223 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002224 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002225 break;
2226 default:
2227 return false;
2228 }
2229 if (!BranchWritePC(context, target))
2230 return false;
2231 }
2232 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002233}
2234
Johnny Chen53ebab72011-02-08 23:21:57 +00002235// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2236// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2237// CBNZ, CBZ
2238bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002239EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002240{
2241#if 0
2242 // ARM pseudo code...
2243 EncodingSpecificOperations();
2244 if nonzero ^ IsZero(R[n]) then
2245 BranchWritePC(PC + imm32);
2246#endif
2247
2248 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002249
2250 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002251 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002252 if (!success)
2253 return false;
2254
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002255 EmulateInstruction::Context context;
2256 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002257 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002258 if (!success)
2259 return false;
2260
2261 addr_t target; // target address
2262 uint32_t imm32; // PC-relative offset to branch forward
2263 bool nonzero;
2264 switch (encoding) {
2265 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002266 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002267 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002268 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002269 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002270 break;
2271 default:
2272 return false;
2273 }
2274 if (nonzero ^ (reg_val == 0))
2275 if (!BranchWritePC(context, target))
2276 return false;
2277
2278 return true;
2279}
2280
Johnny Chen60299ec2011-02-17 19:34:27 +00002281// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2282// A base register provides a pointer to the table, and a second register supplies an index into the table.
2283// The branch length is twice the value of the byte returned from the table.
2284//
2285// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2286// A base register provides a pointer to the table, and a second register supplies an index into the table.
2287// The branch length is twice the value of the halfword returned from the table.
2288// TBB, TBH
2289bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002290EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002291{
2292#if 0
2293 // ARM pseudo code...
2294 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2295 if is_tbh then
2296 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2297 else
2298 halfwords = UInt(MemU[R[n]+R[m], 1]);
2299 BranchWritePC(PC + 2*halfwords);
2300#endif
2301
2302 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002303
2304 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2305 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2306 bool is_tbh; // true if table branch halfword
2307 switch (encoding) {
2308 case eEncodingT1:
2309 Rn = Bits32(opcode, 19, 16);
2310 Rm = Bits32(opcode, 3, 0);
2311 is_tbh = BitIsSet(opcode, 4);
2312 if (Rn == 13 || BadReg(Rm))
2313 return false;
2314 if (InITBlock() && !LastInITBlock())
2315 return false;
2316 break;
2317 default:
2318 return false;
2319 }
2320
2321 // Read the address of the table from the operand register Rn.
2322 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002323 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002324 if (!success)
2325 return false;
2326
2327 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002328 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002329 if (!success)
2330 return false;
2331
2332 // the offsetted table address
2333 addr_t addr = base + (is_tbh ? index*2 : index);
2334
2335 // PC-relative offset to branch forward
2336 EmulateInstruction::Context context;
2337 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002338 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002339 if (!success)
2340 return false;
2341
Johnny Chene39f22d2011-02-19 01:36:13 +00002342 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002343 if (!success)
2344 return false;
2345
2346 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002347 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002348 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Greg Claytonc07d4512011-04-26 23:48:45 +00002349 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
Johnny Chen60299ec2011-02-17 19:34:27 +00002350
2351 if (!BranchWritePC(context, target))
2352 return false;
2353
2354 return true;
2355}
2356
Caroline Ticedcc11b32011-03-02 23:57:02 +00002357// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2358// It can optionally update the condition flags based on the result.
2359bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002360EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002361{
2362#if 0
2363 if ConditionPassed() then
2364 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002365 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002366 R[d] = result;
2367 if setflags then
2368 APSR.N = result<31>;
2369 APSR.Z = IsZeroBit(result);
2370 APSR.C = carry;
2371 APSR.V = overflow;
2372#endif
2373
2374 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002375
Greg Clayton7bc39082011-03-24 23:53:38 +00002376 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002377 {
2378 uint32_t d;
2379 uint32_t n;
2380 bool setflags;
2381 uint32_t imm32;
2382 uint32_t carry_out;
2383
2384 //EncodingSpecificOperations();
2385 switch (encoding)
2386 {
2387 case eEncodingT1:
2388 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2389 d = Bits32 (opcode, 2, 0);
2390 n = Bits32 (opcode, 5, 3);
2391 setflags = !InITBlock();
2392 imm32 = Bits32 (opcode, 8,6);
2393
2394 break;
2395
2396 case eEncodingT2:
2397 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2398 d = Bits32 (opcode, 10, 8);
2399 n = Bits32 (opcode, 10, 8);
2400 setflags = !InITBlock();
2401 imm32 = Bits32 (opcode, 7, 0);
2402
2403 break;
2404
2405 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002406 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2407 // if Rn == '1101' then SEE ADD (SP plus immediate);
2408 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002409 d = Bits32 (opcode, 11, 8);
2410 n = Bits32 (opcode, 19, 16);
2411 setflags = BitIsSet (opcode, 20);
2412 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2413
2414 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2415 if (BadReg (d) || (n == 15))
2416 return false;
2417
2418 break;
2419
2420 case eEncodingT4:
2421 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002422 // if Rn == '1111' then SEE ADR;
2423 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002424 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2425 d = Bits32 (opcode, 11, 8);
2426 n = Bits32 (opcode, 19, 16);
2427 setflags = false;
2428 uint32_t i = Bit32 (opcode, 26);
2429 uint32_t imm3 = Bits32 (opcode, 14, 12);
2430 uint32_t imm8 = Bits32 (opcode, 7, 0);
2431 imm32 = (i << 11) | (imm3 << 8) | imm8;
2432
2433 // if BadReg(d) then UNPREDICTABLE;
2434 if (BadReg (d))
2435 return false;
2436
2437 break;
2438 }
2439 default:
2440 return false;
2441 }
2442
2443 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2444 if (!success)
2445 return false;
2446
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002447 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002448 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2449
Greg Claytonc07d4512011-04-26 23:48:45 +00002450 RegisterInfo reg_n;
2451 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002452
2453 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002454 context.type = eContextArithmetic;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002455 context.SetRegisterPlusOffset (reg_n, imm32);
2456
2457 //R[d] = result;
2458 //if setflags then
2459 //APSR.N = result<31>;
2460 //APSR.Z = IsZeroBit(result);
2461 //APSR.C = carry;
2462 //APSR.V = overflow;
2463 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2464 return false;
2465
2466 }
2467 return true;
2468}
2469
Johnny Chen8fa20592011-02-18 01:22:22 +00002470// This instruction adds an immediate value to a register value, and writes the result to the destination
2471// register. It can optionally update the condition flags based on the result.
2472bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002473EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002474{
2475#if 0
2476 // ARM pseudo code...
2477 if ConditionPassed() then
2478 EncodingSpecificOperations();
2479 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2480 if d == 15 then
2481 ALUWritePC(result); // setflags is always FALSE here
2482 else
2483 R[d] = result;
2484 if setflags then
2485 APSR.N = result<31>;
2486 APSR.Z = IsZeroBit(result);
2487 APSR.C = carry;
2488 APSR.V = overflow;
2489#endif
2490
2491 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002492
Greg Clayton7bc39082011-03-24 23:53:38 +00002493 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002494 {
2495 uint32_t Rd, Rn;
2496 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2497 bool setflags;
2498 switch (encoding)
2499 {
2500 case eEncodingA1:
2501 Rd = Bits32(opcode, 15, 12);
2502 Rn = Bits32(opcode, 19, 16);
2503 setflags = BitIsSet(opcode, 20);
2504 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2505 break;
2506 default:
2507 return false;
2508 }
2509
Johnny Chen8fa20592011-02-18 01:22:22 +00002510 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002511 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002512 if (!success)
2513 return false;
2514
2515 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2516
2517 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002518 context.type = eContextArithmetic;
2519 RegisterInfo dwarf_reg;
2520 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00002521 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002522
2523 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2524 return false;
2525 }
2526 return true;
2527}
2528
Johnny Chend761dcf2011-02-17 22:03:29 +00002529// This instruction adds a register value and an optionally-shifted register value, and writes the result
2530// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002531bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002532EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002533{
2534#if 0
2535 // ARM pseudo code...
2536 if ConditionPassed() then
2537 EncodingSpecificOperations();
2538 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2539 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2540 if d == 15 then
2541 ALUWritePC(result); // setflags is always FALSE here
2542 else
2543 R[d] = result;
2544 if setflags then
2545 APSR.N = result<31>;
2546 APSR.Z = IsZeroBit(result);
2547 APSR.C = carry;
2548 APSR.V = overflow;
2549#endif
2550
2551 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002552
Greg Clayton7bc39082011-03-24 23:53:38 +00002553 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002554 {
2555 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002556 ARM_ShifterType shift_t;
2557 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002558 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002559 switch (encoding)
2560 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002561 case eEncodingT1:
2562 Rd = Bits32(opcode, 2, 0);
2563 Rn = Bits32(opcode, 5, 3);
2564 Rm = Bits32(opcode, 8, 6);
2565 setflags = !InITBlock();
2566 shift_t = SRType_LSL;
2567 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002568 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002569 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002570 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002571 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002572 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002573 shift_t = SRType_LSL;
2574 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002575 if (Rn == 15 && Rm == 15)
2576 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002577 if (Rd == 15 && InITBlock() && !LastInITBlock())
2578 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002579 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002580 case eEncodingA1:
2581 Rd = Bits32(opcode, 15, 12);
2582 Rn = Bits32(opcode, 19, 16);
2583 Rm = Bits32(opcode, 3, 0);
2584 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002585 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002586 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002587 default:
2588 return false;
2589 }
2590
Johnny Chen26863dc2011-02-09 23:43:29 +00002591 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002592 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002593 if (!success)
2594 return false;
2595
2596 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002597 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002598 if (!success)
2599 return false;
2600
Johnny Chene97c0d52011-02-18 19:32:20 +00002601 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002602 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002603
2604 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002605 context.type = eContextArithmetic;
2606 RegisterInfo op1_reg;
2607 RegisterInfo op2_reg;
2608 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2609 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00002610 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002611
Johnny Chen10530c22011-02-17 22:37:12 +00002612 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002613 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002614 }
2615 return true;
2616}
2617
Johnny Chen34075cb2011-02-22 01:56:31 +00002618// Compare Negative (immediate) adds a register value and an immediate value.
2619// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002620bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002621EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002622{
2623#if 0
2624 // ARM pseudo code...
2625 if ConditionPassed() then
2626 EncodingSpecificOperations();
2627 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2628 APSR.N = result<31>;
2629 APSR.Z = IsZeroBit(result);
2630 APSR.C = carry;
2631 APSR.V = overflow;
2632#endif
2633
2634 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002635
2636 uint32_t Rn; // the first operand
2637 uint32_t imm32; // the immediate value to be compared with
2638 switch (encoding) {
2639 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002640 Rn = Bits32(opcode, 19, 16);
2641 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2642 if (Rn == 15)
2643 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002644 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002645 case eEncodingA1:
2646 Rn = Bits32(opcode, 19, 16);
2647 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2648 break;
2649 default:
2650 return false;
2651 }
2652 // Read the register value from the operand register Rn.
2653 uint32_t reg_val = ReadCoreReg(Rn, &success);
2654 if (!success)
2655 return false;
2656
Johnny Chen078fbc62011-02-22 19:48:22 +00002657 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002658
2659 EmulateInstruction::Context context;
2660 context.type = EmulateInstruction::eContextImmediate;
2661 context.SetNoArgs ();
2662 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2663 return false;
2664
2665 return true;
2666}
2667
2668// Compare Negative (register) adds a register value and an optionally-shifted register value.
2669// It updates the condition flags based on the result, and discards the result.
2670bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002671EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002672{
2673#if 0
2674 // ARM pseudo code...
2675 if ConditionPassed() then
2676 EncodingSpecificOperations();
2677 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2678 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2679 APSR.N = result<31>;
2680 APSR.Z = IsZeroBit(result);
2681 APSR.C = carry;
2682 APSR.V = overflow;
2683#endif
2684
2685 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002686
2687 uint32_t Rn; // the first operand
2688 uint32_t Rm; // the second operand
2689 ARM_ShifterType shift_t;
2690 uint32_t shift_n; // the shift applied to the value read from Rm
2691 switch (encoding) {
2692 case eEncodingT1:
2693 Rn = Bits32(opcode, 2, 0);
2694 Rm = Bits32(opcode, 5, 3);
2695 shift_t = SRType_LSL;
2696 shift_n = 0;
2697 break;
2698 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002699 Rn = Bits32(opcode, 19, 16);
2700 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002701 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002702 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2703 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002704 return false;
2705 break;
2706 case eEncodingA1:
2707 Rn = Bits32(opcode, 19, 16);
2708 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002709 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002710 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002711 default:
2712 return false;
2713 }
2714 // Read the register value from register Rn.
2715 uint32_t val1 = ReadCoreReg(Rn, &success);
2716 if (!success)
2717 return false;
2718
2719 // Read the register value from register Rm.
2720 uint32_t val2 = ReadCoreReg(Rm, &success);
2721 if (!success)
2722 return false;
2723
2724 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002725 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002726
2727 EmulateInstruction::Context context;
2728 context.type = EmulateInstruction::eContextImmediate;
2729 context.SetNoArgs();
2730 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2731 return false;
2732
2733 return true;
2734}
2735
2736// Compare (immediate) subtracts an immediate value from a register value.
2737// It updates the condition flags based on the result, and discards the result.
2738bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002739EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002740{
2741#if 0
2742 // ARM pseudo code...
2743 if ConditionPassed() then
2744 EncodingSpecificOperations();
2745 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2746 APSR.N = result<31>;
2747 APSR.Z = IsZeroBit(result);
2748 APSR.C = carry;
2749 APSR.V = overflow;
2750#endif
2751
2752 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002753
2754 uint32_t Rn; // the first operand
2755 uint32_t imm32; // the immediate value to be compared with
2756 switch (encoding) {
2757 case eEncodingT1:
2758 Rn = Bits32(opcode, 10, 8);
2759 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002760 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002761 case eEncodingT2:
2762 Rn = Bits32(opcode, 19, 16);
2763 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2764 if (Rn == 15)
2765 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002766 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002767 case eEncodingA1:
2768 Rn = Bits32(opcode, 19, 16);
2769 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002770 break;
2771 default:
2772 return false;
2773 }
2774 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002775 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002776 if (!success)
2777 return false;
2778
Johnny Chen10530c22011-02-17 22:37:12 +00002779 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2780
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002781 EmulateInstruction::Context context;
2782 context.type = EmulateInstruction::eContextImmediate;
2783 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002784 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2785 return false;
2786
Johnny Chend4dc4442011-02-11 02:02:56 +00002787 return true;
2788}
2789
Johnny Chen34075cb2011-02-22 01:56:31 +00002790// Compare (register) subtracts an optionally-shifted register value from a register value.
2791// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002792bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002793EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002794{
2795#if 0
2796 // ARM pseudo code...
2797 if ConditionPassed() then
2798 EncodingSpecificOperations();
2799 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2800 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2801 APSR.N = result<31>;
2802 APSR.Z = IsZeroBit(result);
2803 APSR.C = carry;
2804 APSR.V = overflow;
2805#endif
2806
2807 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002808
2809 uint32_t Rn; // the first operand
2810 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002811 ARM_ShifterType shift_t;
2812 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002813 switch (encoding) {
2814 case eEncodingT1:
2815 Rn = Bits32(opcode, 2, 0);
2816 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002817 shift_t = SRType_LSL;
2818 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002819 break;
2820 case eEncodingT2:
2821 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2822 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002823 shift_t = SRType_LSL;
2824 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002825 if (Rn < 8 && Rm < 8)
2826 return false;
2827 if (Rn == 15 || Rm == 15)
2828 return false;
2829 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002830 case eEncodingA1:
2831 Rn = Bits32(opcode, 19, 16);
2832 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002833 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002834 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002835 default:
2836 return false;
2837 }
2838 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002839 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002840 if (!success)
2841 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002842
Johnny Chene4a4d302011-02-11 21:53:58 +00002843 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002844 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002845 if (!success)
2846 return false;
2847
Johnny Chen34075cb2011-02-22 01:56:31 +00002848 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2849 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002850
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002851 EmulateInstruction::Context context;
2852 context.type = EmulateInstruction::eContextImmediate;
2853 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002854 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2855 return false;
2856
Johnny Chene4a4d302011-02-11 21:53:58 +00002857 return true;
2858}
2859
Johnny Chen82f16aa2011-02-15 20:10:55 +00002860// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2861// shifting in copies of its sign bit, and writes the result to the destination register. It can
2862// optionally update the condition flags based on the result.
2863bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002864EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002865{
2866#if 0
2867 // ARM pseudo code...
2868 if ConditionPassed() then
2869 EncodingSpecificOperations();
2870 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2871 if d == 15 then // Can only occur for ARM encoding
2872 ALUWritePC(result); // setflags is always FALSE here
2873 else
2874 R[d] = result;
2875 if setflags then
2876 APSR.N = result<31>;
2877 APSR.Z = IsZeroBit(result);
2878 APSR.C = carry;
2879 // APSR.V unchanged
2880#endif
2881
Greg Clayton7bc39082011-03-24 23:53:38 +00002882 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002883}
2884
2885// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2886// shifting in copies of its sign bit, and writes the result to the destination register.
2887// The variable number of bits is read from the bottom byte of a register. It can optionally update
2888// the condition flags based on the result.
2889bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002890EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002891{
2892#if 0
2893 // ARM pseudo code...
2894 if ConditionPassed() then
2895 EncodingSpecificOperations();
2896 shift_n = UInt(R[m]<7:0>);
2897 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2898 R[d] = result;
2899 if setflags then
2900 APSR.N = result<31>;
2901 APSR.Z = IsZeroBit(result);
2902 APSR.C = carry;
2903 // APSR.V unchanged
2904#endif
2905
Greg Clayton7bc39082011-03-24 23:53:38 +00002906 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002907}
2908
2909// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2910// shifting in zeros, and writes the result to the destination register. It can optionally
2911// update the condition flags based on the result.
2912bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002913EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002914{
2915#if 0
2916 // ARM pseudo code...
2917 if ConditionPassed() then
2918 EncodingSpecificOperations();
2919 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2920 if d == 15 then // Can only occur for ARM encoding
2921 ALUWritePC(result); // setflags is always FALSE here
2922 else
2923 R[d] = result;
2924 if setflags then
2925 APSR.N = result<31>;
2926 APSR.Z = IsZeroBit(result);
2927 APSR.C = carry;
2928 // APSR.V unchanged
2929#endif
2930
Greg Clayton7bc39082011-03-24 23:53:38 +00002931 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002932}
2933
2934// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2935// shifting in zeros, and writes the result to the destination register. The variable number
2936// of bits is read from the bottom byte of a register. It can optionally update the condition
2937// flags based on the result.
2938bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002939EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002940{
2941#if 0
2942 // ARM pseudo code...
2943 if ConditionPassed() then
2944 EncodingSpecificOperations();
2945 shift_n = UInt(R[m]<7:0>);
2946 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2947 R[d] = result;
2948 if setflags then
2949 APSR.N = result<31>;
2950 APSR.Z = IsZeroBit(result);
2951 APSR.C = carry;
2952 // APSR.V unchanged
2953#endif
2954
Greg Clayton7bc39082011-03-24 23:53:38 +00002955 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002956}
2957
2958// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2959// shifting in zeros, and writes the result to the destination register. It can optionally
2960// update the condition flags based on the result.
2961bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002962EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002963{
2964#if 0
2965 // ARM pseudo code...
2966 if ConditionPassed() then
2967 EncodingSpecificOperations();
2968 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2969 if d == 15 then // Can only occur for ARM encoding
2970 ALUWritePC(result); // setflags is always FALSE here
2971 else
2972 R[d] = result;
2973 if setflags then
2974 APSR.N = result<31>;
2975 APSR.Z = IsZeroBit(result);
2976 APSR.C = carry;
2977 // APSR.V unchanged
2978#endif
2979
Greg Clayton7bc39082011-03-24 23:53:38 +00002980 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002981}
2982
2983// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2984// shifting in zeros, and writes the result to the destination register. The variable number
2985// of bits is read from the bottom byte of a register. It can optionally update the condition
2986// flags based on the result.
2987bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002988EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002989{
2990#if 0
2991 // ARM pseudo code...
2992 if ConditionPassed() then
2993 EncodingSpecificOperations();
2994 shift_n = UInt(R[m]<7:0>);
2995 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2996 R[d] = result;
2997 if setflags then
2998 APSR.N = result<31>;
2999 APSR.Z = IsZeroBit(result);
3000 APSR.C = carry;
3001 // APSR.V unchanged
3002#endif
3003
Greg Clayton7bc39082011-03-24 23:53:38 +00003004 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003005}
3006
Johnny Cheneeab4852011-02-16 22:14:44 +00003007// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3008// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3009// It can optionally update the condition flags based on the result.
3010bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003011EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003012{
3013#if 0
3014 // ARM pseudo code...
3015 if ConditionPassed() then
3016 EncodingSpecificOperations();
3017 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3018 if d == 15 then // Can only occur for ARM encoding
3019 ALUWritePC(result); // setflags is always FALSE here
3020 else
3021 R[d] = result;
3022 if setflags then
3023 APSR.N = result<31>;
3024 APSR.Z = IsZeroBit(result);
3025 APSR.C = carry;
3026 // APSR.V unchanged
3027#endif
3028
Greg Clayton7bc39082011-03-24 23:53:38 +00003029 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003030}
3031
3032// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3033// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3034// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3035// flags based on the result.
3036bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003037EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003038{
3039#if 0
3040 // ARM pseudo code...
3041 if ConditionPassed() then
3042 EncodingSpecificOperations();
3043 shift_n = UInt(R[m]<7:0>);
3044 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3045 R[d] = result;
3046 if setflags then
3047 APSR.N = result<31>;
3048 APSR.Z = IsZeroBit(result);
3049 APSR.C = carry;
3050 // APSR.V unchanged
3051#endif
3052
Greg Clayton7bc39082011-03-24 23:53:38 +00003053 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003054}
3055
3056// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3057// with the carry flag shifted into bit [31].
3058//
3059// RRX can optionally update the condition flags based on the result.
3060// In that case, bit [0] is shifted into the carry flag.
3061bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003062EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003063{
3064#if 0
3065 // ARM pseudo code...
3066 if ConditionPassed() then
3067 EncodingSpecificOperations();
3068 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3069 if d == 15 then // Can only occur for ARM encoding
3070 ALUWritePC(result); // setflags is always FALSE here
3071 else
3072 R[d] = result;
3073 if setflags then
3074 APSR.N = result<31>;
3075 APSR.Z = IsZeroBit(result);
3076 APSR.C = carry;
3077 // APSR.V unchanged
3078#endif
3079
Greg Clayton7bc39082011-03-24 23:53:38 +00003080 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003081}
3082
Johnny Chen41a0a152011-02-16 01:27:54 +00003083bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003084EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003085{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003086 assert(shift_type == SRType_ASR
3087 || shift_type == SRType_LSL
3088 || shift_type == SRType_LSR
3089 || shift_type == SRType_ROR
3090 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003091
Johnny Chen82f16aa2011-02-15 20:10:55 +00003092 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003093
Greg Clayton7bc39082011-03-24 23:53:38 +00003094 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003095 {
Johnny Chene7f89532011-02-15 23:22:46 +00003096 uint32_t Rd; // the destination register
3097 uint32_t Rm; // the first operand register
3098 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003099 uint32_t carry; // the carry bit after the shift operation
3100 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003101
3102 // Special case handling!
3103 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003104 ARMEncoding use_encoding = encoding;
3105 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003106 {
3107 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3108 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003109 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003110 }
3111
Greg Clayton7bc39082011-03-24 23:53:38 +00003112 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003113 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003114 // Due to the above special case handling!
3115 assert(shift_type != SRType_ROR);
3116
Johnny Chen82f16aa2011-02-15 20:10:55 +00003117 Rd = Bits32(opcode, 2, 0);
3118 Rm = Bits32(opcode, 5, 3);
3119 setflags = !InITBlock();
3120 imm5 = Bits32(opcode, 10, 6);
3121 break;
3122 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003123 // A8.6.141 RRX
3124 assert(shift_type != SRType_RRX);
3125
Johnny Chen82f16aa2011-02-15 20:10:55 +00003126 Rd = Bits32(opcode, 11, 8);
3127 Rm = Bits32(opcode, 3, 0);
3128 setflags = BitIsSet(opcode, 20);
3129 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3130 if (BadReg(Rd) || BadReg(Rm))
3131 return false;
3132 break;
3133 case eEncodingA1:
3134 Rd = Bits32(opcode, 15, 12);
3135 Rm = Bits32(opcode, 3, 0);
3136 setflags = BitIsSet(opcode, 20);
3137 imm5 = Bits32(opcode, 11, 7);
3138 break;
3139 default:
3140 return false;
3141 }
3142
Johnny Cheneeab4852011-02-16 22:14:44 +00003143 // A8.6.139 ROR (immediate)
3144 if (shift_type == SRType_ROR && imm5 == 0)
3145 shift_type = SRType_RRX;
3146
Johnny Chen82f16aa2011-02-15 20:10:55 +00003147 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003148 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003149 if (!success)
3150 return false;
3151
Johnny Cheneeab4852011-02-16 22:14:44 +00003152 // Decode the shift amount if not RRX.
3153 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003154
Johnny Chene97c0d52011-02-18 19:32:20 +00003155 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003156
3157 // The context specifies that an immediate is to be moved into Rd.
3158 EmulateInstruction::Context context;
3159 context.type = EmulateInstruction::eContextImmediate;
3160 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003161
Johnny Chen10530c22011-02-17 22:37:12 +00003162 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003163 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003164 }
3165 return true;
3166}
3167
Johnny Chene7f89532011-02-15 23:22:46 +00003168bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003169EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003170{
Johnny Chen41a0a152011-02-16 01:27:54 +00003171 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003172
3173 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003174
Greg Clayton7bc39082011-03-24 23:53:38 +00003175 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003176 {
3177 uint32_t Rd; // the destination register
3178 uint32_t Rn; // the first operand register
3179 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3180 uint32_t carry; // the carry bit after the shift operation
3181 bool setflags;
3182 switch (encoding) {
3183 case eEncodingT1:
3184 Rd = Bits32(opcode, 2, 0);
3185 Rn = Rd;
3186 Rm = Bits32(opcode, 5, 3);
3187 setflags = !InITBlock();
3188 break;
3189 case eEncodingT2:
3190 Rd = Bits32(opcode, 11, 8);
3191 Rn = Bits32(opcode, 19, 16);
3192 Rm = Bits32(opcode, 3, 0);
3193 setflags = BitIsSet(opcode, 20);
3194 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3195 return false;
3196 break;
3197 case eEncodingA1:
3198 Rd = Bits32(opcode, 15, 12);
3199 Rn = Bits32(opcode, 3, 0);
3200 Rm = Bits32(opcode, 11, 8);
3201 setflags = BitIsSet(opcode, 20);
3202 if (Rd == 15 || Rn == 15 || Rm == 15)
3203 return false;
3204 break;
3205 default:
3206 return false;
3207 }
3208
3209 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003210 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003211 if (!success)
3212 return false;
3213 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003214 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003215 if (!success)
3216 return false;
3217
3218 // Get the shift amount.
3219 uint32_t amt = Bits32(val, 7, 0);
3220
Johnny Chene97c0d52011-02-18 19:32:20 +00003221 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003222
3223 // The context specifies that an immediate is to be moved into Rd.
3224 EmulateInstruction::Context context;
3225 context.type = EmulateInstruction::eContextImmediate;
3226 context.SetNoArgs ();
3227
Johnny Chen10530c22011-02-17 22:37:12 +00003228 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003229 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003230 }
3231 return true;
3232}
3233
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003234// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003235// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003236// can be written back to the base register.
3237bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003238EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003239{
3240#if 0
3241 // ARM pseudo code...
3242 if ConditionPassed()
3243 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3244 address = R[n];
3245
3246 for i = 0 to 14
3247 if registers<i> == '1' then
3248 R[i] = MemA[address, 4]; address = address + 4;
3249 if registers<15> == '1' then
3250 LoadWritePC (MemA[address, 4]);
3251
3252 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3253 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3254
3255#endif
3256
3257 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003258
Greg Clayton7bc39082011-03-24 23:53:38 +00003259 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003260 {
3261 uint32_t n;
3262 uint32_t registers = 0;
3263 bool wback;
3264 const uint32_t addr_byte_size = GetAddressByteSize();
3265 switch (encoding)
3266 {
3267 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003268 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003269 n = Bits32 (opcode, 10, 8);
3270 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003271 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003272 wback = BitIsClear (registers, n);
3273 // if BitCount(registers) < 1 then UNPREDICTABLE;
3274 if (BitCount(registers) < 1)
3275 return false;
3276 break;
3277 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003278 // if W == '1' && Rn == '1101' then SEE POP;
3279 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003280 n = Bits32 (opcode, 19, 16);
3281 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003282 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003283 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003284
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003285 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003286 if ((n == 15)
3287 || (BitCount (registers) < 2)
3288 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3289 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003290
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003291 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003292 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003293 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003294
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003295 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003296 if (wback
3297 && BitIsSet (registers, n))
3298 return false;
3299 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003300
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003301 case eEncodingA1:
3302 n = Bits32 (opcode, 19, 16);
3303 registers = Bits32 (opcode, 15, 0);
3304 wback = BitIsSet (opcode, 21);
3305 if ((n == 15)
3306 || (BitCount (registers) < 1))
3307 return false;
3308 break;
3309 default:
3310 return false;
3311 }
3312
3313 int32_t offset = 0;
3314 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3315 if (!success)
3316 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003317
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003318 EmulateInstruction::Context context;
3319 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003320 RegisterInfo dwarf_reg;
3321 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003322 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003323
3324 for (int i = 0; i < 14; ++i)
3325 {
3326 if (BitIsSet (registers, i))
3327 {
Caroline Tice85aab332011-02-08 23:56:10 +00003328 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003329 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003330 if (wback && (n == 13)) // Pop Instruction
3331 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3332
3333 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003334 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003335 if (!success)
3336 return false;
3337
3338 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3339 return false;
3340
3341 offset += addr_byte_size;
3342 }
3343 }
3344
3345 if (BitIsSet (registers, 15))
3346 {
3347 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003348 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003349 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003350 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003351 if (!success)
3352 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003353 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003354 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003355 return false;
3356 }
3357
3358 if (wback && BitIsClear (registers, n))
3359 {
Caroline Ticefa172202011-02-11 22:49:54 +00003360 // R[n] = R[n] + 4 * BitCount (registers)
3361 int32_t offset = addr_byte_size * BitCount (registers);
3362 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003363 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003364
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003365 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3366 return false;
3367 }
3368 if (wback && BitIsSet (registers, n))
3369 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003370 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003371 }
3372 return true;
3373}
Caroline Tice713c2662011-02-11 17:59:55 +00003374
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003375// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3376// The consecutive memory locations end at this address and the address just below the lowest of those locations
3377// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003378bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003379EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003380{
3381#if 0
3382 // ARM pseudo code...
3383 if ConditionPassed() then
3384 EncodingSpecificOperations();
3385 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003386
Caroline Tice713c2662011-02-11 17:59:55 +00003387 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003388 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003389 R[i] = MemA[address,4]; address = address + 4;
3390
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003391 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003392 LoadWritePC(MemA[address,4]);
3393
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003394 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3395 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003396#endif
3397
3398 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003399
Greg Clayton7bc39082011-03-24 23:53:38 +00003400 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003401 {
3402 uint32_t n;
3403 uint32_t registers = 0;
3404 bool wback;
3405 const uint32_t addr_byte_size = GetAddressByteSize();
3406
3407 // EncodingSpecificOperations();
3408 switch (encoding)
3409 {
3410 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003411 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003412 n = Bits32 (opcode, 19, 16);
3413 registers = Bits32 (opcode, 15, 0);
3414 wback = BitIsSet (opcode, 21);
3415
3416 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3417 if ((n == 15) || (BitCount (registers) < 1))
3418 return false;
3419
3420 break;
3421
3422 default:
3423 return false;
3424 }
3425 // address = R[n] - 4*BitCount(registers) + 4;
3426
3427 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003428 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003429
3430 if (!success)
3431 return false;
3432
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003433 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003434
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003435 EmulateInstruction::Context context;
3436 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003437 RegisterInfo dwarf_reg;
3438 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003439 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003440
3441 // for i = 0 to 14
3442 for (int i = 0; i < 14; ++i)
3443 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003444 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003445 if (BitIsSet (registers, i))
3446 {
3447 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003448 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003449 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003450 if (!success)
3451 return false;
3452 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3453 return false;
3454 offset += addr_byte_size;
3455 }
3456 }
3457
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003458 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003459 // LoadWritePC(MemA[address,4]);
3460 if (BitIsSet (registers, 15))
3461 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003462 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003463 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003464 if (!success)
3465 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003466 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003467 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003468 return false;
3469 }
3470
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003471 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003472 if (wback && BitIsClear (registers, n))
3473 {
Caroline Tice713c2662011-02-11 17:59:55 +00003474 if (!success)
3475 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003476
3477 offset = (addr_byte_size * BitCount (registers)) * -1;
3478 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003479 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003480 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003481 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3482 return false;
3483 }
3484
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003485 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003486 if (wback && BitIsSet (registers, n))
3487 return WriteBits32Unknown (n);
3488 }
3489 return true;
3490}
3491
3492// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3493// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3494// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003495bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003496EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003497{
3498#if 0
3499 // ARM pseudo code...
3500 if ConditionPassed() then
3501 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3502 address = R[n] - 4*BitCount(registers);
3503
3504 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003505 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003506 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003507 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003508 LoadWritePC(MemA[address,4]);
3509
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003510 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3511 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003512#endif
3513
3514 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003515
Greg Clayton7bc39082011-03-24 23:53:38 +00003516 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003517 {
3518 uint32_t n;
3519 uint32_t registers = 0;
3520 bool wback;
3521 const uint32_t addr_byte_size = GetAddressByteSize();
3522 switch (encoding)
3523 {
3524 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003525 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003526 n = Bits32 (opcode, 19, 16);
3527 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003528 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003529 wback = BitIsSet (opcode, 21);
3530
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003531 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003532 if ((n == 15)
3533 || (BitCount (registers) < 2)
3534 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3535 return false;
3536
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003537 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003538 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003539 return false;
3540
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003541 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003542 if (wback && BitIsSet (registers, n))
3543 return false;
3544
3545 break;
3546
3547 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003548 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003549 n = Bits32 (opcode, 19, 16);
3550 registers = Bits32 (opcode, 15, 0);
3551 wback = BitIsSet (opcode, 21);
3552
3553 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3554 if ((n == 15) || (BitCount (registers) < 1))
3555 return false;
3556
3557 break;
3558
3559 default:
3560 return false;
3561 }
3562
Caroline Tice713c2662011-02-11 17:59:55 +00003563 // address = R[n] - 4*BitCount(registers);
3564
Caroline Tice0b29e242011-02-08 23:16:02 +00003565 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003566 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003567
3568 if (!success)
3569 return false;
3570
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003571 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003572 EmulateInstruction::Context context;
3573 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003574 RegisterInfo dwarf_reg;
3575 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003576 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003577
3578 for (int i = 0; i < 14; ++i)
3579 {
3580 if (BitIsSet (registers, i))
3581 {
3582 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003583 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003584 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003585 if (!success)
3586 return false;
3587
3588 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3589 return false;
3590
3591 offset += addr_byte_size;
3592 }
3593 }
3594
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003595 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003596 // LoadWritePC(MemA[address,4]);
3597 if (BitIsSet (registers, 15))
3598 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003599 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003600 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003601 if (!success)
3602 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003603 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003604 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003605 return false;
3606 }
3607
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003608 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003609 if (wback && BitIsClear (registers, n))
3610 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003611 if (!success)
3612 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003613
3614 offset = (addr_byte_size * BitCount (registers)) * -1;
3615 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003616 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003617 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003618 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3619 return false;
3620 }
3621
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003622 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003623 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003624 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003625 }
3626 return true;
3627}
Caroline Tice85aab332011-02-08 23:56:10 +00003628
Caroline Tice713c2662011-02-11 17:59:55 +00003629// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3630// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3631// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003632bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003633EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003634{
3635#if 0
3636 if ConditionPassed() then
3637 EncodingSpecificOperations();
3638 address = R[n] + 4;
3639
3640 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003641 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003642 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003643 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003644 LoadWritePC(MemA[address,4]);
3645
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003646 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3647 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003648#endif
3649
3650 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003651
Greg Clayton7bc39082011-03-24 23:53:38 +00003652 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003653 {
3654 uint32_t n;
3655 uint32_t registers = 0;
3656 bool wback;
3657 const uint32_t addr_byte_size = GetAddressByteSize();
3658 switch (encoding)
3659 {
3660 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003661 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003662 n = Bits32 (opcode, 19, 16);
3663 registers = Bits32 (opcode, 15, 0);
3664 wback = BitIsSet (opcode, 21);
3665
3666 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3667 if ((n == 15) || (BitCount (registers) < 1))
3668 return false;
3669
3670 break;
3671 default:
3672 return false;
3673 }
3674 // address = R[n] + 4;
3675
3676 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003677 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003678
3679 if (!success)
3680 return false;
3681
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003682 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003683
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003684 EmulateInstruction::Context context;
3685 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003686 RegisterInfo dwarf_reg;
3687 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003688 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003689
3690 for (int i = 0; i < 14; ++i)
3691 {
3692 if (BitIsSet (registers, i))
3693 {
3694 // R[i] = MemA[address,4]; address = address + 4;
3695
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003696 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003697 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003698 if (!success)
3699 return false;
3700
3701 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3702 return false;
3703
3704 offset += addr_byte_size;
3705 }
3706 }
3707
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003708 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003709 // LoadWritePC(MemA[address,4]);
3710 if (BitIsSet (registers, 15))
3711 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003712 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003713 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003714 if (!success)
3715 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003716 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003717 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003718 return false;
3719 }
3720
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003721 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003722 if (wback && BitIsClear (registers, n))
3723 {
Caroline Tice85aab332011-02-08 23:56:10 +00003724 if (!success)
3725 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003726
3727 offset = addr_byte_size * BitCount (registers);
3728 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003729 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003730 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003731 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3732 return false;
3733 }
3734
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003735 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003736 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003737 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003738 }
3739 return true;
3740}
Caroline Tice0b29e242011-02-08 23:16:02 +00003741
Johnny Chenef21b592011-02-10 01:52:38 +00003742// Load Register (immediate) calculates an address from a base register value and
3743// an immediate offset, loads a word from memory, and writes to a register.
3744// LDR (immediate, Thumb)
3745bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003746EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003747{
3748#if 0
3749 // ARM pseudo code...
3750 if (ConditionPassed())
3751 {
3752 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3753 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3754 address = if index then offset_addr else R[n];
3755 data = MemU[address,4];
3756 if wback then R[n] = offset_addr;
3757 if t == 15 then
3758 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3759 elsif UnalignedSupport() || address<1:0> = '00' then
3760 R[t] = data;
3761 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3762 }
3763#endif
3764
3765 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003766
Greg Clayton7bc39082011-03-24 23:53:38 +00003767 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003768 {
3769 uint32_t Rt; // the destination register
3770 uint32_t Rn; // the base register
3771 uint32_t imm32; // the immediate offset used to form the address
3772 addr_t offset_addr; // the offset address
3773 addr_t address; // the calculated address
3774 uint32_t data; // the literal data value from memory load
3775 bool add, index, wback;
3776 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003777 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003778 Rt = Bits32(opcode, 2, 0);
3779 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003780 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3781 // index = TRUE; add = TRUE; wback = FALSE
3782 add = true;
3783 index = true;
3784 wback = false;
3785
3786 break;
3787
3788 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003789 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003790 Rt = Bits32 (opcode, 10, 8);
3791 Rn = 13;
3792 imm32 = Bits32 (opcode, 7, 0) << 2;
3793
3794 // index = TRUE; add = TRUE; wback = FALSE;
3795 index = true;
3796 add = true;
3797 wback = false;
3798
3799 break;
3800
3801 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003802 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003803 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3804 Rt = Bits32 (opcode, 15, 12);
3805 Rn = Bits32 (opcode, 19, 16);
3806 imm32 = Bits32 (opcode, 11, 0);
3807
3808 // index = TRUE; add = TRUE; wback = FALSE;
3809 index = true;
3810 add = true;
3811 wback = false;
3812
3813 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3814 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3815 return false;
3816
3817 break;
3818
3819 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003820 // if Rn == '1111' then SEE LDR (literal);
3821 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3822 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3823 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003824 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3825 return false;
3826
3827 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3828 Rt = Bits32 (opcode, 15, 12);
3829 Rn = Bits32 (opcode, 19, 16);
3830 imm32 = Bits32 (opcode, 7, 0);
3831
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003832 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003833 index = BitIsSet (opcode, 10);
3834 add = BitIsSet (opcode, 9);
3835 wback = BitIsSet (opcode, 8);
3836
3837 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3838 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3839 return false;
3840
3841 break;
3842
3843 default:
3844 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003845 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003846 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003847 if (!success)
3848 return false;
3849 if (add)
3850 offset_addr = base + imm32;
3851 else
3852 offset_addr = base - imm32;
3853
3854 address = (index ? offset_addr : base);
3855
Greg Claytonc07d4512011-04-26 23:48:45 +00003856 RegisterInfo base_reg;
3857 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
Johnny Chenef21b592011-02-10 01:52:38 +00003858 if (wback)
3859 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003860 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003861 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3862 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003863
Johnny Chenef21b592011-02-10 01:52:38 +00003864 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3865 return false;
3866 }
3867
3868 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003869 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003870 context.type = EmulateInstruction::eContextRegisterLoad;
3871 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003872
3873 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003874 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003875 if (!success)
3876 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003877
3878 if (Rt == 15)
3879 {
3880 if (Bits32(address, 1, 0) == 0)
3881 {
Johnny Chen668b4512011-02-15 21:08:58 +00003882 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003883 return false;
3884 }
3885 else
3886 return false;
3887 }
3888 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3889 {
3890 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3891 return false;
3892 }
3893 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003894 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003895 }
3896 return true;
3897}
3898
Caroline Ticeaf556562011-02-15 18:42:15 +00003899// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3900// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3901// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003902bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003903EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003904{
3905#if 0
3906 if ConditionPassed() then
3907 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3908 address = R[n];
3909
3910 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003911 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003912 if i == n && wback && i != LowestSetBit(registers) then
3913 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3914 else
3915 MemA[address,4] = R[i];
3916 address = address + 4;
3917
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003918 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003919 MemA[address,4] = PCStoreValue();
3920 if wback then R[n] = R[n] + 4*BitCount(registers);
3921#endif
3922
3923 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003924
Greg Clayton7bc39082011-03-24 23:53:38 +00003925 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003926 {
3927 uint32_t n;
3928 uint32_t registers = 0;
3929 bool wback;
3930 const uint32_t addr_byte_size = GetAddressByteSize();
3931
3932 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3933 switch (encoding)
3934 {
3935 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003936 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003937 n = Bits32 (opcode, 10, 8);
3938 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003939 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003940 wback = true;
3941
3942 // if BitCount(registers) < 1 then UNPREDICTABLE;
3943 if (BitCount (registers) < 1)
3944 return false;
3945
3946 break;
3947
3948 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003949 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003950 n = Bits32 (opcode, 19, 16);
3951 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003952 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003953 wback = BitIsSet (opcode, 21);
3954
3955 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3956 if ((n == 15) || (BitCount (registers) < 2))
3957 return false;
3958
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003959 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003960 if (wback && BitIsSet (registers, n))
3961 return false;
3962
3963 break;
3964
3965 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003966 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003967 n = Bits32 (opcode, 19, 16);
3968 registers = Bits32 (opcode, 15, 0);
3969 wback = BitIsSet (opcode, 21);
3970
3971 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3972 if ((n == 15) || (BitCount (registers) < 1))
3973 return false;
3974
3975 break;
3976
3977 default:
3978 return false;
3979 }
3980
3981 // address = R[n];
3982 int32_t offset = 0;
3983 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3984 if (!success)
3985 return false;
3986
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003987 EmulateInstruction::Context context;
3988 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00003989 RegisterInfo base_reg;
3990 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefa172202011-02-11 22:49:54 +00003991
3992 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003993 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003994 for (int i = 0; i < 14; ++i)
3995 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003996 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003997 if (BitIsSet (registers, i))
3998 {
3999 if (i < lowest_set_bit)
4000 lowest_set_bit = i;
4001 // if i == n && wback && i != LowestSetBit(registers) then
4002 if ((i == n) && wback && (i != lowest_set_bit))
4003 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4004 WriteBits32UnknownToMemory (address + offset);
4005 else
4006 {
4007 // MemA[address,4] = R[i];
4008 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4009 if (!success)
4010 return false;
4011
Greg Claytonc07d4512011-04-26 23:48:45 +00004012 RegisterInfo data_reg;
4013 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004014 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004015 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004016 return false;
4017 }
4018
4019 // address = address + 4;
4020 offset += addr_byte_size;
4021 }
4022 }
4023
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004024 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004025 // MemA[address,4] = PCStoreValue();
4026 if (BitIsSet (registers, 15))
4027 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004028 RegisterInfo pc_reg;
4029 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004030 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004031 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004032 if (!success)
4033 return false;
4034
Caroline Tice8d681f52011-03-17 23:50:16 +00004035 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004036 return false;
4037 }
4038
4039 // if wback then R[n] = R[n] + 4*BitCount(registers);
4040 if (wback)
4041 {
4042 offset = addr_byte_size * BitCount (registers);
4043 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004044 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004045 addr_t data = address + offset;
4046 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4047 return false;
4048 }
4049 }
4050 return true;
4051}
4052
Caroline Ticeaf556562011-02-15 18:42:15 +00004053// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4054// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4055// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004056bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004057EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004058{
4059#if 0
4060 if ConditionPassed() then
4061 EncodingSpecificOperations();
4062 address = R[n] - 4*BitCount(registers) + 4;
4063
4064 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004065 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004066 if i == n && wback && i != LowestSetBit(registers) then
4067 MemA[address,4] = bits(32) UNKNOWN;
4068 else
4069 MemA[address,4] = R[i];
4070 address = address + 4;
4071
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004072 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004073 MemA[address,4] = PCStoreValue();
4074
4075 if wback then R[n] = R[n] - 4*BitCount(registers);
4076#endif
4077
4078 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004079
Greg Clayton7bc39082011-03-24 23:53:38 +00004080 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004081 {
4082 uint32_t n;
4083 uint32_t registers = 0;
4084 bool wback;
4085 const uint32_t addr_byte_size = GetAddressByteSize();
4086
4087 // EncodingSpecificOperations();
4088 switch (encoding)
4089 {
4090 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004091 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004092 n = Bits32 (opcode, 19, 16);
4093 registers = Bits32 (opcode, 15, 0);
4094 wback = BitIsSet (opcode, 21);
4095
4096 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4097 if ((n == 15) || (BitCount (registers) < 1))
4098 return false;
4099 break;
4100 default:
4101 return false;
4102 }
4103
4104 // address = R[n] - 4*BitCount(registers) + 4;
4105 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004106 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004107 if (!success)
4108 return false;
4109
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004110 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004111
4112 EmulateInstruction::Context context;
4113 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004114 RegisterInfo base_reg;
4115 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004116
4117 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004118 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004119 for (int i = 0; i < 14; ++i)
4120 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004121 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004122 if (BitIsSet (registers, i))
4123 {
4124 if (i < lowest_bit_set)
4125 lowest_bit_set = i;
4126 //if i == n && wback && i != LowestSetBit(registers) then
4127 if ((i == n) && wback && (i != lowest_bit_set))
4128 // MemA[address,4] = bits(32) UNKNOWN;
4129 WriteBits32UnknownToMemory (address + offset);
4130 else
4131 {
4132 // MemA[address,4] = R[i];
4133 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4134 if (!success)
4135 return false;
4136
Greg Claytonc07d4512011-04-26 23:48:45 +00004137 RegisterInfo data_reg;
4138 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004139 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004140 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004141 return false;
4142 }
4143
4144 // address = address + 4;
4145 offset += addr_byte_size;
4146 }
4147 }
4148
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004149 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004150 // MemA[address,4] = PCStoreValue();
4151 if (BitIsSet (registers, 15))
4152 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004153 RegisterInfo pc_reg;
4154 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004155 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004156 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004157 if (!success)
4158 return false;
4159
Caroline Tice8d681f52011-03-17 23:50:16 +00004160 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004161 return false;
4162 }
4163
4164 // if wback then R[n] = R[n] - 4*BitCount(registers);
4165 if (wback)
4166 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004167 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004168 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4169 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004170 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004171 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4172 return false;
4173 }
4174 }
4175 return true;
4176}
4177
Caroline Ticeaf556562011-02-15 18:42:15 +00004178// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4179// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4180// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004181bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004182EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004183{
4184#if 0
4185 if ConditionPassed() then
4186 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4187 address = R[n] - 4*BitCount(registers);
4188
4189 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004190 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004191 if i == n && wback && i != LowestSetBit(registers) then
4192 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4193 else
4194 MemA[address,4] = R[i];
4195 address = address + 4;
4196
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004197 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004198 MemA[address,4] = PCStoreValue();
4199
4200 if wback then R[n] = R[n] - 4*BitCount(registers);
4201#endif
4202
4203
4204 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004205
Greg Clayton7bc39082011-03-24 23:53:38 +00004206 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004207 {
4208 uint32_t n;
4209 uint32_t registers = 0;
4210 bool wback;
4211 const uint32_t addr_byte_size = GetAddressByteSize();
4212
4213 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4214 switch (encoding)
4215 {
4216 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004217 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004218 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4219 {
4220 // See PUSH
4221 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004222 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004223 n = Bits32 (opcode, 19, 16);
4224 registers = Bits32 (opcode, 15, 0);
4225 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4226 wback = BitIsSet (opcode, 21);
4227 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4228 if ((n == 15) || BitCount (registers) < 2)
4229 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004230 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004231 if (wback && BitIsSet (registers, n))
4232 return false;
4233 break;
4234
4235 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00004236 // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004237 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4238 {
4239 // See Push
4240 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004241 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004242 n = Bits32 (opcode, 19, 16);
4243 registers = Bits32 (opcode, 15, 0);
4244 wback = BitIsSet (opcode, 21);
4245 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4246 if ((n == 15) || BitCount (registers) < 1)
4247 return false;
4248 break;
4249
4250 default:
4251 return false;
4252 }
4253
4254 // address = R[n] - 4*BitCount(registers);
4255
4256 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004257 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004258 if (!success)
4259 return false;
4260
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004261 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004262
4263 EmulateInstruction::Context context;
4264 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004265 RegisterInfo base_reg;
4266 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004267
4268 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004269 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004270 for (int i = 0; i < 14; ++i)
4271 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004272 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004273 if (BitIsSet (registers, i))
4274 {
4275 if (i < lowest_set_bit)
4276 lowest_set_bit = i;
4277 // if i == n && wback && i != LowestSetBit(registers) then
4278 if ((i == n) && wback && (i != lowest_set_bit))
4279 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4280 WriteBits32UnknownToMemory (address + offset);
4281 else
4282 {
4283 // MemA[address,4] = R[i];
4284 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4285 if (!success)
4286 return false;
4287
Greg Claytonc07d4512011-04-26 23:48:45 +00004288 RegisterInfo data_reg;
4289 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004290 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004291 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004292 return false;
4293 }
4294
4295 // address = address + 4;
4296 offset += addr_byte_size;
4297 }
4298 }
4299
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004300 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004301 // MemA[address,4] = PCStoreValue();
4302 if (BitIsSet (registers, 15))
4303 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004304 RegisterInfo pc_reg;
4305 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004306 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004307 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004308 if (!success)
4309 return false;
4310
Caroline Tice8d681f52011-03-17 23:50:16 +00004311 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004312 return false;
4313 }
4314
4315 // if wback then R[n] = R[n] - 4*BitCount(registers);
4316 if (wback)
4317 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004318 offset = (addr_byte_size * BitCount (registers)) * -1;
4319 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4320 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004321 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004322 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4323 return false;
4324 }
4325 }
4326 return true;
4327}
4328
4329// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4330// from a base register. The consecutive memory locations start just above this address, and the address of the last
4331// of those locations can optionally be written back to the base register.
4332bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004333EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004334{
4335#if 0
4336 if ConditionPassed() then
4337 EncodingSpecificOperations();
4338 address = R[n] + 4;
4339
4340 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004341 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004342 if i == n && wback && i != LowestSetBit(registers) then
4343 MemA[address,4] = bits(32) UNKNOWN;
4344 else
4345 MemA[address,4] = R[i];
4346 address = address + 4;
4347
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004348 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004349 MemA[address,4] = PCStoreValue();
4350
4351 if wback then R[n] = R[n] + 4*BitCount(registers);
4352#endif
4353
4354 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004355
Greg Clayton7bc39082011-03-24 23:53:38 +00004356 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004357 {
4358 uint32_t n;
4359 uint32_t registers = 0;
4360 bool wback;
4361 const uint32_t addr_byte_size = GetAddressByteSize();
4362
4363 // EncodingSpecificOperations();
4364 switch (encoding)
4365 {
4366 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004367 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004368 n = Bits32 (opcode, 19, 16);
4369 registers = Bits32 (opcode, 15, 0);
4370 wback = BitIsSet (opcode, 21);
4371
4372 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4373 if ((n == 15) && (BitCount (registers) < 1))
4374 return false;
4375 break;
4376 default:
4377 return false;
4378 }
4379 // address = R[n] + 4;
4380
4381 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004382 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004383 if (!success)
4384 return false;
4385
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004386 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004387
4388 EmulateInstruction::Context context;
4389 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004390 RegisterInfo base_reg;
4391 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004392
4393 uint32_t lowest_set_bit = 14;
4394 // for i = 0 to 14
4395 for (int i = 0; i < 14; ++i)
4396 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004397 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004398 if (BitIsSet (registers, i))
4399 {
4400 if (i < lowest_set_bit)
4401 lowest_set_bit = i;
4402 // if i == n && wback && i != LowestSetBit(registers) then
4403 if ((i == n) && wback && (i != lowest_set_bit))
4404 // MemA[address,4] = bits(32) UNKNOWN;
4405 WriteBits32UnknownToMemory (address + offset);
4406 // else
4407 else
4408 {
4409 // MemA[address,4] = R[i];
4410 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4411 if (!success)
4412 return false;
4413
Greg Claytonc07d4512011-04-26 23:48:45 +00004414 RegisterInfo data_reg;
4415 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004416 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004417 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004418 return false;
4419 }
4420
4421 // address = address + 4;
4422 offset += addr_byte_size;
4423 }
4424 }
4425
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004426 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004427 // MemA[address,4] = PCStoreValue();
4428 if (BitIsSet (registers, 15))
4429 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004430 RegisterInfo pc_reg;
4431 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004432 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004433 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004434 if (!success)
4435 return false;
4436
Caroline Tice8d681f52011-03-17 23:50:16 +00004437 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004438 return false;
4439 }
4440
4441 // if wback then R[n] = R[n] + 4*BitCount(registers);
4442 if (wback)
4443 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004444 offset = addr_byte_size * BitCount (registers);
4445 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4446 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004447 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004448 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4449 return false;
4450 }
4451 }
4452 return true;
4453}
Caroline Tice7fac8572011-02-15 22:53:54 +00004454
4455// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4456// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4457bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004458EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004459{
4460#if 0
4461 if ConditionPassed() then
4462 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4463 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4464 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004465 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004466 MemU[address,4] = R[t];
4467 else // Can only occur before ARMv7
4468 MemU[address,4] = bits(32) UNKNOWN;
4469 if wback then R[n] = offset_addr;
4470#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004471
Caroline Tice7fac8572011-02-15 22:53:54 +00004472 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004473
Greg Clayton7bc39082011-03-24 23:53:38 +00004474 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004475 {
4476 const uint32_t addr_byte_size = GetAddressByteSize();
4477
4478 uint32_t t;
4479 uint32_t n;
4480 uint32_t imm32;
4481 bool index;
4482 bool add;
4483 bool wback;
4484 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4485 switch (encoding)
4486 {
4487 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004488 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004489 t = Bits32 (opcode, 2, 0);
4490 n = Bits32 (opcode, 5, 3);
4491 imm32 = Bits32 (opcode, 10, 6) << 2;
4492
4493 // index = TRUE; add = TRUE; wback = FALSE;
4494 index = true;
4495 add = false;
4496 wback = false;
4497 break;
4498
4499 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004500 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004501 t = Bits32 (opcode, 10, 8);
4502 n = 13;
4503 imm32 = Bits32 (opcode, 7, 0) << 2;
4504
4505 // index = TRUE; add = TRUE; wback = FALSE;
4506 index = true;
4507 add = true;
4508 wback = false;
4509 break;
4510
4511 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004512 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004513 if (Bits32 (opcode, 19, 16) == 15)
4514 return false;
4515
4516 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4517 t = Bits32 (opcode, 15, 12);
4518 n = Bits32 (opcode, 19, 16);
4519 imm32 = Bits32 (opcode, 11, 0);
4520
4521 // index = TRUE; add = TRUE; wback = FALSE;
4522 index = true;
4523 add = true;
4524 wback = false;
4525
4526 // if t == 15 then UNPREDICTABLE;
4527 if (t == 15)
4528 return false;
4529 break;
4530
4531 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004532 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4533 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4534 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004535 if ((Bits32 (opcode, 19, 16) == 15)
4536 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4537 return false;
4538
4539 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4540 t = Bits32 (opcode, 15, 12);
4541 n = Bits32 (opcode, 19, 16);
4542 imm32 = Bits32 (opcode, 7, 0);
4543
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004544 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004545 index = BitIsSet (opcode, 10);
4546 add = BitIsSet (opcode, 9);
4547 wback = BitIsSet (opcode, 8);
4548
4549 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4550 if ((t == 15) || (wback && (n == t)))
4551 return false;
4552 break;
4553
4554 default:
4555 return false;
4556 }
4557
4558 addr_t offset_addr;
4559 addr_t address;
4560
4561 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004562 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004563 if (!success)
4564 return false;
4565
4566 if (add)
4567 offset_addr = base_address + imm32;
4568 else
4569 offset_addr = base_address - imm32;
4570
4571 // address = if index then offset_addr else R[n];
4572 if (index)
4573 address = offset_addr;
4574 else
4575 address = base_address;
4576
4577 EmulateInstruction::Context context;
4578 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004579 RegisterInfo base_reg;
4580 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004581
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004582 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004583 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4584 {
4585 // MemU[address,4] = R[t];
4586 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4587 if (!success)
4588 return false;
4589
Greg Claytonc07d4512011-04-26 23:48:45 +00004590 RegisterInfo data_reg;
4591 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004592 int32_t offset = address - base_address;
4593 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004594 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004595 return false;
4596 }
4597 else
4598 {
4599 // MemU[address,4] = bits(32) UNKNOWN;
4600 WriteBits32UnknownToMemory (address);
4601 }
4602
4603 // if wback then R[n] = offset_addr;
4604 if (wback)
4605 {
4606 context.type = eContextRegisterLoad;
4607 context.SetAddress (offset_addr);
4608 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4609 return false;
4610 }
4611 }
4612 return true;
4613}
Caroline Ticeaf556562011-02-15 18:42:15 +00004614
Caroline Tice3fd63e92011-02-16 00:33:43 +00004615// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4616// word from a register to memory. The offset register value can optionally be shifted.
4617bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004618EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004619{
4620#if 0
4621 if ConditionPassed() then
4622 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4623 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4624 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4625 address = if index then offset_addr else R[n];
4626 if t == 15 then // Only possible for encoding A1
4627 data = PCStoreValue();
4628 else
4629 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004630 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004631 MemU[address,4] = data;
4632 else // Can only occur before ARMv7
4633 MemU[address,4] = bits(32) UNKNOWN;
4634 if wback then R[n] = offset_addr;
4635#endif
4636
4637 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004638
Greg Clayton7bc39082011-03-24 23:53:38 +00004639 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004640 {
4641 const uint32_t addr_byte_size = GetAddressByteSize();
4642
4643 uint32_t t;
4644 uint32_t n;
4645 uint32_t m;
4646 ARM_ShifterType shift_t;
4647 uint32_t shift_n;
4648 bool index;
4649 bool add;
4650 bool wback;
4651
4652 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4653 switch (encoding)
4654 {
4655 case eEncodingT1:
4656 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4657 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4658 t = Bits32 (opcode, 2, 0);
4659 n = Bits32 (opcode, 5, 3);
4660 m = Bits32 (opcode, 8, 6);
4661
4662 // index = TRUE; add = TRUE; wback = FALSE;
4663 index = true;
4664 add = true;
4665 wback = false;
4666
4667 // (shift_t, shift_n) = (SRType_LSL, 0);
4668 shift_t = SRType_LSL;
4669 shift_n = 0;
4670 break;
4671
4672 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004673 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004674 if (Bits32 (opcode, 19, 16) == 15)
4675 return false;
4676
4677 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4678 t = Bits32 (opcode, 15, 12);
4679 n = Bits32 (opcode, 19, 16);
4680 m = Bits32 (opcode, 3, 0);
4681
4682 // index = TRUE; add = TRUE; wback = FALSE;
4683 index = true;
4684 add = true;
4685 wback = false;
4686
4687 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4688 shift_t = SRType_LSL;
4689 shift_n = Bits32 (opcode, 5, 4);
4690
4691 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4692 if ((t == 15) || (BadReg (m)))
4693 return false;
4694 break;
4695
4696 case eEncodingA1:
4697 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004698 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004699 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4700 t = Bits32 (opcode, 15, 12);
4701 n = Bits32 (opcode, 19, 16);
4702 m = Bits32 (opcode, 3, 0);
4703
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004704 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004705 index = BitIsSet (opcode, 24);
4706 add = BitIsSet (opcode, 23);
4707 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4708
4709 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4710 uint32_t typ = Bits32 (opcode, 6, 5);
4711 uint32_t imm5 = Bits32 (opcode, 11, 7);
4712 shift_n = DecodeImmShift(typ, imm5, shift_t);
4713
4714 // if m == 15 then UNPREDICTABLE;
4715 if (m == 15)
4716 return false;
4717
4718 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4719 if (wback && ((n == 15) || (n == t)))
4720 return false;
4721
4722 break;
4723 }
4724 default:
4725 return false;
4726 }
4727
4728 addr_t offset_addr;
4729 addr_t address;
4730 int32_t offset = 0;
4731
4732 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4733 if (!success)
4734 return false;
4735
4736 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4737 if (!success)
4738 return false;
4739
4740 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004741 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004742
4743 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4744 if (add)
4745 offset_addr = base_address + offset;
4746 else
4747 offset_addr = base_address - offset;
4748
4749 // address = if index then offset_addr else R[n];
4750 if (index)
4751 address = offset_addr;
4752 else
4753 address = base_address;
4754
4755 uint32_t data;
4756 // if t == 15 then // Only possible for encoding A1
4757 if (t == 15)
4758 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004759 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004760 else
4761 // data = R[t];
4762 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4763
4764 if (!success)
4765 return false;
4766
4767 EmulateInstruction::Context context;
4768 context.type = eContextRegisterStore;
4769
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004770 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004771 if (UnalignedSupport ()
4772 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4773 || CurrentInstrSet() == eModeARM)
4774 {
4775 // MemU[address,4] = data;
4776
Greg Claytonc07d4512011-04-26 23:48:45 +00004777 RegisterInfo base_reg;
4778 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004779
Greg Claytonc07d4512011-04-26 23:48:45 +00004780 RegisterInfo data_reg;
4781 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004782
4783 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004784 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004785 return false;
4786
4787 }
4788 else
4789 // MemU[address,4] = bits(32) UNKNOWN;
4790 WriteBits32UnknownToMemory (address);
4791
4792 // if wback then R[n] = offset_addr;
4793 if (wback)
4794 {
4795 context.type = eContextRegisterLoad;
4796 context.SetAddress (offset_addr);
4797 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4798 return false;
4799 }
4800
4801 }
4802 return true;
4803}
Caroline Tice73a29de2011-02-16 20:22:22 +00004804
4805bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004806EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004807{
4808#if 0
4809 if ConditionPassed() then
4810 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4811 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4812 address = if index then offset_addr else R[n];
4813 MemU[address,1] = R[t]<7:0>;
4814 if wback then R[n] = offset_addr;
4815#endif
4816
4817
4818 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004819
Greg Clayton7bc39082011-03-24 23:53:38 +00004820 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004821 {
4822 uint32_t t;
4823 uint32_t n;
4824 uint32_t imm32;
4825 bool index;
4826 bool add;
4827 bool wback;
4828 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4829 switch (encoding)
4830 {
4831 case eEncodingT1:
4832 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4833 t = Bits32 (opcode, 2, 0);
4834 n = Bits32 (opcode, 5, 3);
4835 imm32 = Bits32 (opcode, 10, 6);
4836
4837 // index = TRUE; add = TRUE; wback = FALSE;
4838 index = true;
4839 add = true;
4840 wback = false;
4841 break;
4842
4843 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004844 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004845 if (Bits32 (opcode, 19, 16) == 15)
4846 return false;
4847
4848 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4849 t = Bits32 (opcode, 15, 12);
4850 n = Bits32 (opcode, 19, 16);
4851 imm32 = Bits32 (opcode, 11, 0);
4852
4853 // index = TRUE; add = TRUE; wback = FALSE;
4854 index = true;
4855 add = true;
4856 wback = false;
4857
4858 // if BadReg(t) then UNPREDICTABLE;
4859 if (BadReg (t))
4860 return false;
4861 break;
4862
4863 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004864 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4865 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004866 if (Bits32 (opcode, 19, 16) == 15)
4867 return false;
4868
4869 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4870 t = Bits32 (opcode, 15, 12);
4871 n = Bits32 (opcode, 19, 16);
4872 imm32 = Bits32 (opcode, 7, 0);
4873
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004874 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004875 index = BitIsSet (opcode, 10);
4876 add = BitIsSet (opcode, 9);
4877 wback = BitIsSet (opcode, 8);
4878
4879 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4880 if ((BadReg (t)) || (wback && (n == t)))
4881 return false;
4882 break;
4883
4884 default:
4885 return false;
4886 }
4887
4888 addr_t offset_addr;
4889 addr_t address;
4890 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4891 if (!success)
4892 return false;
4893
4894 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4895 if (add)
4896 offset_addr = base_address + imm32;
4897 else
4898 offset_addr = base_address - imm32;
4899
4900 // address = if index then offset_addr else R[n];
4901 if (index)
4902 address = offset_addr;
4903 else
4904 address = base_address;
4905
Caroline Ticecc96eb52011-02-17 19:20:40 +00004906 // MemU[address,1] = R[t]<7:0>
Greg Claytonc07d4512011-04-26 23:48:45 +00004907 RegisterInfo base_reg;
4908 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004909
Greg Claytonc07d4512011-04-26 23:48:45 +00004910 RegisterInfo data_reg;
4911 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004912
4913 EmulateInstruction::Context context;
4914 context.type = eContextRegisterStore;
4915 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4916
4917 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4918 if (!success)
4919 return false;
4920
4921 data = Bits32 (data, 7, 0);
4922
Caroline Ticecc96eb52011-02-17 19:20:40 +00004923 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004924 return false;
4925
4926 // if wback then R[n] = offset_addr;
4927 if (wback)
4928 {
4929 context.type = eContextRegisterLoad;
4930 context.SetAddress (offset_addr);
4931 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4932 return false;
4933 }
4934
4935 }
4936
4937 return true;
4938}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004939
4940// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4941// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4942bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004943EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004944{
4945#if 0
4946 if ConditionPassed() then
4947 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4948 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4949 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4950 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004951 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004952 MemU[address,2] = R[t]<15:0>;
4953 else // Can only occur before ARMv7
4954 MemU[address,2] = bits(16) UNKNOWN;
4955 if wback then R[n] = offset_addr;
4956#endif
4957
4958 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004959
Greg Clayton7bc39082011-03-24 23:53:38 +00004960 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004961 {
4962 uint32_t t;
4963 uint32_t n;
4964 uint32_t m;
4965 bool index;
4966 bool add;
4967 bool wback;
4968 ARM_ShifterType shift_t;
4969 uint32_t shift_n;
4970
4971 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4972 switch (encoding)
4973 {
4974 case eEncodingT1:
4975 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4976 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4977 t = Bits32 (opcode, 2, 0);
4978 n = Bits32 (opcode, 5, 3);
4979 m = Bits32 (opcode, 8, 6);
4980
4981 // index = TRUE; add = TRUE; wback = FALSE;
4982 index = true;
4983 add = true;
4984 wback = false;
4985
4986 // (shift_t, shift_n) = (SRType_LSL, 0);
4987 shift_t = SRType_LSL;
4988 shift_n = 0;
4989
4990 break;
4991
4992 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004993 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004994 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4995 t = Bits32 (opcode, 15, 12);
4996 n = Bits32 (opcode, 19, 16);
4997 m = Bits32 (opcode, 3, 0);
4998 if (n == 15)
4999 return false;
5000
5001 // index = TRUE; add = TRUE; wback = FALSE;
5002 index = true;
5003 add = true;
5004 wback = false;
5005
5006 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5007 shift_t = SRType_LSL;
5008 shift_n = Bits32 (opcode, 5, 4);
5009
5010 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5011 if (BadReg (t) || BadReg (m))
5012 return false;
5013
5014 break;
5015
5016 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005017 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005018 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5019 t = Bits32 (opcode, 15, 12);
5020 n = Bits32 (opcode, 19, 16);
5021 m = Bits32 (opcode, 3, 0);
5022
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005023 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005024 index = BitIsSet (opcode, 24);
5025 add = BitIsSet (opcode, 23);
5026 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5027
5028 // (shift_t, shift_n) = (SRType_LSL, 0);
5029 shift_t = SRType_LSL;
5030 shift_n = 0;
5031
5032 // if t == 15 || m == 15 then UNPREDICTABLE;
5033 if ((t == 15) || (m == 15))
5034 return false;
5035
5036 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5037 if (wback && ((n == 15) || (n == t)))
5038 return false;
5039
5040 break;
5041
5042 default:
5043 return false;
5044 }
5045
5046 uint32_t Rm = ReadCoreReg (m, &success);
5047 if (!success)
5048 return false;
5049
5050 uint32_t Rn = ReadCoreReg (n, &success);
5051 if (!success)
5052 return false;
5053
5054 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5055 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5056
5057 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5058 addr_t offset_addr;
5059 if (add)
5060 offset_addr = Rn + offset;
5061 else
5062 offset_addr = Rn - offset;
5063
5064 // address = if index then offset_addr else R[n];
5065 addr_t address;
5066 if (index)
5067 address = offset_addr;
5068 else
5069 address = Rn;
5070
5071 EmulateInstruction::Context context;
5072 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005073 RegisterInfo base_reg;
5074 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5075 RegisterInfo offset_reg;
5076 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005077
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005078 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005079 if (UnalignedSupport() || BitIsClear (address, 0))
5080 {
5081 // MemU[address,2] = R[t]<15:0>;
5082 uint32_t Rt = ReadCoreReg (t, &success);
5083 if (!success)
5084 return false;
5085
5086 EmulateInstruction::Context context;
5087 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005088 RegisterInfo base_reg;
5089 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5090 RegisterInfo offset_reg;
5091 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5092 RegisterInfo data_reg;
5093 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005094 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5095
5096 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5097 return false;
5098 }
5099 else // Can only occur before ARMv7
5100 {
5101 // MemU[address,2] = bits(16) UNKNOWN;
5102 }
5103
5104 // if wback then R[n] = offset_addr;
5105 if (wback)
5106 {
5107 context.type = eContextAdjustBaseRegister;
5108 context.SetAddress (offset_addr);
5109 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5110 return false;
5111 }
5112 }
5113
5114 return true;
5115}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005116
Johnny Chen157b9592011-02-18 21:13:05 +00005117// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5118// and writes the result to the destination register. It can optionally update the condition flags
5119// based on the result.
5120bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005121EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005122{
5123#if 0
5124 // ARM pseudo code...
5125 if ConditionPassed() then
5126 EncodingSpecificOperations();
5127 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5128 if d == 15 then // Can only occur for ARM encoding
5129 ALUWritePC(result); // setflags is always FALSE here
5130 else
5131 R[d] = result;
5132 if setflags then
5133 APSR.N = result<31>;
5134 APSR.Z = IsZeroBit(result);
5135 APSR.C = carry;
5136 APSR.V = overflow;
5137#endif
5138
5139 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005140
Greg Clayton7bc39082011-03-24 23:53:38 +00005141 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005142 {
5143 uint32_t Rd, Rn;
5144 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5145 bool setflags;
5146 switch (encoding)
5147 {
5148 case eEncodingT1:
5149 Rd = Bits32(opcode, 11, 8);
5150 Rn = Bits32(opcode, 19, 16);
5151 setflags = BitIsSet(opcode, 20);
5152 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5153 if (BadReg(Rd) || BadReg(Rn))
5154 return false;
5155 break;
5156 case eEncodingA1:
5157 Rd = Bits32(opcode, 15, 12);
5158 Rn = Bits32(opcode, 19, 16);
5159 setflags = BitIsSet(opcode, 20);
5160 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005161
Johnny Chen157b9592011-02-18 21:13:05 +00005162 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005163 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005164 break;
5165 default:
5166 return false;
5167 }
5168
5169 // Read the first operand.
5170 int32_t val1 = ReadCoreReg(Rn, &success);
5171 if (!success)
5172 return false;
5173
5174 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5175
5176 EmulateInstruction::Context context;
5177 context.type = EmulateInstruction::eContextImmediate;
5178 context.SetNoArgs ();
5179
5180 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5181 return false;
5182 }
5183 return true;
5184}
5185
5186// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5187// register value, and writes the result to the destination register. It can optionally update the
5188// condition flags based on the result.
5189bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005190EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005191{
5192#if 0
5193 // ARM pseudo code...
5194 if ConditionPassed() then
5195 EncodingSpecificOperations();
5196 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5197 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5198 if d == 15 then // Can only occur for ARM encoding
5199 ALUWritePC(result); // setflags is always FALSE here
5200 else
5201 R[d] = result;
5202 if setflags then
5203 APSR.N = result<31>;
5204 APSR.Z = IsZeroBit(result);
5205 APSR.C = carry;
5206 APSR.V = overflow;
5207#endif
5208
5209 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005210
Greg Clayton7bc39082011-03-24 23:53:38 +00005211 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005212 {
5213 uint32_t Rd, Rn, Rm;
5214 ARM_ShifterType shift_t;
5215 uint32_t shift_n; // the shift applied to the value read from Rm
5216 bool setflags;
5217 switch (encoding)
5218 {
5219 case eEncodingT1:
5220 Rd = Rn = Bits32(opcode, 2, 0);
5221 Rm = Bits32(opcode, 5, 3);
5222 setflags = !InITBlock();
5223 shift_t = SRType_LSL;
5224 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005225 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005226 case eEncodingT2:
5227 Rd = Bits32(opcode, 11, 8);
5228 Rn = Bits32(opcode, 19, 16);
5229 Rm = Bits32(opcode, 3, 0);
5230 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005231 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005232 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5233 return false;
5234 break;
5235 case eEncodingA1:
5236 Rd = Bits32(opcode, 15, 12);
5237 Rn = Bits32(opcode, 19, 16);
5238 Rm = Bits32(opcode, 3, 0);
5239 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005240 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005241
Johnny Chen157b9592011-02-18 21:13:05 +00005242 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005243 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005244 break;
5245 default:
5246 return false;
5247 }
5248
5249 // Read the first operand.
5250 int32_t val1 = ReadCoreReg(Rn, &success);
5251 if (!success)
5252 return false;
5253
5254 // Read the second operand.
5255 int32_t val2 = ReadCoreReg(Rm, &success);
5256 if (!success)
5257 return false;
5258
5259 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5260 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5261
5262 EmulateInstruction::Context context;
5263 context.type = EmulateInstruction::eContextImmediate;
5264 context.SetNoArgs ();
5265
5266 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5267 return false;
5268 }
5269 return true;
5270}
5271
Johnny Chena695f952011-02-23 21:24:25 +00005272// This instruction adds an immediate value to the PC value to form a PC-relative address,
5273// and writes the result to the destination register.
5274bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005275EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005276{
5277#if 0
5278 // ARM pseudo code...
5279 if ConditionPassed() then
5280 EncodingSpecificOperations();
5281 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5282 if d == 15 then // Can only occur for ARM encodings
5283 ALUWritePC(result);
5284 else
5285 R[d] = result;
5286#endif
5287
5288 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005289
Greg Clayton7bc39082011-03-24 23:53:38 +00005290 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005291 {
5292 uint32_t Rd;
5293 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5294 bool add;
5295 switch (encoding)
5296 {
5297 case eEncodingT1:
5298 Rd = Bits32(opcode, 10, 8);
5299 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5300 break;
5301 case eEncodingT2:
5302 case eEncodingT3:
5303 Rd = Bits32(opcode, 11, 8);
5304 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5305 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5306 if (BadReg(Rd))
5307 return false;
5308 break;
5309 case eEncodingA1:
5310 case eEncodingA2:
5311 Rd = Bits32(opcode, 15, 12);
5312 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5313 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5314 break;
5315 default:
5316 return false;
5317 }
5318
5319 // Read the PC value.
5320 uint32_t pc = ReadCoreReg(PC_REG, &success);
5321 if (!success)
5322 return false;
5323
5324 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5325
5326 EmulateInstruction::Context context;
5327 context.type = EmulateInstruction::eContextImmediate;
5328 context.SetNoArgs ();
5329
5330 if (!WriteCoreReg(context, result, Rd))
5331 return false;
5332 }
5333 return true;
5334}
5335
Johnny Chene97c0d52011-02-18 19:32:20 +00005336// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5337// to the destination register. It can optionally update the condition flags based on the result.
5338bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005339EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005340{
5341#if 0
5342 // ARM pseudo code...
5343 if ConditionPassed() then
5344 EncodingSpecificOperations();
5345 result = R[n] AND imm32;
5346 if d == 15 then // Can only occur for ARM encoding
5347 ALUWritePC(result); // setflags is always FALSE here
5348 else
5349 R[d] = result;
5350 if setflags then
5351 APSR.N = result<31>;
5352 APSR.Z = IsZeroBit(result);
5353 APSR.C = carry;
5354 // APSR.V unchanged
5355#endif
5356
5357 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005358
Greg Clayton7bc39082011-03-24 23:53:38 +00005359 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005360 {
5361 uint32_t Rd, Rn;
5362 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5363 bool setflags;
5364 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5365 switch (encoding)
5366 {
5367 case eEncodingT1:
5368 Rd = Bits32(opcode, 11, 8);
5369 Rn = Bits32(opcode, 19, 16);
5370 setflags = BitIsSet(opcode, 20);
5371 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005372 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005373 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005374 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005375 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5376 return false;
5377 break;
5378 case eEncodingA1:
5379 Rd = Bits32(opcode, 15, 12);
5380 Rn = Bits32(opcode, 19, 16);
5381 setflags = BitIsSet(opcode, 20);
5382 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005383
Johnny Chene97c0d52011-02-18 19:32:20 +00005384 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005385 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005386 break;
5387 default:
5388 return false;
5389 }
5390
Johnny Chene97c0d52011-02-18 19:32:20 +00005391 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005392 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005393 if (!success)
5394 return false;
5395
5396 uint32_t result = val1 & imm32;
5397
5398 EmulateInstruction::Context context;
5399 context.type = EmulateInstruction::eContextImmediate;
5400 context.SetNoArgs ();
5401
5402 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5403 return false;
5404 }
5405 return true;
5406}
5407
5408// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5409// and writes the result to the destination register. It can optionally update the condition flags
5410// based on the result.
5411bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005412EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005413{
5414#if 0
5415 // ARM pseudo code...
5416 if ConditionPassed() then
5417 EncodingSpecificOperations();
5418 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5419 result = R[n] AND shifted;
5420 if d == 15 then // Can only occur for ARM encoding
5421 ALUWritePC(result); // setflags is always FALSE here
5422 else
5423 R[d] = result;
5424 if setflags then
5425 APSR.N = result<31>;
5426 APSR.Z = IsZeroBit(result);
5427 APSR.C = carry;
5428 // APSR.V unchanged
5429#endif
5430
5431 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005432
Greg Clayton7bc39082011-03-24 23:53:38 +00005433 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005434 {
5435 uint32_t Rd, Rn, Rm;
5436 ARM_ShifterType shift_t;
5437 uint32_t shift_n; // the shift applied to the value read from Rm
5438 bool setflags;
5439 uint32_t carry;
5440 switch (encoding)
5441 {
5442 case eEncodingT1:
5443 Rd = Rn = Bits32(opcode, 2, 0);
5444 Rm = Bits32(opcode, 5, 3);
5445 setflags = !InITBlock();
5446 shift_t = SRType_LSL;
5447 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005448 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005449 case eEncodingT2:
5450 Rd = Bits32(opcode, 11, 8);
5451 Rn = Bits32(opcode, 19, 16);
5452 Rm = Bits32(opcode, 3, 0);
5453 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005454 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005455 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005456 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005457 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005458 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5459 return false;
5460 break;
5461 case eEncodingA1:
5462 Rd = Bits32(opcode, 15, 12);
5463 Rn = Bits32(opcode, 19, 16);
5464 Rm = Bits32(opcode, 3, 0);
5465 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005466 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005467
Johnny Chene97c0d52011-02-18 19:32:20 +00005468 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005469 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005470 break;
5471 default:
5472 return false;
5473 }
5474
Johnny Chene97c0d52011-02-18 19:32:20 +00005475 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005476 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005477 if (!success)
5478 return false;
5479
5480 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005481 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005482 if (!success)
5483 return false;
5484
5485 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5486 uint32_t result = val1 & shifted;
5487
5488 EmulateInstruction::Context context;
5489 context.type = EmulateInstruction::eContextImmediate;
5490 context.SetNoArgs ();
5491
5492 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5493 return false;
5494 }
5495 return true;
5496}
5497
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005498// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5499// immediate value, and writes the result to the destination register. It can optionally update the
5500// condition flags based on the result.
5501bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005502EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005503{
5504#if 0
5505 // ARM pseudo code...
5506 if ConditionPassed() then
5507 EncodingSpecificOperations();
5508 result = R[n] AND NOT(imm32);
5509 if d == 15 then // Can only occur for ARM encoding
5510 ALUWritePC(result); // setflags is always FALSE here
5511 else
5512 R[d] = result;
5513 if setflags then
5514 APSR.N = result<31>;
5515 APSR.Z = IsZeroBit(result);
5516 APSR.C = carry;
5517 // APSR.V unchanged
5518#endif
5519
5520 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005521
Greg Clayton7bc39082011-03-24 23:53:38 +00005522 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005523 {
5524 uint32_t Rd, Rn;
5525 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5526 bool setflags;
5527 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5528 switch (encoding)
5529 {
5530 case eEncodingT1:
5531 Rd = Bits32(opcode, 11, 8);
5532 Rn = Bits32(opcode, 19, 16);
5533 setflags = BitIsSet(opcode, 20);
5534 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5535 if (BadReg(Rd) || BadReg(Rn))
5536 return false;
5537 break;
5538 case eEncodingA1:
5539 Rd = Bits32(opcode, 15, 12);
5540 Rn = Bits32(opcode, 19, 16);
5541 setflags = BitIsSet(opcode, 20);
5542 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005543
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005544 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005545 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005546 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005547 break;
5548 default:
5549 return false;
5550 }
5551
5552 // Read the first operand.
5553 uint32_t val1 = ReadCoreReg(Rn, &success);
5554 if (!success)
5555 return false;
5556
5557 uint32_t result = val1 & ~imm32;
5558
5559 EmulateInstruction::Context context;
5560 context.type = EmulateInstruction::eContextImmediate;
5561 context.SetNoArgs ();
5562
5563 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5564 return false;
5565 }
5566 return true;
5567}
5568
5569// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5570// optionally-shifted register value, and writes the result to the destination register.
5571// It can optionally update the condition flags based on the result.
5572bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005573EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005574{
5575#if 0
5576 // ARM pseudo code...
5577 if ConditionPassed() then
5578 EncodingSpecificOperations();
5579 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5580 result = R[n] AND NOT(shifted);
5581 if d == 15 then // Can only occur for ARM encoding
5582 ALUWritePC(result); // setflags is always FALSE here
5583 else
5584 R[d] = result;
5585 if setflags then
5586 APSR.N = result<31>;
5587 APSR.Z = IsZeroBit(result);
5588 APSR.C = carry;
5589 // APSR.V unchanged
5590#endif
5591
5592 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005593
Greg Clayton7bc39082011-03-24 23:53:38 +00005594 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005595 {
5596 uint32_t Rd, Rn, Rm;
5597 ARM_ShifterType shift_t;
5598 uint32_t shift_n; // the shift applied to the value read from Rm
5599 bool setflags;
5600 uint32_t carry;
5601 switch (encoding)
5602 {
5603 case eEncodingT1:
5604 Rd = Rn = Bits32(opcode, 2, 0);
5605 Rm = Bits32(opcode, 5, 3);
5606 setflags = !InITBlock();
5607 shift_t = SRType_LSL;
5608 shift_n = 0;
5609 break;
5610 case eEncodingT2:
5611 Rd = Bits32(opcode, 11, 8);
5612 Rn = Bits32(opcode, 19, 16);
5613 Rm = Bits32(opcode, 3, 0);
5614 setflags = BitIsSet(opcode, 20);
5615 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5616 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5617 return false;
5618 break;
5619 case eEncodingA1:
5620 Rd = Bits32(opcode, 15, 12);
5621 Rn = Bits32(opcode, 19, 16);
5622 Rm = Bits32(opcode, 3, 0);
5623 setflags = BitIsSet(opcode, 20);
5624 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005625
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005626 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005627 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005628 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005629 break;
5630 default:
5631 return false;
5632 }
5633
5634 // Read the first operand.
5635 uint32_t val1 = ReadCoreReg(Rn, &success);
5636 if (!success)
5637 return false;
5638
5639 // Read the second operand.
5640 uint32_t val2 = ReadCoreReg(Rm, &success);
5641 if (!success)
5642 return false;
5643
5644 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5645 uint32_t result = val1 & ~shifted;
5646
5647 EmulateInstruction::Context context;
5648 context.type = EmulateInstruction::eContextImmediate;
5649 context.SetNoArgs ();
5650
5651 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5652 return false;
5653 }
5654 return true;
5655}
5656
Caroline Tice4d729c52011-02-18 00:55:53 +00005657// 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 +00005658// 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 +00005659bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005660EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005661{
5662#if 0
5663 if ConditionPassed() then
5664 EncodingSpecificOperations();
5665 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5666 address = if index then offset_addr else R[n];
5667 data = MemU[address,4];
5668 if wback then R[n] = offset_addr;
5669 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005670 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5671 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005672 R[t] = data;
5673 else // Can only apply before ARMv7
5674 R[t] = ROR(data, 8*UInt(address<1:0>));
5675#endif
5676
5677 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005678
Greg Clayton7bc39082011-03-24 23:53:38 +00005679 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005680 {
5681 const uint32_t addr_byte_size = GetAddressByteSize();
5682
5683 uint32_t t;
5684 uint32_t n;
5685 uint32_t imm32;
5686 bool index;
5687 bool add;
5688 bool wback;
5689
5690 switch (encoding)
5691 {
5692 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005693 // if Rn == '1111' then SEE LDR (literal);
5694 // if P == '0' && W == '1' then SEE LDRT;
5695 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005696 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5697 t = Bits32 (opcode, 15, 12);
5698 n = Bits32 (opcode, 19, 16);
5699 imm32 = Bits32 (opcode, 11, 0);
5700
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005701 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5702 index = BitIsSet (opcode, 24);
5703 add = BitIsSet (opcode, 23);
5704 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005705
5706 // if wback && n == t then UNPREDICTABLE;
5707 if (wback && (n == t))
5708 return false;
5709
5710 break;
5711
5712 default:
5713 return false;
5714 }
5715
5716 addr_t address;
5717 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005718 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005719 if (!success)
5720 return false;
5721
5722 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5723 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005724 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005725 else
5726 offset_addr = base_address - imm32;
5727
5728 // address = if index then offset_addr else R[n];
5729 if (index)
5730 address = offset_addr;
5731 else
5732 address = base_address;
5733
5734 // data = MemU[address,4];
5735
Greg Claytonc07d4512011-04-26 23:48:45 +00005736 RegisterInfo base_reg;
5737 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4d729c52011-02-18 00:55:53 +00005738
5739 EmulateInstruction::Context context;
5740 context.type = eContextRegisterLoad;
5741 context.SetRegisterPlusOffset (base_reg, address - base_address);
5742
5743 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5744 if (!success)
5745 return false;
5746
5747 // if wback then R[n] = offset_addr;
5748 if (wback)
5749 {
5750 context.type = eContextAdjustBaseRegister;
5751 context.SetAddress (offset_addr);
5752 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5753 return false;
5754 }
5755
5756 // if t == 15 then
5757 if (t == 15)
5758 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005759 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005760 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5761 {
5762 // LoadWritePC (data);
5763 context.type = eContextRegisterLoad;
5764 context.SetRegisterPlusOffset (base_reg, address - base_address);
5765 LoadWritePC (context, data);
5766 }
5767 else
5768 return false;
5769 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005770 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005771 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5772 {
5773 // R[t] = data;
5774 context.type = eContextRegisterLoad;
5775 context.SetRegisterPlusOffset (base_reg, address - base_address);
5776 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5777 return false;
5778 }
5779 // else // Can only apply before ARMv7
5780 else
5781 {
5782 // R[t] = ROR(data, 8*UInt(address<1:0>));
5783 data = ROR (data, Bits32 (address, 1, 0));
5784 context.type = eContextRegisterLoad;
5785 context.SetImmediate (data);
5786 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5787 return false;
5788 }
5789
5790 }
5791 return true;
5792}
5793
Caroline Ticefe479112011-02-18 18:52:37 +00005794// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5795// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5796bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005797EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005798{
5799#if 0
5800 if ConditionPassed() then
5801 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5802 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5803 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5804 address = if index then offset_addr else R[n];
5805 data = MemU[address,4];
5806 if wback then R[n] = offset_addr;
5807 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005808 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5809 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005810 R[t] = data;
5811 else // Can only apply before ARMv7
5812 if CurrentInstrSet() == InstrSet_ARM then
5813 R[t] = ROR(data, 8*UInt(address<1:0>));
5814 else
5815 R[t] = bits(32) UNKNOWN;
5816#endif
5817
5818 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005819
Greg Clayton7bc39082011-03-24 23:53:38 +00005820 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005821 {
5822 const uint32_t addr_byte_size = GetAddressByteSize();
5823
5824 uint32_t t;
5825 uint32_t n;
5826 uint32_t m;
5827 bool index;
5828 bool add;
5829 bool wback;
5830 ARM_ShifterType shift_t;
5831 uint32_t shift_n;
5832
5833 switch (encoding)
5834 {
5835 case eEncodingT1:
5836 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5837 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5838 t = Bits32 (opcode, 2, 0);
5839 n = Bits32 (opcode, 5, 3);
5840 m = Bits32 (opcode, 8, 6);
5841
5842 // index = TRUE; add = TRUE; wback = FALSE;
5843 index = true;
5844 add = true;
5845 wback = false;
5846
5847 // (shift_t, shift_n) = (SRType_LSL, 0);
5848 shift_t = SRType_LSL;
5849 shift_n = 0;
5850
5851 break;
5852
5853 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005854 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005855 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5856 t = Bits32 (opcode, 15, 12);
5857 n = Bits32 (opcode, 19, 16);
5858 m = Bits32 (opcode, 3, 0);
5859
5860 // index = TRUE; add = TRUE; wback = FALSE;
5861 index = true;
5862 add = true;
5863 wback = false;
5864
5865 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5866 shift_t = SRType_LSL;
5867 shift_n = Bits32 (opcode, 5, 4);
5868
5869 // if BadReg(m) then UNPREDICTABLE;
5870 if (BadReg (m))
5871 return false;
5872
5873 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5874 if ((t == 15) && InITBlock() && !LastInITBlock())
5875 return false;
5876
5877 break;
5878
5879 case eEncodingA1:
5880 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005881 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005882 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5883 t = Bits32 (opcode, 15, 12);
5884 n = Bits32 (opcode, 19, 16);
5885 m = Bits32 (opcode, 3, 0);
5886
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005887 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005888 index = BitIsSet (opcode, 24);
5889 add = BitIsSet (opcode, 23);
5890 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5891
5892 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5893 uint32_t type = Bits32 (opcode, 6, 5);
5894 uint32_t imm5 = Bits32 (opcode, 11, 7);
5895 shift_n = DecodeImmShift (type, imm5, shift_t);
5896
5897 // if m == 15 then UNPREDICTABLE;
5898 if (m == 15)
5899 return false;
5900
5901 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5902 if (wback && ((n == 15) || (n == t)))
5903 return false;
5904 }
5905 break;
5906
5907
5908 default:
5909 return false;
5910 }
5911
5912 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5913 if (!success)
5914 return false;
5915
5916 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5917 if (!success)
5918 return false;
5919
5920 addr_t offset_addr;
5921 addr_t address;
5922
5923 // 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 +00005924 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005925
5926 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5927 if (add)
5928 offset_addr = Rn + offset;
5929 else
5930 offset_addr = Rn - offset;
5931
5932 // address = if index then offset_addr else R[n];
5933 if (index)
5934 address = offset_addr;
5935 else
5936 address = Rn;
5937
5938 // data = MemU[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +00005939 RegisterInfo base_reg;
5940 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefe479112011-02-18 18:52:37 +00005941
5942 EmulateInstruction::Context context;
5943 context.type = eContextRegisterLoad;
5944 context.SetRegisterPlusOffset (base_reg, address - Rn);
5945
5946 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5947 if (!success)
5948 return false;
5949
5950 // if wback then R[n] = offset_addr;
5951 if (wback)
5952 {
5953 context.type = eContextAdjustBaseRegister;
5954 context.SetAddress (offset_addr);
5955 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5956 return false;
5957 }
5958
5959 // if t == 15 then
5960 if (t == 15)
5961 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005962 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005963 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5964 {
5965 context.type = eContextRegisterLoad;
5966 context.SetRegisterPlusOffset (base_reg, address - Rn);
5967 LoadWritePC (context, data);
5968 }
5969 else
5970 return false;
5971 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005972 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005973 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5974 {
5975 // R[t] = data;
5976 context.type = eContextRegisterLoad;
5977 context.SetRegisterPlusOffset (base_reg, address - Rn);
5978 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5979 return false;
5980 }
5981 else // Can only apply before ARMv7
5982 {
5983 // if CurrentInstrSet() == InstrSet_ARM then
5984 if (CurrentInstrSet () == eModeARM)
5985 {
5986 // R[t] = ROR(data, 8*UInt(address<1:0>));
5987 data = ROR (data, Bits32 (address, 1, 0));
5988 context.type = eContextRegisterLoad;
5989 context.SetImmediate (data);
5990 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5991 return false;
5992 }
5993 else
5994 {
5995 // R[t] = bits(32) UNKNOWN;
5996 WriteBits32Unknown (t);
5997 }
5998 }
5999 }
6000 return true;
6001}
Caroline Tice21b604b2011-02-18 21:06:04 +00006002
6003// LDRB (immediate, Thumb)
6004bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006005EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00006006{
6007#if 0
6008 if ConditionPassed() then
6009 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6010 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6011 address = if index then offset_addr else R[n];
6012 R[t] = ZeroExtend(MemU[address,1], 32);
6013 if wback then R[n] = offset_addr;
6014#endif
6015
6016 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00006017
Greg Clayton7bc39082011-03-24 23:53:38 +00006018 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00006019 {
6020 uint32_t t;
6021 uint32_t n;
6022 uint32_t imm32;
6023 bool index;
6024 bool add;
6025 bool wback;
6026
6027 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6028 switch (encoding)
6029 {
6030 case eEncodingT1:
6031 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6032 t = Bits32 (opcode, 2, 0);
6033 n = Bits32 (opcode, 5, 3);
6034 imm32 = Bits32 (opcode, 10, 6);
6035
6036 // index = TRUE; add = TRUE; wback = FALSE;
6037 index = true;
6038 add = true;
6039 wback= false;
6040
6041 break;
6042
6043 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006044 // if Rt == '1111' then SEE PLD;
6045 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006046 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6047 t = Bits32 (opcode, 15, 12);
6048 n = Bits32 (opcode, 19, 16);
6049 imm32 = Bits32 (opcode, 11, 0);
6050
6051 // index = TRUE; add = TRUE; wback = FALSE;
6052 index = true;
6053 add = true;
6054 wback = false;
6055
6056 // if t == 13 then UNPREDICTABLE;
6057 if (t == 13)
6058 return false;
6059
6060 break;
6061
6062 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006063 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6064 // if Rn == '1111' then SEE LDRB (literal);
6065 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6066 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006067 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6068 return false;
6069
6070 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6071 t = Bits32 (opcode, 15, 12);
6072 n = Bits32 (opcode, 19, 16);
6073 imm32 = Bits32 (opcode, 7, 0);
6074
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006075 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006076 index = BitIsSet (opcode, 10);
6077 add = BitIsSet (opcode, 9);
6078 wback = BitIsSet (opcode, 8);
6079
6080 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6081 if (BadReg (t) || (wback && (n == t)))
6082 return false;
6083
6084 break;
6085
6086 default:
6087 return false;
6088 }
6089
6090 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6091 if (!success)
6092 return false;
6093
6094 addr_t address;
6095 addr_t offset_addr;
6096
6097 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6098 if (add)
6099 offset_addr = Rn + imm32;
6100 else
6101 offset_addr = Rn - imm32;
6102
6103 // address = if index then offset_addr else R[n];
6104 if (index)
6105 address = offset_addr;
6106 else
6107 address = Rn;
6108
6109 // R[t] = ZeroExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006110 RegisterInfo base_reg;
6111 RegisterInfo data_reg;
6112 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6113 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice21b604b2011-02-18 21:06:04 +00006114
6115 EmulateInstruction::Context context;
6116 context.type = eContextRegisterLoad;
6117 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6118
6119 uint64_t data = MemURead (context, address, 1, 0, &success);
6120 if (!success)
6121 return false;
6122
6123 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6124 return false;
6125
6126 // if wback then R[n] = offset_addr;
6127 if (wback)
6128 {
6129 context.type = eContextAdjustBaseRegister;
6130 context.SetAddress (offset_addr);
6131 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6132 return false;
6133 }
6134 }
6135 return true;
6136}
Caroline Ticef55261f2011-02-18 22:24:22 +00006137
6138// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6139// zero-extends it to form a 32-bit word and writes it to a register.
6140bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006141EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006142{
6143#if 0
6144 if ConditionPassed() then
6145 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6146 base = Align(PC,4);
6147 address = if add then (base + imm32) else (base - imm32);
6148 R[t] = ZeroExtend(MemU[address,1], 32);
6149#endif
6150
6151 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006152
Greg Clayton7bc39082011-03-24 23:53:38 +00006153 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006154 {
6155 uint32_t t;
6156 uint32_t imm32;
6157 bool add;
6158 switch (encoding)
6159 {
6160 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006161 // if Rt == '1111' then SEE PLD;
6162 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006163 t = Bits32 (opcode, 15, 12);
6164 imm32 = Bits32 (opcode, 11, 0);
6165 add = BitIsSet (opcode, 23);
6166
6167 // if t == 13 then UNPREDICTABLE;
6168 if (t == 13)
6169 return false;
6170
6171 break;
6172
6173 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006174 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006175 t = Bits32 (opcode, 15, 12);
6176 imm32 = Bits32 (opcode, 11, 0);
6177 add = BitIsSet (opcode, 23);
6178
6179 // if t == 15 then UNPREDICTABLE;
6180 if (t == 15)
6181 return false;
6182 break;
6183
6184 default:
6185 return false;
6186 }
6187
6188 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006189 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006190 if (!success)
6191 return false;
6192
6193 uint32_t base = AlignPC (pc_val);
6194
6195 addr_t address;
6196 // address = if add then (base + imm32) else (base - imm32);
6197 if (add)
6198 address = base + imm32;
6199 else
6200 address = base - imm32;
6201
6202 // R[t] = ZeroExtend(MemU[address,1], 32);
6203 EmulateInstruction::Context context;
6204 context.type = eContextRelativeBranchImmediate;
6205 context.SetImmediate (address - base);
6206
6207 uint64_t data = MemURead (context, address, 1, 0, &success);
6208 if (!success)
6209 return false;
6210
6211 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6212 return false;
6213 }
6214 return true;
6215}
Caroline Tice30fec122011-02-18 23:52:21 +00006216
6217// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6218// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6219// optionally be shifted.
6220bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006221EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006222{
6223#if 0
6224 if ConditionPassed() then
6225 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6226 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6227 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6228 address = if index then offset_addr else R[n];
6229 R[t] = ZeroExtend(MemU[address,1],32);
6230 if wback then R[n] = offset_addr;
6231#endif
6232
6233 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006234
Greg Clayton7bc39082011-03-24 23:53:38 +00006235 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006236 {
6237 uint32_t t;
6238 uint32_t n;
6239 uint32_t m;
6240 bool index;
6241 bool add;
6242 bool wback;
6243 ARM_ShifterType shift_t;
6244 uint32_t shift_n;
6245
6246 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6247 switch (encoding)
6248 {
6249 case eEncodingT1:
6250 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6251 t = Bits32 (opcode, 2, 0);
6252 n = Bits32 (opcode, 5, 3);
6253 m = Bits32 (opcode, 8, 6);
6254
6255 // index = TRUE; add = TRUE; wback = FALSE;
6256 index = true;
6257 add = true;
6258 wback = false;
6259
6260 // (shift_t, shift_n) = (SRType_LSL, 0);
6261 shift_t = SRType_LSL;
6262 shift_n = 0;
6263 break;
6264
6265 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006266 // if Rt == '1111' then SEE PLD;
6267 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006268 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6269 t = Bits32 (opcode, 15, 12);
6270 n = Bits32 (opcode, 19, 16);
6271 m = Bits32 (opcode, 3, 0);
6272
6273 // index = TRUE; add = TRUE; wback = FALSE;
6274 index = true;
6275 add = true;
6276 wback = false;
6277
6278 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6279 shift_t = SRType_LSL;
6280 shift_n = Bits32 (opcode, 5, 4);
6281
6282 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6283 if ((t == 13) || BadReg (m))
6284 return false;
6285 break;
6286
6287 case eEncodingA1:
6288 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006289 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006290 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6291 t = Bits32 (opcode, 15, 12);
6292 n = Bits32 (opcode, 19, 16);
6293 m = Bits32 (opcode, 3, 0);
6294
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006295 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006296 index = BitIsSet (opcode, 24);
6297 add = BitIsSet (opcode, 23);
6298 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6299
6300 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6301 uint32_t type = Bits32 (opcode, 6, 5);
6302 uint32_t imm5 = Bits32 (opcode, 11, 7);
6303 shift_n = DecodeImmShift (type, imm5, shift_t);
6304
6305 // if t == 15 || m == 15 then UNPREDICTABLE;
6306 if ((t == 15) || (m == 15))
6307 return false;
6308
6309 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6310 if (wback && ((n == 15) || (n == t)))
6311 return false;
6312 }
6313 break;
6314
6315 default:
6316 return false;
6317 }
6318
6319 addr_t offset_addr;
6320 addr_t address;
6321
6322 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6323 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6324 if (!success)
6325 return false;
6326
6327 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6328
6329 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6330 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6331 if (!success)
6332 return false;
6333
6334 if (add)
6335 offset_addr = Rn + offset;
6336 else
6337 offset_addr = Rn - offset;
6338
6339 // address = if index then offset_addr else R[n];
6340 if (index)
6341 address = offset_addr;
6342 else
6343 address = Rn;
6344
6345 // R[t] = ZeroExtend(MemU[address,1],32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006346 RegisterInfo base_reg;
6347 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice30fec122011-02-18 23:52:21 +00006348
6349 EmulateInstruction::Context context;
6350 context.type = eContextRegisterLoad;
6351 context.SetRegisterPlusOffset (base_reg, address - Rn);
6352
6353 uint64_t data = MemURead (context, address, 1, 0, &success);
6354 if (!success)
6355 return false;
6356
6357 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6358 return false;
6359
6360 // if wback then R[n] = offset_addr;
6361 if (wback)
6362 {
6363 context.type = eContextAdjustBaseRegister;
6364 context.SetAddress (offset_addr);
6365 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6366 return false;
6367 }
6368 }
6369 return true;
6370}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006371
6372// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6373// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6374// post-indexed, or pre-indexed addressing.
6375bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006376EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006377{
6378#if 0
6379 if ConditionPassed() then
6380 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6381 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6382 address = if index then offset_addr else R[n];
6383 data = MemU[address,2];
6384 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006385 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006386 R[t] = ZeroExtend(data, 32);
6387 else // Can only apply before ARMv7
6388 R[t] = bits(32) UNKNOWN;
6389#endif
6390
6391
6392 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006393
Greg Clayton7bc39082011-03-24 23:53:38 +00006394 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006395 {
6396 uint32_t t;
6397 uint32_t n;
6398 uint32_t imm32;
6399 bool index;
6400 bool add;
6401 bool wback;
6402
6403 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6404 switch (encoding)
6405 {
6406 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006407 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006408 t = Bits32 (opcode, 2, 0);
6409 n = Bits32 (opcode, 5, 3);
6410 imm32 = Bits32 (opcode, 10, 6) << 1;
6411
6412 // index = TRUE; add = TRUE; wback = FALSE;
6413 index = true;
6414 add = true;
6415 wback = false;
6416
6417 break;
6418
6419 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006420 // if Rt == '1111' then SEE "Unallocated memory hints";
6421 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006422 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6423 t = Bits32 (opcode, 15, 12);
6424 n = Bits32 (opcode, 19, 16);
6425 imm32 = Bits32 (opcode, 11, 0);
6426
6427 // index = TRUE; add = TRUE; wback = FALSE;
6428 index = true;
6429 add = true;
6430 wback = false;
6431
6432 // if t == 13 then UNPREDICTABLE;
6433 if (t == 13)
6434 return false;
6435 break;
6436
6437 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006438 // if Rn == '1111' then SEE LDRH (literal);
6439 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6440 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6441 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006442 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6443 return false;
6444
6445 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6446 t = Bits32 (opcode, 15, 12);
6447 n = Bits32 (opcode, 19, 16);
6448 imm32 = Bits32 (opcode, 7, 0);
6449
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006450 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006451 index = BitIsSet (opcode, 10);
6452 add = BitIsSet (opcode, 9);
6453 wback = BitIsSet (opcode, 8);
6454
6455 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6456 if (BadReg (t) || (wback && (n == t)))
6457 return false;
6458 break;
6459
6460 default:
6461 return false;
6462 }
6463
6464 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6465 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6466 if (!success)
6467 return false;
6468
6469 addr_t offset_addr;
6470 addr_t address;
6471
6472 if (add)
6473 offset_addr = Rn + imm32;
6474 else
6475 offset_addr = Rn - imm32;
6476
6477 // address = if index then offset_addr else R[n];
6478 if (index)
6479 address = offset_addr;
6480 else
6481 address = Rn;
6482
6483 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006484 RegisterInfo base_reg;
6485 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006486
6487 EmulateInstruction::Context context;
6488 context.type = eContextRegisterLoad;
6489 context.SetRegisterPlusOffset (base_reg, address - Rn);
6490
6491 uint64_t data = MemURead (context, address, 2, 0, &success);
6492 if (!success)
6493 return false;
6494
6495 // if wback then R[n] = offset_addr;
6496 if (wback)
6497 {
6498 context.type = eContextAdjustBaseRegister;
6499 context.SetAddress (offset_addr);
6500 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6501 return false;
6502 }
6503
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006504 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006505 if (UnalignedSupport () || BitIsClear (address, 0))
6506 {
6507 // R[t] = ZeroExtend(data, 32);
6508 context.type = eContextRegisterLoad;
6509 context.SetRegisterPlusOffset (base_reg, address - Rn);
6510 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6511 return false;
6512 }
6513 else // Can only apply before ARMv7
6514 {
6515 // R[t] = bits(32) UNKNOWN;
6516 WriteBits32Unknown (t);
6517 }
6518 }
6519 return true;
6520}
Caroline Ticefe479112011-02-18 18:52:37 +00006521
Caroline Tice952b5382011-02-28 23:15:24 +00006522// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6523// zero-extends it to form a 32-bit word, and writes it to a register.
6524bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006525EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006526{
6527#if 0
6528 if ConditionPassed() then
6529 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6530 base = Align(PC,4);
6531 address = if add then (base + imm32) else (base - imm32);
6532 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006533 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006534 R[t] = ZeroExtend(data, 32);
6535 else // Can only apply before ARMv7
6536 R[t] = bits(32) UNKNOWN;
6537#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006538
Caroline Tice952b5382011-02-28 23:15:24 +00006539 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006540
Greg Clayton7bc39082011-03-24 23:53:38 +00006541 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006542 {
6543 uint32_t t;
6544 uint32_t imm32;
6545 bool add;
6546
6547 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6548 switch (encoding)
6549 {
6550 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006551 // if Rt == '1111' then SEE "Unallocated memory hints";
6552 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006553 t = Bits32 (opcode, 15, 12);
6554 imm32 = Bits32 (opcode, 11, 0);
6555 add = BitIsSet (opcode, 23);
6556
6557 // if t == 13 then UNPREDICTABLE;
6558 if (t == 13)
6559 return false;
6560
6561 break;
6562
6563 case eEncodingA1:
6564 {
6565 uint32_t imm4H = Bits32 (opcode, 11, 8);
6566 uint32_t imm4L = Bits32 (opcode, 3, 0);
6567
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006568 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006569 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006570 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006571 add = BitIsSet (opcode, 23);
6572
6573 // if t == 15 then UNPREDICTABLE;
6574 if (t == 15)
6575 return false;
6576 break;
6577 }
6578
6579 default:
6580 return false;
6581 }
6582
6583 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006584 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006585 if (!success)
6586 return false;
6587
6588 addr_t base = AlignPC (pc_value);
6589 addr_t address;
6590
6591 // address = if add then (base + imm32) else (base - imm32);
6592 if (add)
6593 address = base + imm32;
6594 else
6595 address = base - imm32;
6596
6597 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006598 RegisterInfo base_reg;
6599 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice952b5382011-02-28 23:15:24 +00006600
6601 EmulateInstruction::Context context;
6602 context.type = eContextRegisterLoad;
6603 context.SetRegisterPlusOffset (base_reg, address - base);
6604
6605 uint64_t data = MemURead (context, address, 2, 0, &success);
6606 if (!success)
6607 return false;
6608
6609
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006610 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006611 if (UnalignedSupport () || BitIsClear (address, 0))
6612 {
6613 // R[t] = ZeroExtend(data, 32);
6614 context.type = eContextRegisterLoad;
6615 context.SetRegisterPlusOffset (base_reg, address - base);
6616 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6617 return false;
6618
6619 }
6620 else // Can only apply before ARMv7
6621 {
6622 // R[t] = bits(32) UNKNOWN;
6623 WriteBits32Unknown (t);
6624 }
6625 }
6626 return true;
6627}
6628
Caroline Tice0e6bc952011-03-01 18:00:42 +00006629// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6630// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6631// be shifted left by 0, 1, 2, or 3 bits.
6632bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006633EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006634{
6635#if 0
6636 if ConditionPassed() then
6637 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6638 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6639 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6640 address = if index then offset_addr else R[n];
6641 data = MemU[address,2];
6642 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006643 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006644 R[t] = ZeroExtend(data, 32);
6645 else // Can only apply before ARMv7
6646 R[t] = bits(32) UNKNOWN;
6647#endif
6648
6649 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006650
Greg Clayton7bc39082011-03-24 23:53:38 +00006651 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006652 {
6653 uint32_t t;
6654 uint32_t n;
6655 uint32_t m;
6656 bool index;
6657 bool add;
6658 bool wback;
6659 ARM_ShifterType shift_t;
6660 uint32_t shift_n;
6661
6662 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6663 switch (encoding)
6664 {
6665 case eEncodingT1:
6666 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6667 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6668 t = Bits32 (opcode, 2, 0);
6669 n = Bits32 (opcode, 5, 3);
6670 m = Bits32 (opcode, 8, 6);
6671
6672 // index = TRUE; add = TRUE; wback = FALSE;
6673 index = true;
6674 add = true;
6675 wback = false;
6676
6677 // (shift_t, shift_n) = (SRType_LSL, 0);
6678 shift_t = SRType_LSL;
6679 shift_n = 0;
6680
6681 break;
6682
6683 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006684 // if Rn == '1111' then SEE LDRH (literal);
6685 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006686 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6687 t = Bits32 (opcode, 15, 12);
6688 n = Bits32 (opcode, 19, 16);
6689 m = Bits32 (opcode, 3, 0);
6690
6691 // index = TRUE; add = TRUE; wback = FALSE;
6692 index = true;
6693 add = true;
6694 wback = false;
6695
6696 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6697 shift_t = SRType_LSL;
6698 shift_n = Bits32 (opcode, 5, 4);
6699
6700 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6701 if ((t == 13) || BadReg (m))
6702 return false;
6703 break;
6704
6705 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006706 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006707 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6708 t = Bits32 (opcode, 15, 12);
6709 n = Bits32 (opcode, 19, 16);
6710 m = Bits32 (opcode, 3, 0);
6711
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006712 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006713 index = BitIsSet (opcode, 24);
6714 add = BitIsSet (opcode, 23);
6715 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6716
6717 // (shift_t, shift_n) = (SRType_LSL, 0);
6718 shift_t = SRType_LSL;
6719 shift_n = 0;
6720
6721 // if t == 15 || m == 15 then UNPREDICTABLE;
6722 if ((t == 15) || (m == 15))
6723 return false;
6724
6725 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6726 if (wback && ((n == 15) || (n == t)))
6727 return false;
6728
6729 break;
6730
6731 default:
6732 return false;
6733 }
6734
6735 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6736
6737 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6738 if (!success)
6739 return false;
6740
6741 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6742
6743 addr_t offset_addr;
6744 addr_t address;
6745
6746 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6747 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6748 if (!success)
6749 return false;
6750
6751 if (add)
6752 offset_addr = Rn + offset;
6753 else
6754 offset_addr = Rn - offset;
6755
6756 // address = if index then offset_addr else R[n];
6757 if (index)
6758 address = offset_addr;
6759 else
6760 address = Rn;
6761
6762 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006763 RegisterInfo base_reg;
6764 RegisterInfo offset_reg;
6765 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6766 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice0e6bc952011-03-01 18:00:42 +00006767
6768 EmulateInstruction::Context context;
6769 context.type = eContextRegisterLoad;
6770 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6771 uint64_t data = MemURead (context, address, 2, 0, &success);
6772 if (!success)
6773 return false;
6774
6775 // if wback then R[n] = offset_addr;
6776 if (wback)
6777 {
6778 context.type = eContextAdjustBaseRegister;
6779 context.SetAddress (offset_addr);
6780 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6781 return false;
6782 }
6783
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006784 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006785 if (UnalignedSupport() || BitIsClear (address, 0))
6786 {
6787 // R[t] = ZeroExtend(data, 32);
6788 context.type = eContextRegisterLoad;
6789 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6790 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6791 return false;
6792 }
6793 else // Can only apply before ARMv7
6794 {
6795 // R[t] = bits(32) UNKNOWN;
6796 WriteBits32Unknown (t);
6797 }
6798 }
6799 return true;
6800}
6801
Caroline Ticea5e28af2011-03-01 21:53:03 +00006802// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6803// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6804// or pre-indexed addressing.
6805bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006806EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006807{
6808#if 0
6809 if ConditionPassed() then
6810 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6811 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6812 address = if index then offset_addr else R[n];
6813 R[t] = SignExtend(MemU[address,1], 32);
6814 if wback then R[n] = offset_addr;
6815#endif
6816
6817 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006818
Greg Clayton7bc39082011-03-24 23:53:38 +00006819 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006820 {
6821 uint32_t t;
6822 uint32_t n;
6823 uint32_t imm32;
6824 bool index;
6825 bool add;
6826 bool wback;
6827
6828 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6829 switch (encoding)
6830 {
6831 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006832 // if Rt == '1111' then SEE PLI;
6833 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006834 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6835 t = Bits32 (opcode, 15, 12);
6836 n = Bits32 (opcode, 19, 16);
6837 imm32 = Bits32 (opcode, 11, 0);
6838
6839 // index = TRUE; add = TRUE; wback = FALSE;
6840 index = true;
6841 add = true;
6842 wback = false;
6843
6844 // if t == 13 then UNPREDICTABLE;
6845 if (t == 13)
6846 return false;
6847
6848 break;
6849
6850 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006851 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6852 // if Rn == '1111' then SEE LDRSB (literal);
6853 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6854 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006855 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6856 return false;
6857
6858 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6859 t = Bits32 (opcode, 15, 12);
6860 n = Bits32 (opcode, 19, 16);
6861 imm32 = Bits32 (opcode, 7, 0);
6862
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006863 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006864 index = BitIsSet (opcode, 10);
6865 add = BitIsSet (opcode, 9);
6866 wback = BitIsSet (opcode, 8);
6867
6868 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006869 if (((t == 13) || ((t == 15)
6870 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6871 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006872 return false;
6873
6874 break;
6875
6876 case eEncodingA1:
6877 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006878 // if Rn == '1111' then SEE LDRSB (literal);
6879 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006880 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6881 t = Bits32 (opcode, 15, 12);
6882 n = Bits32 (opcode, 19, 16);
6883
6884 uint32_t imm4H = Bits32 (opcode, 11, 8);
6885 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006886 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006887
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006888 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006889 index = BitIsSet (opcode, 24);
6890 add = BitIsSet (opcode, 23);
6891 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6892
6893 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6894 if ((t == 15) || (wback && (n == t)))
6895 return false;
6896
6897 break;
6898 }
6899
6900 default:
6901 return false;
6902 }
6903
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006904 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006905 if (!success)
6906 return false;
6907
6908 addr_t offset_addr;
6909 addr_t address;
6910
6911 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6912 if (add)
6913 offset_addr = Rn + imm32;
6914 else
6915 offset_addr = Rn - imm32;
6916
6917 // address = if index then offset_addr else R[n];
6918 if (index)
6919 address = offset_addr;
6920 else
6921 address = Rn;
6922
6923 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006924 RegisterInfo base_reg;
6925 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006926
6927 EmulateInstruction::Context context;
6928 context.type = eContextRegisterLoad;
6929 context.SetRegisterPlusOffset (base_reg, address - Rn);
6930
6931 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6932 if (!success)
6933 return false;
6934
6935 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6936 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6937 return false;
6938
6939 // if wback then R[n] = offset_addr;
6940 if (wback)
6941 {
6942 context.type = eContextAdjustBaseRegister;
6943 context.SetAddress (offset_addr);
6944 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6945 return false;
6946 }
6947 }
6948
6949 return true;
6950}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006951
Caroline Tice5f593912011-03-01 22:25:17 +00006952// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6953// sign-extends it to form a 32-bit word, and writes tit to a register.
6954bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006955EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006956{
6957#if 0
6958 if ConditionPassed() then
6959 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6960 base = Align(PC,4);
6961 address = if add then (base + imm32) else (base - imm32);
6962 R[t] = SignExtend(MemU[address,1], 32);
6963#endif
6964
6965 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006966
Greg Clayton7bc39082011-03-24 23:53:38 +00006967 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006968 {
6969 uint32_t t;
6970 uint32_t imm32;
6971 bool add;
6972
6973 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6974 switch (encoding)
6975 {
6976 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006977 // if Rt == '1111' then SEE PLI;
6978 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006979 t = Bits32 (opcode, 15, 12);
6980 imm32 = Bits32 (opcode, 11, 0);
6981 add = BitIsSet (opcode, 23);
6982
6983 // if t == 13 then UNPREDICTABLE;
6984 if (t == 13)
6985 return false;
6986
6987 break;
6988
6989 case eEncodingA1:
6990 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006991 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006992 t = Bits32 (opcode, 15, 12);
6993 uint32_t imm4H = Bits32 (opcode, 11, 8);
6994 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006995 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006996 add = BitIsSet (opcode, 23);
6997
6998 // if t == 15 then UNPREDICTABLE;
6999 if (t == 15)
7000 return false;
7001
7002 break;
7003 }
7004
7005 default:
7006 return false;
7007 }
7008
7009 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007010 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007011 if (!success)
7012 return false;
7013 uint64_t base = AlignPC (pc_value);
7014
7015 // address = if add then (base + imm32) else (base - imm32);
7016 addr_t address;
7017 if (add)
7018 address = base + imm32;
7019 else
7020 address = base - imm32;
7021
7022 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007023 RegisterInfo base_reg;
7024 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice5f593912011-03-01 22:25:17 +00007025
7026 EmulateInstruction::Context context;
7027 context.type = eContextRegisterLoad;
7028 context.SetRegisterPlusOffset (base_reg, address - base);
7029
7030 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7031 if (!success)
7032 return false;
7033
7034 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7035 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7036 return false;
7037 }
7038 return true;
7039}
7040
Caroline Tice672f3112011-03-01 23:55:59 +00007041// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7042// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7043// shifted left by 0, 1, 2, or 3 bits.
7044bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007045EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007046{
7047#if 0
7048 if ConditionPassed() then
7049 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7050 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7051 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7052 address = if index then offset_addr else R[n];
7053 R[t] = SignExtend(MemU[address,1], 32);
7054 if wback then R[n] = offset_addr;
7055#endif
7056
7057 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007058
Greg Clayton7bc39082011-03-24 23:53:38 +00007059 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007060 {
7061 uint32_t t;
7062 uint32_t n;
7063 uint32_t m;
7064 bool index;
7065 bool add;
7066 bool wback;
7067 ARM_ShifterType shift_t;
7068 uint32_t shift_n;
7069
7070 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7071 switch (encoding)
7072 {
7073 case eEncodingT1:
7074 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7075 t = Bits32 (opcode, 2, 0);
7076 n = Bits32 (opcode, 5, 3);
7077 m = Bits32 (opcode, 8, 6);
7078
7079 // index = TRUE; add = TRUE; wback = FALSE;
7080 index = true;
7081 add = true;
7082 wback = false;
7083
7084 // (shift_t, shift_n) = (SRType_LSL, 0);
7085 shift_t = SRType_LSL;
7086 shift_n = 0;
7087
7088 break;
7089
7090 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007091 // if Rt == '1111' then SEE PLI;
7092 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007093 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7094 t = Bits32 (opcode, 15, 12);
7095 n = Bits32 (opcode, 19, 16);
7096 m = Bits32 (opcode, 3, 0);
7097
7098 // index = TRUE; add = TRUE; wback = FALSE;
7099 index = true;
7100 add = true;
7101 wback = false;
7102
7103 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7104 shift_t = SRType_LSL;
7105 shift_n = Bits32 (opcode, 5, 4);
7106
7107 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7108 if ((t == 13) || BadReg (m))
7109 return false;
7110 break;
7111
7112 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007113 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007114 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7115 t = Bits32 (opcode, 15, 12);
7116 n = Bits32 (opcode, 19, 16);
7117 m = Bits32 (opcode, 3, 0);
7118
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007119 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007120 index = BitIsSet (opcode, 24);
7121 add = BitIsSet (opcode, 23);
7122 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7123
7124 // (shift_t, shift_n) = (SRType_LSL, 0);
7125 shift_t = SRType_LSL;
7126 shift_n = 0;
7127
7128 // if t == 15 || m == 15 then UNPREDICTABLE;
7129 if ((t == 15) || (m == 15))
7130 return false;
7131
7132 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7133 if (wback && ((n == 15) || (n == t)))
7134 return false;
7135 break;
7136
7137 default:
7138 return false;
7139 }
7140
7141 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7142 if (!success)
7143 return false;
7144
7145 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7146 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7147
7148 addr_t offset_addr;
7149 addr_t address;
7150
7151 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7152 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7153 if (!success)
7154 return false;
7155
7156 if (add)
7157 offset_addr = Rn + offset;
7158 else
7159 offset_addr = Rn - offset;
7160
7161 // address = if index then offset_addr else R[n];
7162 if (index)
7163 address = offset_addr;
7164 else
7165 address = Rn;
7166
7167 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007168 RegisterInfo base_reg;
7169 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7170 RegisterInfo offset_reg;
7171 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice672f3112011-03-01 23:55:59 +00007172
7173 EmulateInstruction::Context context;
7174 context.type = eContextRegisterLoad;
7175 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7176
7177 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7178 if (!success)
7179 return false;
7180
7181 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7182 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7183 return false;
7184
7185 // if wback then R[n] = offset_addr;
7186 if (wback)
7187 {
7188 context.type = eContextAdjustBaseRegister;
7189 context.SetAddress (offset_addr);
7190 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7191 return false;
7192 }
7193 }
7194 return true;
7195}
7196
Caroline Tice78fb5632011-03-02 00:39:42 +00007197// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7198// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7199// pre-indexed addressing.
7200bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007201EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007202{
7203#if 0
7204 if ConditionPassed() then
7205 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7206 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7207 address = if index then offset_addr else R[n];
7208 data = MemU[address,2];
7209 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007210 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007211 R[t] = SignExtend(data, 32);
7212 else // Can only apply before ARMv7
7213 R[t] = bits(32) UNKNOWN;
7214#endif
7215
7216 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007217
Greg Clayton7bc39082011-03-24 23:53:38 +00007218 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007219 {
7220 uint32_t t;
7221 uint32_t n;
7222 uint32_t imm32;
7223 bool index;
7224 bool add;
7225 bool wback;
7226
7227 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7228 switch (encoding)
7229 {
7230 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007231 // if Rn == '1111' then SEE LDRSH (literal);
7232 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007233 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7234 t = Bits32 (opcode, 15, 12);
7235 n = Bits32 (opcode, 19, 16);
7236 imm32 = Bits32 (opcode, 11, 0);
7237
7238 // index = TRUE; add = TRUE; wback = FALSE;
7239 index = true;
7240 add = true;
7241 wback = false;
7242
7243 // if t == 13 then UNPREDICTABLE;
7244 if (t == 13)
7245 return false;
7246
7247 break;
7248
7249 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007250 // if Rn == '1111' then SEE LDRSH (literal);
7251 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7252 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7253 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007254 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7255 return false;
7256
7257 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7258 t = Bits32 (opcode, 15, 12);
7259 n = Bits32 (opcode, 19, 16);
7260 imm32 = Bits32 (opcode, 7, 0);
7261
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007262 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007263 index = BitIsSet (opcode, 10);
7264 add = BitIsSet (opcode, 9);
7265 wback = BitIsSet (opcode, 8);
7266
7267 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7268 if (BadReg (t) || (wback && (n == t)))
7269 return false;
7270
7271 break;
7272
7273 case eEncodingA1:
7274 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007275 // if Rn == '1111' then SEE LDRSH (literal);
7276 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007277 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7278 t = Bits32 (opcode, 15, 12);
7279 n = Bits32 (opcode, 19, 16);
7280 uint32_t imm4H = Bits32 (opcode, 11,8);
7281 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007282 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007283
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007284 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007285 index = BitIsSet (opcode, 24);
7286 add = BitIsSet (opcode, 23);
7287 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7288
7289 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7290 if ((t == 15) || (wback && (n == t)))
7291 return false;
7292
7293 break;
7294 }
7295
7296 default:
7297 return false;
7298 }
7299
7300 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7301 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7302 if (!success)
7303 return false;
7304
7305 addr_t offset_addr;
7306 if (add)
7307 offset_addr = Rn + imm32;
7308 else
7309 offset_addr = Rn - imm32;
7310
7311 // address = if index then offset_addr else R[n];
7312 addr_t address;
7313 if (index)
7314 address = offset_addr;
7315 else
7316 address = Rn;
7317
7318 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007319 RegisterInfo base_reg;
7320 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice78fb5632011-03-02 00:39:42 +00007321
7322 EmulateInstruction::Context context;
7323 context.type = eContextRegisterLoad;
7324 context.SetRegisterPlusOffset (base_reg, address - Rn);
7325
7326 uint64_t data = MemURead (context, address, 2, 0, &success);
7327 if (!success)
7328 return false;
7329
7330 // if wback then R[n] = offset_addr;
7331 if (wback)
7332 {
7333 context.type = eContextAdjustBaseRegister;
7334 context.SetAddress (offset_addr);
7335 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7336 return false;
7337 }
7338
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007339 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007340 if (UnalignedSupport() || BitIsClear (address, 0))
7341 {
7342 // R[t] = SignExtend(data, 32);
7343 int64_t signed_data = llvm::SignExtend64<16>(data);
7344 context.type = eContextRegisterLoad;
7345 context.SetRegisterPlusOffset (base_reg, address - Rn);
7346 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7347 return false;
7348 }
7349 else // Can only apply before ARMv7
7350 {
7351 // R[t] = bits(32) UNKNOWN;
7352 WriteBits32Unknown (t);
7353 }
7354 }
7355 return true;
7356}
7357
Caroline Ticed2fac092011-03-02 19:45:34 +00007358// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7359// sign-extends it to from a 32-bit word, and writes it to a register.
7360bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007361EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007362{
7363#if 0
7364 if ConditionPassed() then
7365 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7366 base = Align(PC,4);
7367 address = if add then (base + imm32) else (base - imm32);
7368 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007369 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007370 R[t] = SignExtend(data, 32);
7371 else // Can only apply before ARMv7
7372 R[t] = bits(32) UNKNOWN;
7373#endif
7374
7375 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007376
Greg Clayton7bc39082011-03-24 23:53:38 +00007377 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007378 {
7379 uint32_t t;
7380 uint32_t imm32;
7381 bool add;
7382
7383 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7384 switch (encoding)
7385 {
7386 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007387 // if Rt == '1111' then SEE "Unallocated memory hints";
7388 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007389 t = Bits32 (opcode, 15, 12);
7390 imm32 = Bits32 (opcode, 11, 0);
7391 add = BitIsSet (opcode, 23);
7392
7393 // if t == 13 then UNPREDICTABLE;
7394 if (t == 13)
7395 return false;
7396
7397 break;
7398
7399 case eEncodingA1:
7400 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007401 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007402 t = Bits32 (opcode, 15, 12);
7403 uint32_t imm4H = Bits32 (opcode, 11, 8);
7404 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007405 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007406 add = BitIsSet (opcode, 23);
7407
7408 // if t == 15 then UNPREDICTABLE;
7409 if (t == 15)
7410 return false;
7411
7412 break;
7413 }
7414 default:
7415 return false;
7416 }
7417
7418 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007419 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007420 if (!success)
7421 return false;
7422
7423 uint64_t base = AlignPC (pc_value);
7424
7425 addr_t address;
7426 // address = if add then (base + imm32) else (base - imm32);
7427 if (add)
7428 address = base + imm32;
7429 else
7430 address = base - imm32;
7431
7432 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007433 RegisterInfo base_reg;
7434 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Ticed2fac092011-03-02 19:45:34 +00007435
7436 EmulateInstruction::Context context;
7437 context.type = eContextRegisterLoad;
7438 context.SetRegisterPlusOffset (base_reg, imm32);
7439
7440 uint64_t data = MemURead (context, address, 2, 0, &success);
7441 if (!success)
7442 return false;
7443
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007444 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007445 if (UnalignedSupport() || BitIsClear (address, 0))
7446 {
7447 // R[t] = SignExtend(data, 32);
7448 int64_t signed_data = llvm::SignExtend64<16>(data);
7449 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7450 return false;
7451 }
7452 else // Can only apply before ARMv7
7453 {
7454 // R[t] = bits(32) UNKNOWN;
7455 WriteBits32Unknown (t);
7456 }
7457 }
7458 return true;
7459}
7460
Caroline Tice291a3e92011-03-02 21:13:44 +00007461// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7462// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7463// shifted left by 0, 1, 2, or 3 bits.
7464bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007465EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007466{
7467#if 0
7468 if ConditionPassed() then
7469 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7470 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7471 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7472 address = if index then offset_addr else R[n];
7473 data = MemU[address,2];
7474 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007475 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007476 R[t] = SignExtend(data, 32);
7477 else // Can only apply before ARMv7
7478 R[t] = bits(32) UNKNOWN;
7479#endif
7480
7481 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007482
Greg Clayton7bc39082011-03-24 23:53:38 +00007483 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007484 {
7485 uint32_t t;
7486 uint32_t n;
7487 uint32_t m;
7488 bool index;
7489 bool add;
7490 bool wback;
7491 ARM_ShifterType shift_t;
7492 uint32_t shift_n;
7493
7494 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7495 switch (encoding)
7496 {
7497 case eEncodingT1:
7498 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7499 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7500 t = Bits32 (opcode, 2, 0);
7501 n = Bits32 (opcode, 5, 3);
7502 m = Bits32 (opcode, 8, 6);
7503
7504 // index = TRUE; add = TRUE; wback = FALSE;
7505 index = true;
7506 add = true;
7507 wback = false;
7508
7509 // (shift_t, shift_n) = (SRType_LSL, 0);
7510 shift_t = SRType_LSL;
7511 shift_n = 0;
7512
7513 break;
7514
7515 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007516 // if Rn == '1111' then SEE LDRSH (literal);
7517 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007518 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7519 t = Bits32 (opcode, 15, 12);
7520 n = Bits32 (opcode, 19, 16);
7521 m = Bits32 (opcode, 3, 0);
7522
7523 // index = TRUE; add = TRUE; wback = FALSE;
7524 index = true;
7525 add = true;
7526 wback = false;
7527
7528 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7529 shift_t = SRType_LSL;
7530 shift_n = Bits32 (opcode, 5, 4);
7531
7532 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7533 if ((t == 13) || BadReg (m))
7534 return false;
7535
7536 break;
7537
7538 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007539 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007540 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7541 t = Bits32 (opcode, 15, 12);
7542 n = Bits32 (opcode, 19, 16);
7543 m = Bits32 (opcode, 3, 0);
7544
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007545 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007546 index = BitIsSet (opcode, 24);
7547 add = BitIsSet (opcode, 23);
7548 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7549
7550 // (shift_t, shift_n) = (SRType_LSL, 0);
7551 shift_t = SRType_LSL;
7552 shift_n = 0;
7553
7554 // if t == 15 || m == 15 then UNPREDICTABLE;
7555 if ((t == 15) || (m == 15))
7556 return false;
7557
7558 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7559 if (wback && ((n == 15) || (n == t)))
7560 return false;
7561
7562 break;
7563
7564 default:
7565 break;
7566 }
7567
7568 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7569 if (!success)
7570 return false;
7571
7572 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7573 if (!success)
7574 return false;
7575
7576 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7577 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7578
7579 addr_t offset_addr;
7580 addr_t address;
7581
7582 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7583 if (add)
7584 offset_addr = Rn + offset;
7585 else
7586 offset_addr = Rn - offset;
7587
7588 // address = if index then offset_addr else R[n];
7589 if (index)
7590 address = offset_addr;
7591 else
7592 address = Rn;
7593
7594 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007595 RegisterInfo base_reg;
7596 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007597
Greg Claytonc07d4512011-04-26 23:48:45 +00007598 RegisterInfo offset_reg;
7599 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007600
7601 EmulateInstruction::Context context;
7602 context.type = eContextRegisterLoad;
7603 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7604
7605 uint64_t data = MemURead (context, address, 2, 0, &success);
7606 if (!success)
7607 return false;
7608
7609 // if wback then R[n] = offset_addr;
7610 if (wback)
7611 {
7612 context.type = eContextAdjustBaseRegister;
7613 context.SetAddress (offset_addr);
7614 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7615 return false;
7616 }
7617
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007618 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007619 if (UnalignedSupport() || BitIsClear (address, 0))
7620 {
7621 // R[t] = SignExtend(data, 32);
7622 context.type = eContextRegisterLoad;
7623 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7624
7625 int64_t signed_data = llvm::SignExtend64<16>(data);
7626 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7627 return false;
7628 }
7629 else // Can only apply before ARMv7
7630 {
7631 // R[t] = bits(32) UNKNOWN;
7632 WriteBits32Unknown (t);
7633 }
7634 }
7635 return true;
7636}
Caroline Tice6bf65162011-03-03 17:42:58 +00007637
7638// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7639// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7640bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007641EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007642{
7643#if 0
7644 if ConditionPassed() then
7645 EncodingSpecificOperations();
7646 rotated = ROR(R[m], rotation);
7647 R[d] = SignExtend(rotated<7:0>, 32);
7648#endif
7649
7650 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007651
Greg Clayton7bc39082011-03-24 23:53:38 +00007652 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007653 {
7654 uint32_t d;
7655 uint32_t m;
7656 uint32_t rotation;
7657
7658 // EncodingSpecificOperations();
7659 switch (encoding)
7660 {
7661 case eEncodingT1:
7662 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7663 d = Bits32 (opcode, 2, 0);
7664 m = Bits32 (opcode, 5, 3);
7665 rotation = 0;
7666
7667 break;
7668
7669 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007670 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007671 d = Bits32 (opcode, 11, 8);
7672 m = Bits32 (opcode, 3, 0);
7673 rotation = Bits32 (opcode, 5, 4) << 3;
7674
7675 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7676 if (BadReg (d) || BadReg (m))
7677 return false;
7678
7679 break;
7680
7681 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007682 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007683 d = Bits32 (opcode, 15, 12);
7684 m = Bits32 (opcode, 3, 0);
7685 rotation = Bits32 (opcode, 11, 10) << 3;
7686
7687 // if d == 15 || m == 15 then UNPREDICTABLE;
7688 if ((d == 15) || (m == 15))
7689 return false;
7690
7691 break;
7692
7693 default:
7694 return false;
7695 }
7696
Caroline Tice868198b2011-03-03 18:04:49 +00007697 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7698 if (!success)
7699 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007700
7701 // rotated = ROR(R[m], rotation);
7702 uint64_t rotated = ROR (Rm, rotation);
7703
7704 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007705 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007706
Greg Claytonc07d4512011-04-26 23:48:45 +00007707 RegisterInfo source_reg;
7708 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice6bf65162011-03-03 17:42:58 +00007709
7710 EmulateInstruction::Context context;
7711 context.type = eContextRegisterLoad;
7712 context.SetRegister (source_reg);
7713
Caroline Tice8ce96d92011-03-03 18:27:17 +00007714 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007715 return false;
7716 }
7717 return true;
7718}
Caroline Tice291a3e92011-03-02 21:13:44 +00007719
Caroline Tice868198b2011-03-03 18:04:49 +00007720// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7721// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7722bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007723EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007724{
7725#if 0
7726 if ConditionPassed() then
7727 EncodingSpecificOperations();
7728 rotated = ROR(R[m], rotation);
7729 R[d] = SignExtend(rotated<15:0>, 32);
7730#endif
7731
7732 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007733
Greg Clayton7bc39082011-03-24 23:53:38 +00007734 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007735 {
7736 uint32_t d;
7737 uint32_t m;
7738 uint32_t rotation;
7739
7740 // EncodingSpecificOperations();
7741 switch (encoding)
7742 {
7743 case eEncodingT1:
7744 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7745 d = Bits32 (opcode, 2, 0);
7746 m = Bits32 (opcode, 5, 3);
7747 rotation = 0;
7748
7749 break;
7750
7751 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007752 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007753 d = Bits32 (opcode, 11, 8);
7754 m = Bits32 (opcode, 3, 0);
7755 rotation = Bits32 (opcode, 5, 4) << 3;
7756
7757 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7758 if (BadReg (d) || BadReg (m))
7759 return false;
7760
7761 break;
7762
7763 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007764 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007765 d = Bits32 (opcode, 15, 12);
7766 m = Bits32 (opcode, 3, 0);
7767 rotation = Bits32 (opcode, 11, 10) << 3;
7768
7769 // if d == 15 || m == 15 then UNPREDICTABLE;
7770 if ((d == 15) || (m == 15))
7771 return false;
7772
7773 break;
7774
7775 default:
7776 return false;
7777 }
7778
7779 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7780 if (!success)
7781 return false;
7782
7783 // rotated = ROR(R[m], rotation);
7784 uint64_t rotated = ROR (Rm, rotation);
7785
7786 // R[d] = SignExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007787 RegisterInfo source_reg;
7788 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice868198b2011-03-03 18:04:49 +00007789
7790 EmulateInstruction::Context context;
7791 context.type = eContextRegisterLoad;
7792 context.SetRegister (source_reg);
7793
Caroline Tice8ce96d92011-03-03 18:27:17 +00007794 int64_t data = llvm::SignExtend64<16> (rotated);
7795 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007796 return false;
7797 }
7798
7799 return true;
7800}
7801
Caroline Tice8ce96d92011-03-03 18:27:17 +00007802// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7803// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7804bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007805EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007806{
7807#if 0
7808 if ConditionPassed() then
7809 EncodingSpecificOperations();
7810 rotated = ROR(R[m], rotation);
7811 R[d] = ZeroExtend(rotated<7:0>, 32);
7812#endif
7813
7814 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007815
Greg Clayton7bc39082011-03-24 23:53:38 +00007816 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007817 {
7818 uint32_t d;
7819 uint32_t m;
7820 uint32_t rotation;
7821
7822 // EncodingSpecificOperations();
7823 switch (encoding)
7824 {
7825 case eEncodingT1:
7826 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7827 d = Bits32 (opcode, 2, 0);
7828 m = Bits32 (opcode, 5, 3);
7829 rotation = 0;
7830
7831 break;
7832
7833 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007834 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007835 d = Bits32 (opcode, 11, 8);
7836 m = Bits32 (opcode, 3, 0);
7837 rotation = Bits32 (opcode, 5, 4) << 3;
7838
7839 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7840 if (BadReg (d) || BadReg (m))
7841 return false;
7842
7843 break;
7844
7845 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007846 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007847 d = Bits32 (opcode, 15, 12);
7848 m = Bits32 (opcode, 3, 0);
7849 rotation = Bits32 (opcode, 11, 10) << 3;
7850
7851 // if d == 15 || m == 15 then UNPREDICTABLE;
7852 if ((d == 15) || (m == 15))
7853 return false;
7854
7855 break;
7856
7857 default:
7858 return false;
7859 }
7860
7861 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7862 if (!success)
7863 return false;
7864
7865 // rotated = ROR(R[m], rotation);
7866 uint64_t rotated = ROR (Rm, rotation);
7867
7868 // R[d] = ZeroExtend(rotated<7:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007869 RegisterInfo source_reg;
7870 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007871
7872 EmulateInstruction::Context context;
7873 context.type = eContextRegisterLoad;
7874 context.SetRegister (source_reg);
7875
7876 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7877 return false;
7878 }
7879 return true;
7880}
7881
Caroline Tice11555f22011-03-03 18:48:58 +00007882// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7883// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7884bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007885EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007886{
7887#if 0
7888 if ConditionPassed() then
7889 EncodingSpecificOperations();
7890 rotated = ROR(R[m], rotation);
7891 R[d] = ZeroExtend(rotated<15:0>, 32);
7892#endif
7893
7894 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007895
Greg Clayton7bc39082011-03-24 23:53:38 +00007896 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007897 {
7898 uint32_t d;
7899 uint32_t m;
7900 uint32_t rotation;
7901
7902 switch (encoding)
7903 {
7904 case eEncodingT1:
7905 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7906 d = Bits32 (opcode, 2, 0);
7907 m = Bits32 (opcode, 5, 3);
7908 rotation = 0;
7909
7910 break;
7911
7912 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007913 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007914 d = Bits32 (opcode, 11, 8);
7915 m = Bits32 (opcode, 3, 0);
7916 rotation = Bits32 (opcode, 5, 4) << 3;
7917
7918 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7919 if (BadReg (d) || BadReg (m))
7920 return false;
7921
7922 break;
7923
7924 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007925 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007926 d = Bits32 (opcode, 15, 12);
7927 m = Bits32 (opcode, 3, 0);
7928 rotation = Bits32 (opcode, 11, 10) << 3;
7929
7930 // if d == 15 || m == 15 then UNPREDICTABLE;
7931 if ((d == 15) || (m == 15))
7932 return false;
7933
7934 break;
7935
7936 default:
7937 return false;
7938 }
7939
7940 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7941 if (!success)
7942 return false;
7943
7944 // rotated = ROR(R[m], rotation);
7945 uint64_t rotated = ROR (Rm, rotation);
7946
7947 // R[d] = ZeroExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007948 RegisterInfo source_reg;
7949 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice11555f22011-03-03 18:48:58 +00007950
7951 EmulateInstruction::Context context;
7952 context.type = eContextRegisterLoad;
7953 context.SetRegister (source_reg);
7954
7955 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7956 return false;
7957 }
7958 return true;
7959}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007960
7961// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7962// word respectively.
7963bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007964EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007965{
7966#if 0
7967 if ConditionPassed() then
7968 EncodingSpecificOperations();
7969 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7970 UNPREDICTABLE;
7971 else
7972 address = if increment then R[n] else R[n]-8;
7973 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007974 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007975 BranchWritePC(MemA[address,4]);
7976 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7977#endif
7978
7979 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007980
Greg Clayton7bc39082011-03-24 23:53:38 +00007981 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007982 {
7983 uint32_t n;
7984 bool wback;
7985 bool increment;
7986 bool wordhigher;
7987
7988 // EncodingSpecificOperations();
7989 switch (encoding)
7990 {
7991 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007992 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007993 n = Bits32 (opcode, 19, 16);
7994 wback = BitIsSet (opcode, 21);
7995 increment = false;
7996 wordhigher = false;
7997
7998 // if n == 15 then UNPREDICTABLE;
7999 if (n == 15)
8000 return false;
8001
8002 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8003 if (InITBlock() && !LastInITBlock())
8004 return false;
8005
8006 break;
8007
8008 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008009 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008010 n = Bits32 (opcode, 19, 16);
8011 wback = BitIsSet (opcode, 21);
8012 increment = true;
8013 wordhigher = false;
8014
8015 // if n == 15 then UNPREDICTABLE;
8016 if (n == 15)
8017 return false;
8018
8019 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8020 if (InITBlock() && !LastInITBlock())
8021 return false;
8022
8023 break;
8024
8025 case eEncodingA1:
8026 // n = UInt(Rn);
8027 n = Bits32 (opcode, 19, 16);
8028
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008029 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008030 wback = BitIsSet (opcode, 21);
8031 increment = BitIsSet (opcode, 23);
8032 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8033
8034 // if n == 15 then UNPREDICTABLE;
8035 if (n == 15)
8036 return false;
8037
8038 break;
8039
8040 default:
8041 return false;
8042 }
8043
8044 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8045 if (!CurrentModeIsPrivileged ())
8046 // UNPREDICTABLE;
8047 return false;
8048 else
8049 {
8050 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8051 if (!success)
8052 return false;
8053
8054 addr_t address;
8055 // address = if increment then R[n] else R[n]-8;
8056 if (increment)
8057 address = Rn;
8058 else
8059 address = Rn - 8;
8060
8061 // if wordhigher then address = address+4;
8062 if (wordhigher)
8063 address = address + 4;
8064
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008065 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Greg Claytonc07d4512011-04-26 23:48:45 +00008066 RegisterInfo base_reg;
8067 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008068
8069 EmulateInstruction::Context context;
8070 context.type = eContextReturnFromException;
8071 context.SetRegisterPlusOffset (base_reg, address - Rn);
8072
8073 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8074 if (!success)
8075 return false;
8076
8077 CPSRWriteByInstr (data, 15, true);
8078
8079 // BranchWritePC(MemA[address,4]);
8080 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8081 if (!success)
8082 return false;
8083
8084 BranchWritePC (context, data2);
8085
8086 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8087 if (wback)
8088 {
8089 context.type = eContextAdjustBaseRegister;
8090 if (increment)
8091 {
8092 context.SetOffset (8);
8093 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8094 return false;
8095 }
8096 else
8097 {
8098 context.SetOffset (-8);
8099 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8100 return false;
8101 }
8102 } // if wback
8103 }
8104 } // if ConditionPassed()
8105 return true;
8106}
Caroline Tice11555f22011-03-03 18:48:58 +00008107
Johnny Chen2115b412011-02-21 23:42:44 +00008108// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8109// and writes the result to the destination register. It can optionally update the condition flags based on
8110// the result.
8111bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008112EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008113{
8114#if 0
8115 // ARM pseudo code...
8116 if ConditionPassed() then
8117 EncodingSpecificOperations();
8118 result = R[n] EOR imm32;
8119 if d == 15 then // Can only occur for ARM encoding
8120 ALUWritePC(result); // setflags is always FALSE here
8121 else
8122 R[d] = result;
8123 if setflags then
8124 APSR.N = result<31>;
8125 APSR.Z = IsZeroBit(result);
8126 APSR.C = carry;
8127 // APSR.V unchanged
8128#endif
8129
8130 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008131
Greg Clayton7bc39082011-03-24 23:53:38 +00008132 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008133 {
8134 uint32_t Rd, Rn;
8135 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8136 bool setflags;
8137 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8138 switch (encoding)
8139 {
8140 case eEncodingT1:
8141 Rd = Bits32(opcode, 11, 8);
8142 Rn = Bits32(opcode, 19, 16);
8143 setflags = BitIsSet(opcode, 20);
8144 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8145 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8146 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008147 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008148 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8149 return false;
8150 break;
8151 case eEncodingA1:
8152 Rd = Bits32(opcode, 15, 12);
8153 Rn = Bits32(opcode, 19, 16);
8154 setflags = BitIsSet(opcode, 20);
8155 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008156
Johnny Chen2115b412011-02-21 23:42:44 +00008157 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008158 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008159 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008160 break;
8161 default:
8162 return false;
8163 }
8164
8165 // Read the first operand.
8166 uint32_t val1 = ReadCoreReg(Rn, &success);
8167 if (!success)
8168 return false;
8169
8170 uint32_t result = val1 ^ imm32;
8171
8172 EmulateInstruction::Context context;
8173 context.type = EmulateInstruction::eContextImmediate;
8174 context.SetNoArgs ();
8175
8176 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8177 return false;
8178 }
8179 return true;
8180}
8181
8182// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8183// optionally-shifted register value, and writes the result to the destination register.
8184// It can optionally update the condition flags based on the result.
8185bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008186EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008187{
8188#if 0
8189 // ARM pseudo code...
8190 if ConditionPassed() then
8191 EncodingSpecificOperations();
8192 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8193 result = R[n] EOR shifted;
8194 if d == 15 then // Can only occur for ARM encoding
8195 ALUWritePC(result); // setflags is always FALSE here
8196 else
8197 R[d] = result;
8198 if setflags then
8199 APSR.N = result<31>;
8200 APSR.Z = IsZeroBit(result);
8201 APSR.C = carry;
8202 // APSR.V unchanged
8203#endif
8204
8205 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008206
Greg Clayton7bc39082011-03-24 23:53:38 +00008207 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008208 {
8209 uint32_t Rd, Rn, Rm;
8210 ARM_ShifterType shift_t;
8211 uint32_t shift_n; // the shift applied to the value read from Rm
8212 bool setflags;
8213 uint32_t carry;
8214 switch (encoding)
8215 {
8216 case eEncodingT1:
8217 Rd = Rn = Bits32(opcode, 2, 0);
8218 Rm = Bits32(opcode, 5, 3);
8219 setflags = !InITBlock();
8220 shift_t = SRType_LSL;
8221 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008222 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008223 case eEncodingT2:
8224 Rd = Bits32(opcode, 11, 8);
8225 Rn = Bits32(opcode, 19, 16);
8226 Rm = Bits32(opcode, 3, 0);
8227 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008228 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8229 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008230 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008231 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008232 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8233 return false;
8234 break;
8235 case eEncodingA1:
8236 Rd = Bits32(opcode, 15, 12);
8237 Rn = Bits32(opcode, 19, 16);
8238 Rm = Bits32(opcode, 3, 0);
8239 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008240 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008241
Johnny Chen2115b412011-02-21 23:42:44 +00008242 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008243 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008244 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008245 break;
8246 default:
8247 return false;
8248 }
8249
8250 // Read the first operand.
8251 uint32_t val1 = ReadCoreReg(Rn, &success);
8252 if (!success)
8253 return false;
8254
8255 // Read the second operand.
8256 uint32_t val2 = ReadCoreReg(Rm, &success);
8257 if (!success)
8258 return false;
8259
8260 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8261 uint32_t result = val1 ^ shifted;
8262
8263 EmulateInstruction::Context context;
8264 context.type = EmulateInstruction::eContextImmediate;
8265 context.SetNoArgs ();
8266
8267 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8268 return false;
8269 }
8270 return true;
8271}
8272
Johnny Chen7c5234d2011-02-18 23:41:11 +00008273// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8274// writes the result to the destination register. It can optionally update the condition flags based
8275// on the result.
8276bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008277EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008278{
8279#if 0
8280 // ARM pseudo code...
8281 if ConditionPassed() then
8282 EncodingSpecificOperations();
8283 result = R[n] OR imm32;
8284 if d == 15 then // Can only occur for ARM encoding
8285 ALUWritePC(result); // setflags is always FALSE here
8286 else
8287 R[d] = result;
8288 if setflags then
8289 APSR.N = result<31>;
8290 APSR.Z = IsZeroBit(result);
8291 APSR.C = carry;
8292 // APSR.V unchanged
8293#endif
8294
8295 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008296
Greg Clayton7bc39082011-03-24 23:53:38 +00008297 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008298 {
8299 uint32_t Rd, Rn;
8300 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8301 bool setflags;
8302 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8303 switch (encoding)
8304 {
8305 case eEncodingT1:
8306 Rd = Bits32(opcode, 11, 8);
8307 Rn = Bits32(opcode, 19, 16);
8308 setflags = BitIsSet(opcode, 20);
8309 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008310 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008311 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008312 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008313 if (BadReg(Rd) || Rn == 13)
8314 return false;
8315 break;
8316 case eEncodingA1:
8317 Rd = Bits32(opcode, 15, 12);
8318 Rn = Bits32(opcode, 19, 16);
8319 setflags = BitIsSet(opcode, 20);
8320 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008321
Johnny Chen7c5234d2011-02-18 23:41:11 +00008322 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008323 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008324 break;
8325 default:
8326 return false;
8327 }
8328
8329 // Read the first operand.
8330 uint32_t val1 = ReadCoreReg(Rn, &success);
8331 if (!success)
8332 return false;
8333
8334 uint32_t result = val1 | imm32;
8335
8336 EmulateInstruction::Context context;
8337 context.type = EmulateInstruction::eContextImmediate;
8338 context.SetNoArgs ();
8339
8340 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8341 return false;
8342 }
8343 return true;
8344}
8345
8346// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8347// value, and writes the result to the destination register. It can optionally update the condition flags based
8348// on the result.
8349bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008350EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008351{
8352#if 0
8353 // ARM pseudo code...
8354 if ConditionPassed() then
8355 EncodingSpecificOperations();
8356 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8357 result = R[n] OR shifted;
8358 if d == 15 then // Can only occur for ARM encoding
8359 ALUWritePC(result); // setflags is always FALSE here
8360 else
8361 R[d] = result;
8362 if setflags then
8363 APSR.N = result<31>;
8364 APSR.Z = IsZeroBit(result);
8365 APSR.C = carry;
8366 // APSR.V unchanged
8367#endif
8368
8369 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008370
Greg Clayton7bc39082011-03-24 23:53:38 +00008371 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008372 {
8373 uint32_t Rd, Rn, Rm;
8374 ARM_ShifterType shift_t;
8375 uint32_t shift_n; // the shift applied to the value read from Rm
8376 bool setflags;
8377 uint32_t carry;
8378 switch (encoding)
8379 {
8380 case eEncodingT1:
8381 Rd = Rn = Bits32(opcode, 2, 0);
8382 Rm = Bits32(opcode, 5, 3);
8383 setflags = !InITBlock();
8384 shift_t = SRType_LSL;
8385 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008386 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008387 case eEncodingT2:
8388 Rd = Bits32(opcode, 11, 8);
8389 Rn = Bits32(opcode, 19, 16);
8390 Rm = Bits32(opcode, 3, 0);
8391 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008392 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8393 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008394 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008395 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008396 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8397 return false;
8398 break;
8399 case eEncodingA1:
8400 Rd = Bits32(opcode, 15, 12);
8401 Rn = Bits32(opcode, 19, 16);
8402 Rm = Bits32(opcode, 3, 0);
8403 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008404 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008405
Johnny Chen7c5234d2011-02-18 23:41:11 +00008406 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008407 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008408 break;
8409 default:
8410 return false;
8411 }
8412
8413 // Read the first operand.
8414 uint32_t val1 = ReadCoreReg(Rn, &success);
8415 if (!success)
8416 return false;
8417
8418 // Read the second operand.
8419 uint32_t val2 = ReadCoreReg(Rm, &success);
8420 if (!success)
8421 return false;
8422
8423 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008424 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008425
8426 EmulateInstruction::Context context;
8427 context.type = EmulateInstruction::eContextImmediate;
8428 context.SetNoArgs ();
8429
8430 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8431 return false;
8432 }
8433 return true;
8434}
8435
Johnny Chened32e7c2011-02-22 23:42:58 +00008436// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8437// the destination register. It can optionally update the condition flags based on the result.
8438bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008439EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008440{
8441#if 0
8442 // ARM pseudo code...
8443 if ConditionPassed() then
8444 EncodingSpecificOperations();
8445 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8446 if d == 15 then // Can only occur for ARM encoding
8447 ALUWritePC(result); // setflags is always FALSE here
8448 else
8449 R[d] = result;
8450 if setflags then
8451 APSR.N = result<31>;
8452 APSR.Z = IsZeroBit(result);
8453 APSR.C = carry;
8454 APSR.V = overflow;
8455#endif
8456
8457 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008458
8459 uint32_t Rd; // the destination register
8460 uint32_t Rn; // the first operand
8461 bool setflags;
8462 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8463 switch (encoding) {
8464 case eEncodingT1:
8465 Rd = Bits32(opcode, 2, 0);
8466 Rn = Bits32(opcode, 5, 3);
8467 setflags = !InITBlock();
8468 imm32 = 0;
8469 break;
8470 case eEncodingT2:
8471 Rd = Bits32(opcode, 11, 8);
8472 Rn = Bits32(opcode, 19, 16);
8473 setflags = BitIsSet(opcode, 20);
8474 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8475 if (BadReg(Rd) || BadReg(Rn))
8476 return false;
8477 break;
8478 case eEncodingA1:
8479 Rd = Bits32(opcode, 15, 12);
8480 Rn = Bits32(opcode, 19, 16);
8481 setflags = BitIsSet(opcode, 20);
8482 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008483
Johnny Chened32e7c2011-02-22 23:42:58 +00008484 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008485 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008486 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008487 break;
8488 default:
8489 return false;
8490 }
8491 // Read the register value from the operand register Rn.
8492 uint32_t reg_val = ReadCoreReg(Rn, &success);
8493 if (!success)
8494 return false;
8495
8496 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8497
8498 EmulateInstruction::Context context;
8499 context.type = EmulateInstruction::eContextImmediate;
8500 context.SetNoArgs ();
8501
8502 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8503 return false;
8504
8505 return true;
8506}
8507
8508// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8509// result to the destination register. It can optionally update the condition flags based on the result.
8510bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008511EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008512{
8513#if 0
8514 // ARM pseudo code...
8515 if ConditionPassed() then
8516 EncodingSpecificOperations();
8517 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8518 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8519 if d == 15 then // Can only occur for ARM encoding
8520 ALUWritePC(result); // setflags is always FALSE here
8521 else
8522 R[d] = result;
8523 if setflags then
8524 APSR.N = result<31>;
8525 APSR.Z = IsZeroBit(result);
8526 APSR.C = carry;
8527 APSR.V = overflow;
8528#endif
8529
8530 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008531
8532 uint32_t Rd; // the destination register
8533 uint32_t Rn; // the first operand
8534 uint32_t Rm; // the second operand
8535 bool setflags;
8536 ARM_ShifterType shift_t;
8537 uint32_t shift_n; // the shift applied to the value read from Rm
8538 switch (encoding) {
8539 case eEncodingT1:
8540 Rd = Bits32(opcode, 11, 8);
8541 Rn = Bits32(opcode, 19, 16);
8542 Rm = Bits32(opcode, 3, 0);
8543 setflags = BitIsSet(opcode, 20);
8544 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8545 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8546 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8547 return false;
8548 break;
8549 case eEncodingA1:
8550 Rd = Bits32(opcode, 15, 12);
8551 Rn = Bits32(opcode, 19, 16);
8552 Rm = Bits32(opcode, 3, 0);
8553 setflags = BitIsSet(opcode, 20);
8554 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008555
Johnny Chened32e7c2011-02-22 23:42:58 +00008556 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008557 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008558 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008559 break;
8560 default:
8561 return false;
8562 }
8563 // Read the register value from register Rn.
8564 uint32_t val1 = ReadCoreReg(Rn, &success);
8565 if (!success)
8566 return false;
8567
8568 // Read the register value from register Rm.
8569 uint32_t val2 = ReadCoreReg(Rm, &success);
8570 if (!success)
8571 return false;
8572
8573 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8574 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8575
8576 EmulateInstruction::Context context;
8577 context.type = EmulateInstruction::eContextImmediate;
8578 context.SetNoArgs();
8579 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8580 return false;
8581
8582 return true;
8583}
8584
Johnny Chen90e607b2011-02-23 00:07:09 +00008585// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8586// an immediate value, and writes the result to the destination register. It can optionally update the condition
8587// flags based on the result.
8588bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008589EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008590{
8591#if 0
8592 // ARM pseudo code...
8593 if ConditionPassed() then
8594 EncodingSpecificOperations();
8595 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8596 if d == 15 then
8597 ALUWritePC(result); // setflags is always FALSE here
8598 else
8599 R[d] = result;
8600 if setflags then
8601 APSR.N = result<31>;
8602 APSR.Z = IsZeroBit(result);
8603 APSR.C = carry;
8604 APSR.V = overflow;
8605#endif
8606
8607 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008608
8609 uint32_t Rd; // the destination register
8610 uint32_t Rn; // the first operand
8611 bool setflags;
8612 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8613 switch (encoding) {
8614 case eEncodingA1:
8615 Rd = Bits32(opcode, 15, 12);
8616 Rn = Bits32(opcode, 19, 16);
8617 setflags = BitIsSet(opcode, 20);
8618 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008619
Johnny Chen90e607b2011-02-23 00:07:09 +00008620 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008621 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008622 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008623 break;
8624 default:
8625 return false;
8626 }
8627 // Read the register value from the operand register Rn.
8628 uint32_t reg_val = ReadCoreReg(Rn, &success);
8629 if (!success)
8630 return false;
8631
8632 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8633
8634 EmulateInstruction::Context context;
8635 context.type = EmulateInstruction::eContextImmediate;
8636 context.SetNoArgs ();
8637
8638 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8639 return false;
8640
8641 return true;
8642}
8643
8644// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8645// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8646// condition flags based on the result.
8647bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008648EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008649{
8650#if 0
8651 // ARM pseudo code...
8652 if ConditionPassed() then
8653 EncodingSpecificOperations();
8654 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8655 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8656 if d == 15 then
8657 ALUWritePC(result); // setflags is always FALSE here
8658 else
8659 R[d] = result;
8660 if setflags then
8661 APSR.N = result<31>;
8662 APSR.Z = IsZeroBit(result);
8663 APSR.C = carry;
8664 APSR.V = overflow;
8665#endif
8666
8667 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008668
8669 uint32_t Rd; // the destination register
8670 uint32_t Rn; // the first operand
8671 uint32_t Rm; // the second operand
8672 bool setflags;
8673 ARM_ShifterType shift_t;
8674 uint32_t shift_n; // the shift applied to the value read from Rm
8675 switch (encoding) {
8676 case eEncodingA1:
8677 Rd = Bits32(opcode, 15, 12);
8678 Rn = Bits32(opcode, 19, 16);
8679 Rm = Bits32(opcode, 3, 0);
8680 setflags = BitIsSet(opcode, 20);
8681 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008682
Johnny Chen90e607b2011-02-23 00:07:09 +00008683 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008684 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008685 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008686 break;
8687 default:
8688 return false;
8689 }
8690 // Read the register value from register Rn.
8691 uint32_t val1 = ReadCoreReg(Rn, &success);
8692 if (!success)
8693 return false;
8694
8695 // Read the register value from register Rm.
8696 uint32_t val2 = ReadCoreReg(Rm, &success);
8697 if (!success)
8698 return false;
8699
8700 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8701 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8702
8703 EmulateInstruction::Context context;
8704 context.type = EmulateInstruction::eContextImmediate;
8705 context.SetNoArgs();
8706 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8707 return false;
8708
8709 return true;
8710}
8711
Johnny Chen9b381772011-02-23 01:01:21 +00008712// Subtract with Carry (immediate) subtracts an immediate value and the value of
8713// NOT (Carry flag) from a register value, and writes the result to the destination register.
8714// It can optionally update the condition flags based on the result.
8715bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008716EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008717{
8718#if 0
8719 // ARM pseudo code...
8720 if ConditionPassed() then
8721 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008722 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008723 if d == 15 then // Can only occur for ARM encoding
8724 ALUWritePC(result); // setflags is always FALSE here
8725 else
8726 R[d] = result;
8727 if setflags then
8728 APSR.N = result<31>;
8729 APSR.Z = IsZeroBit(result);
8730 APSR.C = carry;
8731 APSR.V = overflow;
8732#endif
8733
8734 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008735
8736 uint32_t Rd; // the destination register
8737 uint32_t Rn; // the first operand
8738 bool setflags;
8739 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8740 switch (encoding) {
8741 case eEncodingT1:
8742 Rd = Bits32(opcode, 11, 8);
8743 Rn = Bits32(opcode, 19, 16);
8744 setflags = BitIsSet(opcode, 20);
8745 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8746 if (BadReg(Rd) || BadReg(Rn))
8747 return false;
8748 break;
8749 case eEncodingA1:
8750 Rd = Bits32(opcode, 15, 12);
8751 Rn = Bits32(opcode, 19, 16);
8752 setflags = BitIsSet(opcode, 20);
8753 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008754
Johnny Chen9b381772011-02-23 01:01:21 +00008755 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008756 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008757 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008758 break;
8759 default:
8760 return false;
8761 }
8762 // Read the register value from the operand register Rn.
8763 uint32_t reg_val = ReadCoreReg(Rn, &success);
8764 if (!success)
8765 return false;
8766
8767 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8768
8769 EmulateInstruction::Context context;
8770 context.type = EmulateInstruction::eContextImmediate;
8771 context.SetNoArgs ();
8772
8773 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8774 return false;
8775
8776 return true;
8777}
8778
8779// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8780// NOT (Carry flag) from a register value, and writes the result to the destination register.
8781// It can optionally update the condition flags based on the result.
8782bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008783EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008784{
8785#if 0
8786 // ARM pseudo code...
8787 if ConditionPassed() then
8788 EncodingSpecificOperations();
8789 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8790 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8791 if d == 15 then // Can only occur for ARM encoding
8792 ALUWritePC(result); // setflags is always FALSE here
8793 else
8794 R[d] = result;
8795 if setflags then
8796 APSR.N = result<31>;
8797 APSR.Z = IsZeroBit(result);
8798 APSR.C = carry;
8799 APSR.V = overflow;
8800#endif
8801
8802 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008803
8804 uint32_t Rd; // the destination register
8805 uint32_t Rn; // the first operand
8806 uint32_t Rm; // the second operand
8807 bool setflags;
8808 ARM_ShifterType shift_t;
8809 uint32_t shift_n; // the shift applied to the value read from Rm
8810 switch (encoding) {
8811 case eEncodingT1:
8812 Rd = Rn = Bits32(opcode, 2, 0);
8813 Rm = Bits32(opcode, 5, 3);
8814 setflags = !InITBlock();
8815 shift_t = SRType_LSL;
8816 shift_n = 0;
8817 break;
8818 case eEncodingT2:
8819 Rd = Bits32(opcode, 11, 8);
8820 Rn = Bits32(opcode, 19, 16);
8821 Rm = Bits32(opcode, 3, 0);
8822 setflags = BitIsSet(opcode, 20);
8823 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8824 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8825 return false;
8826 break;
8827 case eEncodingA1:
8828 Rd = Bits32(opcode, 15, 12);
8829 Rn = Bits32(opcode, 19, 16);
8830 Rm = Bits32(opcode, 3, 0);
8831 setflags = BitIsSet(opcode, 20);
8832 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008833
Johnny Chen9b381772011-02-23 01:01:21 +00008834 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008835 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008836 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008837 break;
8838 default:
8839 return false;
8840 }
8841 // Read the register value from register Rn.
8842 uint32_t val1 = ReadCoreReg(Rn, &success);
8843 if (!success)
8844 return false;
8845
8846 // Read the register value from register Rm.
8847 uint32_t val2 = ReadCoreReg(Rm, &success);
8848 if (!success)
8849 return false;
8850
8851 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8852 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8853
8854 EmulateInstruction::Context context;
8855 context.type = EmulateInstruction::eContextImmediate;
8856 context.SetNoArgs();
8857 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8858 return false;
8859
8860 return true;
8861}
8862
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008863// This instruction subtracts an immediate value from a register value, and writes the result
8864// to the destination register. It can optionally update the condition flags based on the result.
8865bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008866EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008867{
8868#if 0
8869 // ARM pseudo code...
8870 if ConditionPassed() then
8871 EncodingSpecificOperations();
8872 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8873 R[d] = result;
8874 if setflags then
8875 APSR.N = result<31>;
8876 APSR.Z = IsZeroBit(result);
8877 APSR.C = carry;
8878 APSR.V = overflow;
8879#endif
8880
8881 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008882
8883 uint32_t Rd; // the destination register
8884 uint32_t Rn; // the first operand
8885 bool setflags;
8886 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8887 switch (encoding) {
8888 case eEncodingT1:
8889 Rd = Bits32(opcode, 2, 0);
8890 Rn = Bits32(opcode, 5, 3);
8891 setflags = !InITBlock();
8892 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8893 break;
8894 case eEncodingT2:
8895 Rd = Rn = Bits32(opcode, 10, 8);
8896 setflags = !InITBlock();
8897 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8898 break;
8899 case eEncodingT3:
8900 Rd = Bits32(opcode, 11, 8);
8901 Rn = Bits32(opcode, 19, 16);
8902 setflags = BitIsSet(opcode, 20);
8903 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8904
8905 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8906 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008907 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008908
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008909 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008910 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008911 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008912
8913 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8914 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8915 return false;
8916 break;
8917 case eEncodingT4:
8918 Rd = Bits32(opcode, 11, 8);
8919 Rn = Bits32(opcode, 19, 16);
8920 setflags = BitIsSet(opcode, 20);
8921 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8922
8923 // if Rn == '1111' then SEE ADR;
8924 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008925 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008926
8927 // if Rn == '1101' then SEE SUB (SP minus immediate);
8928 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008929 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008930
8931 if (BadReg(Rd))
8932 return false;
8933 break;
8934 default:
8935 return false;
8936 }
8937 // Read the register value from the operand register Rn.
8938 uint32_t reg_val = ReadCoreReg(Rn, &success);
8939 if (!success)
8940 return false;
8941
8942 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8943
8944 EmulateInstruction::Context context;
8945 context.type = EmulateInstruction::eContextImmediate;
8946 context.SetNoArgs ();
8947
8948 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8949 return false;
8950
8951 return true;
8952}
8953
8954// This instruction subtracts an immediate value from a register value, and writes the result
8955// to the destination register. It can optionally update the condition flags based on the result.
8956bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008957EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008958{
8959#if 0
8960 // ARM pseudo code...
8961 if ConditionPassed() then
8962 EncodingSpecificOperations();
8963 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8964 if d == 15 then
8965 ALUWritePC(result); // setflags is always FALSE here
8966 else
8967 R[d] = result;
8968 if setflags then
8969 APSR.N = result<31>;
8970 APSR.Z = IsZeroBit(result);
8971 APSR.C = carry;
8972 APSR.V = overflow;
8973#endif
8974
8975 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008976
8977 uint32_t Rd; // the destination register
8978 uint32_t Rn; // the first operand
8979 bool setflags;
8980 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8981 switch (encoding) {
8982 case eEncodingA1:
8983 Rd = Bits32(opcode, 15, 12);
8984 Rn = Bits32(opcode, 19, 16);
8985 setflags = BitIsSet(opcode, 20);
8986 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8987
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008988 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008989 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008990 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008991
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008992 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008993 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008994 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008995
8996 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008997 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008998 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008999 break;
9000 default:
9001 return false;
9002 }
9003 // Read the register value from the operand register Rn.
9004 uint32_t reg_val = ReadCoreReg(Rn, &success);
9005 if (!success)
9006 return false;
9007
9008 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9009
9010 EmulateInstruction::Context context;
9011 context.type = EmulateInstruction::eContextImmediate;
9012 context.SetNoArgs ();
9013
9014 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9015 return false;
9016
9017 return true;
9018}
9019
Johnny Chen2115b412011-02-21 23:42:44 +00009020// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9021// immediate value. It updates the condition flags based on the result, and discards the result.
9022bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009023EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009024{
9025#if 0
9026 // ARM pseudo code...
9027 if ConditionPassed() then
9028 EncodingSpecificOperations();
9029 result = R[n] EOR imm32;
9030 APSR.N = result<31>;
9031 APSR.Z = IsZeroBit(result);
9032 APSR.C = carry;
9033 // APSR.V unchanged
9034#endif
9035
9036 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009037
Greg Clayton7bc39082011-03-24 23:53:38 +00009038 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009039 {
9040 uint32_t Rn;
9041 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9042 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9043 switch (encoding)
9044 {
9045 case eEncodingT1:
9046 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009047 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009048 if (BadReg(Rn))
9049 return false;
9050 break;
9051 case eEncodingA1:
9052 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009053 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009054 break;
9055 default:
9056 return false;
9057 }
9058
9059 // Read the first operand.
9060 uint32_t val1 = ReadCoreReg(Rn, &success);
9061 if (!success)
9062 return false;
9063
9064 uint32_t result = val1 ^ imm32;
9065
9066 EmulateInstruction::Context context;
9067 context.type = EmulateInstruction::eContextImmediate;
9068 context.SetNoArgs ();
9069
9070 if (!WriteFlags(context, result, carry))
9071 return false;
9072 }
9073 return true;
9074}
9075
9076// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9077// optionally-shifted register value. It updates the condition flags based on the result, and discards
9078// the result.
9079bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009080EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009081{
9082#if 0
9083 // ARM pseudo code...
9084 if ConditionPassed() then
9085 EncodingSpecificOperations();
9086 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9087 result = R[n] EOR shifted;
9088 APSR.N = result<31>;
9089 APSR.Z = IsZeroBit(result);
9090 APSR.C = carry;
9091 // APSR.V unchanged
9092#endif
9093
9094 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009095
Greg Clayton7bc39082011-03-24 23:53:38 +00009096 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009097 {
9098 uint32_t Rn, Rm;
9099 ARM_ShifterType shift_t;
9100 uint32_t shift_n; // the shift applied to the value read from Rm
9101 uint32_t carry;
9102 switch (encoding)
9103 {
9104 case eEncodingT1:
9105 Rn = Bits32(opcode, 19, 16);
9106 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009107 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009108 if (BadReg(Rn) || BadReg(Rm))
9109 return false;
9110 break;
9111 case eEncodingA1:
9112 Rn = Bits32(opcode, 19, 16);
9113 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009114 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009115 break;
9116 default:
9117 return false;
9118 }
9119
9120 // Read the first operand.
9121 uint32_t val1 = ReadCoreReg(Rn, &success);
9122 if (!success)
9123 return false;
9124
9125 // Read the second operand.
9126 uint32_t val2 = ReadCoreReg(Rm, &success);
9127 if (!success)
9128 return false;
9129
9130 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9131 uint32_t result = val1 ^ shifted;
9132
9133 EmulateInstruction::Context context;
9134 context.type = EmulateInstruction::eContextImmediate;
9135 context.SetNoArgs ();
9136
9137 if (!WriteFlags(context, result, carry))
9138 return false;
9139 }
9140 return true;
9141}
9142
Johnny Chende3cce32011-02-21 21:24:49 +00009143// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9144// It updates the condition flags based on the result, and discards the result.
9145bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009146EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009147{
9148#if 0
9149 // ARM pseudo code...
9150 if ConditionPassed() then
9151 EncodingSpecificOperations();
9152 result = R[n] AND imm32;
9153 APSR.N = result<31>;
9154 APSR.Z = IsZeroBit(result);
9155 APSR.C = carry;
9156 // APSR.V unchanged
9157#endif
9158
9159 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009160
Greg Clayton7bc39082011-03-24 23:53:38 +00009161 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009162 {
9163 uint32_t Rn;
9164 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9165 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9166 switch (encoding)
9167 {
9168 case eEncodingT1:
9169 Rn = Bits32(opcode, 19, 16);
9170 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9171 if (BadReg(Rn))
9172 return false;
9173 break;
9174 case eEncodingA1:
9175 Rn = Bits32(opcode, 19, 16);
9176 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9177 break;
9178 default:
9179 return false;
9180 }
9181
9182 // Read the first operand.
9183 uint32_t val1 = ReadCoreReg(Rn, &success);
9184 if (!success)
9185 return false;
9186
9187 uint32_t result = val1 & imm32;
9188
9189 EmulateInstruction::Context context;
9190 context.type = EmulateInstruction::eContextImmediate;
9191 context.SetNoArgs ();
9192
9193 if (!WriteFlags(context, result, carry))
9194 return false;
9195 }
9196 return true;
9197}
9198
9199// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9200// It updates the condition flags based on the result, and discards the result.
9201bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009202EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009203{
9204#if 0
9205 // ARM pseudo code...
9206 if ConditionPassed() then
9207 EncodingSpecificOperations();
9208 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9209 result = R[n] AND shifted;
9210 APSR.N = result<31>;
9211 APSR.Z = IsZeroBit(result);
9212 APSR.C = carry;
9213 // APSR.V unchanged
9214#endif
9215
9216 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009217
Greg Clayton7bc39082011-03-24 23:53:38 +00009218 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009219 {
9220 uint32_t Rn, Rm;
9221 ARM_ShifterType shift_t;
9222 uint32_t shift_n; // the shift applied to the value read from Rm
9223 uint32_t carry;
9224 switch (encoding)
9225 {
9226 case eEncodingT1:
9227 Rn = Bits32(opcode, 2, 0);
9228 Rm = Bits32(opcode, 5, 3);
9229 shift_t = SRType_LSL;
9230 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009231 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009232 case eEncodingT2:
9233 Rn = Bits32(opcode, 19, 16);
9234 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009235 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009236 if (BadReg(Rn) || BadReg(Rm))
9237 return false;
9238 break;
9239 case eEncodingA1:
9240 Rn = Bits32(opcode, 19, 16);
9241 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009242 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009243 break;
9244 default:
9245 return false;
9246 }
9247
9248 // Read the first operand.
9249 uint32_t val1 = ReadCoreReg(Rn, &success);
9250 if (!success)
9251 return false;
9252
9253 // Read the second operand.
9254 uint32_t val2 = ReadCoreReg(Rm, &success);
9255 if (!success)
9256 return false;
9257
9258 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9259 uint32_t result = val1 & shifted;
9260
9261 EmulateInstruction::Context context;
9262 context.type = EmulateInstruction::eContextImmediate;
9263 context.SetNoArgs ();
9264
9265 if (!WriteFlags(context, result, carry))
9266 return false;
9267 }
9268 return true;
9269}
Caroline Ticed05b4902011-03-29 21:24:06 +00009270
9271// A8.6.216 SUB (SP minus register)
9272bool
9273EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9274{
9275#if 0
9276 if ConditionPassed() then
9277 EncodingSpecificOperations();
9278 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009279 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009280 if d == 15 then // Can only occur for ARM encoding
9281 ALUWritePC(result); // setflags is always FALSE here
9282 else
9283 R[d] = result;
9284 if setflags then
9285 APSR.N = result<31>;
9286 APSR.Z = IsZeroBit(result);
9287 APSR.C = carry;
9288 APSR.V = overflow;
9289#endif
9290
9291 bool success = false;
9292
9293 if (ConditionPassed(opcode))
9294 {
9295 uint32_t d;
9296 uint32_t m;
9297 bool setflags;
9298 ARM_ShifterType shift_t;
9299 uint32_t shift_n;
9300
9301 switch (encoding)
9302 {
9303 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009304 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009305 d = Bits32 (opcode, 11, 8);
9306 m = Bits32 (opcode, 3, 0);
9307 setflags = BitIsSet (opcode, 20);
9308
9309 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9310 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9311
9312 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9313 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9314 return false;
9315
9316 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9317 if ((d == 15) || BadReg (m))
9318 return false;
9319 break;
9320
9321 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009322 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009323 d = Bits32 (opcode, 15, 12);
9324 m = Bits32 (opcode, 3, 0);
9325 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009326
Greg Clayton061b79d2011-05-09 20:18:18 +00009327 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009328 if (d == 15 && setflags)
9329 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009330
9331 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9332 shift_n = DecodeImmShiftARM (opcode, shift_t);
9333 break;
9334
9335 default:
9336 return false;
9337 }
9338
9339 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9340 uint32_t Rm = ReadCoreReg (m, &success);
9341 if (!success)
9342 return false;
9343
9344 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9345
Greg Clayton061b79d2011-05-09 20:18:18 +00009346 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009347 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9348 if (!success)
9349 return false;
9350
9351 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9352
9353 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009354 context.type = eContextArithmetic;
9355 RegisterInfo sp_reg;
9356 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9357 RegisterInfo dwarf_reg;
9358 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +00009359 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9360
Caroline Ticeef440002011-03-30 05:40:56 +00009361 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009362 return false;
9363 }
9364 return true;
9365}
9366
9367
9368// A8.6.7 ADD (register-shifted register)
9369bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009370EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009371{
9372#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009373 if ConditionPassed() then
9374 EncodingSpecificOperations();
9375 shift_n = UInt(R[s]<7:0>);
9376 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009377 (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009378 R[d] = result;
9379 if setflags then
9380 APSR.N = result<31>;
9381 APSR.Z = IsZeroBit(result);
9382 APSR.C = carry;
9383 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009384#endif
9385
Caroline Ticec08ed382011-03-29 23:03:16 +00009386 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009387
9388 if (ConditionPassed(opcode))
9389 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009390 uint32_t d;
9391 uint32_t n;
9392 uint32_t m;
9393 uint32_t s;
9394 bool setflags;
9395 ARM_ShifterType shift_t;
9396
Caroline Ticed05b4902011-03-29 21:24:06 +00009397 switch (encoding)
9398 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009399 case eEncodingA1:
9400 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9401 d = Bits32 (opcode, 15, 12);
9402 n = Bits32 (opcode, 19, 16);
9403 m = Bits32 (opcode, 3, 0);
9404 s = Bits32 (opcode, 11, 8);
9405
Greg Clayton061b79d2011-05-09 20:18:18 +00009406 // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
Caroline Ticec08ed382011-03-29 23:03:16 +00009407 setflags = BitIsSet (opcode, 20);
9408 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9409
9410 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9411 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9412 return false;
9413 break;
9414
9415 default:
9416 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009417 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009418
9419 // shift_n = UInt(R[s]<7:0>);
9420 uint32_t Rs = ReadCoreReg (s, &success);
9421 if (!success)
9422 return false;
9423
9424 uint32_t shift_n = Bits32 (Rs, 7, 0);
9425
9426 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9427 uint32_t Rm = ReadCoreReg (m, &success);
9428 if (!success)
9429 return false;
9430
9431 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9432
Greg Clayton061b79d2011-05-09 20:18:18 +00009433 // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009434 uint32_t Rn = ReadCoreReg (n, &success);
9435 if (!success)
9436 return false;
9437
9438 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9439
9440 // R[d] = result;
9441 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009442 context.type = eContextArithmetic;
9443 RegisterInfo reg_n;
9444 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9445 RegisterInfo reg_m;
9446 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009447
9448 context.SetRegisterRegisterOperands (reg_n, reg_m);
9449
9450 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9451 return false;
9452
9453 // if setflags then
9454 // APSR.N = result<31>;
9455 // APSR.Z = IsZeroBit(result);
9456 // APSR.C = carry;
9457 // APSR.V = overflow;
9458 if (setflags)
9459 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009460 }
9461 return true;
9462}
9463
9464// A8.6.213 SUB (register)
9465bool
9466EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9467{
9468#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009469 if ConditionPassed() then
9470 EncodingSpecificOperations();
9471 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009472 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009473 if d == 15 then // Can only occur for ARM encoding
9474 ALUWritePC(result); // setflags is always FALSE here
9475 else
9476 R[d] = result;
9477 if setflags then
9478 APSR.N = result<31>;
9479 APSR.Z = IsZeroBit(result);
9480 APSR.C = carry;
9481 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009482#endif
9483
Caroline Tice4cccd532011-03-29 23:44:20 +00009484 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009485
9486 if (ConditionPassed(opcode))
9487 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009488 uint32_t d;
9489 uint32_t n;
9490 uint32_t m;
9491 bool setflags;
9492 ARM_ShifterType shift_t;
9493 uint32_t shift_n;
9494
Caroline Ticed05b4902011-03-29 21:24:06 +00009495 switch (encoding)
9496 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009497 case eEncodingT1:
9498 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9499 d = Bits32 (opcode, 2, 0);
9500 n = Bits32 (opcode, 5, 3);
9501 m = Bits32 (opcode, 8, 6);
9502 setflags = !InITBlock();
9503
9504 // (shift_t, shift_n) = (SRType_LSL, 0);
9505 shift_t = SRType_LSL;
9506 shift_n = 0;
9507
9508 break;
9509
9510 case eEncodingT2:
Greg Clayton061b79d2011-05-09 20:18:18 +00009511 // if Rd == Ô1111Õ && S == Ô1Õ then SEE CMP (register);
9512 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9513 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009514 d = Bits32 (opcode, 11, 8);
9515 n = Bits32 (opcode, 19, 16);
9516 m = Bits32 (opcode, 3, 0);
9517 setflags = BitIsSet (opcode, 20);
9518
9519 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9520 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9521
9522 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9523 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9524 return false;
9525
9526 break;
9527
9528 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009529 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9530 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009531 d = Bits32 (opcode, 15, 12);
9532 n = Bits32 (opcode, 19, 16);
9533 m = Bits32 (opcode, 3, 0);
9534 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009535
Greg Clayton061b79d2011-05-09 20:18:18 +00009536 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009537 if ((d == 15) && setflags)
9538 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009539
9540 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9541 shift_n = DecodeImmShiftARM (opcode, shift_t);
9542
9543 break;
9544
9545 default:
9546 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009547 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009548
9549 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9550 uint32_t Rm = ReadCoreReg (m, &success);
9551 if (!success)
9552 return false;
9553
9554 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9555
Greg Clayton061b79d2011-05-09 20:18:18 +00009556 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009557 uint32_t Rn = ReadCoreReg (n, &success);
9558 if (!success)
9559 return false;
9560
9561 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9562
9563 // if d == 15 then // Can only occur for ARM encoding
9564 // ALUWritePC(result); // setflags is always FALSE here
9565 // else
9566 // R[d] = result;
9567 // if setflags then
9568 // APSR.N = result<31>;
9569 // APSR.Z = IsZeroBit(result);
9570 // APSR.C = carry;
9571 // APSR.V = overflow;
9572
9573 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009574 context.type = eContextArithmetic;
9575 RegisterInfo reg_n;
9576 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9577 RegisterInfo reg_m;
9578 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009579 context.SetRegisterRegisterOperands (reg_n, reg_m);
9580
Caroline Ticeef440002011-03-30 05:40:56 +00009581 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009582 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009583 }
9584 return true;
9585}
Caroline Tice4cccd532011-03-29 23:44:20 +00009586
Caroline Ticed05b4902011-03-29 21:24:06 +00009587// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009588// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9589// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009590bool
9591EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9592{
9593#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009594 if ConditionPassed() then
9595 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9596 address = R[n] + imm32;
9597 if ExclusiveMonitorsPass(address,4) then
9598 MemA[address,4] = R[t];
9599 R[d] = 0;
9600 else
9601 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009602#endif
9603
Caroline Tice5168b6c2011-03-30 05:15:46 +00009604 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009605
9606 if (ConditionPassed(opcode))
9607 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009608 uint32_t d;
9609 uint32_t t;
9610 uint32_t n;
9611 uint32_t imm32;
9612 const uint32_t addr_byte_size = GetAddressByteSize();
9613
Caroline Ticed05b4902011-03-29 21:24:06 +00009614 switch (encoding)
9615 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009616 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009617 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009618 d = Bits32 (opcode, 11, 8);
9619 t = Bits32 (opcode, 15, 12);
9620 n = Bits32 (opcode, 19, 16);
9621 imm32 = Bits32 (opcode, 7, 0) << 2;
9622
9623 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9624 if (BadReg (d) || BadReg (t) || (n == 15))
9625 return false;
9626
9627 // if d == n || d == t then UNPREDICTABLE;
9628 if ((d == n) || (d == t))
9629 return false;
9630
9631 break;
9632
9633 case eEncodingA1:
9634 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9635 d = Bits32 (opcode, 15, 12);
9636 t = Bits32 (opcode, 3, 0);
9637 n = Bits32 (opcode, 19, 16);
9638 imm32 = 0;
9639
9640 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9641 if ((d == 15) || (t == 15) || (n == 15))
9642 return false;
9643
9644 // if d == n || d == t then UNPREDICTABLE;
9645 if ((d == n) || (d == t))
9646 return false;
9647
9648 break;
9649
9650 default:
9651 return false;
9652 }
9653
9654 // address = R[n] + imm32;
9655 uint32_t Rn = ReadCoreReg (n, &success);
9656 if (!success)
9657 return false;
9658
9659 addr_t address = Rn + imm32;
9660
Greg Claytonc07d4512011-04-26 23:48:45 +00009661 RegisterInfo base_reg;
9662 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9663 RegisterInfo data_reg;
9664 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009665 EmulateInstruction::Context context;
9666 context.type = eContextRegisterStore;
9667 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9668
9669 // if ExclusiveMonitorsPass(address,4) then
9670 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9671 // always return true.
9672 if (true)
9673 {
9674 // MemA[address,4] = R[t];
9675 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9676 if (!success)
9677 return false;
9678
9679 if (!MemAWrite (context, address, Rt, addr_byte_size))
9680 return false;
9681
9682 // R[d] = 0;
9683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9684 return false;
9685 }
9686 else
9687 {
9688 // R[d] = 1;
9689 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9690 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009691 }
9692 }
9693 return true;
9694}
9695
9696// A8.6.197 STRB (immediate, ARM)
9697bool
9698EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9699{
9700#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009701 if ConditionPassed() then
9702 EncodingSpecificOperations();
9703 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9704 address = if index then offset_addr else R[n];
9705 MemU[address,1] = R[t]<7:0>;
9706 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009707#endif
9708
Caroline Ticeef440002011-03-30 05:40:56 +00009709 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009710
9711 if (ConditionPassed(opcode))
9712 {
Caroline Ticeef440002011-03-30 05:40:56 +00009713 uint32_t t;
9714 uint32_t n;
9715 uint32_t imm32;
9716 bool index;
9717 bool add;
9718 bool wback;
9719
Caroline Ticed05b4902011-03-29 21:24:06 +00009720 switch (encoding)
9721 {
Caroline Ticeef440002011-03-30 05:40:56 +00009722 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009723 // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
Caroline Ticeef440002011-03-30 05:40:56 +00009724 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9725 t = Bits32 (opcode, 15, 12);
9726 n = Bits32 (opcode, 19, 16);
9727 imm32 = Bits32 (opcode, 11, 0);
9728
Greg Clayton061b79d2011-05-09 20:18:18 +00009729 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeef440002011-03-30 05:40:56 +00009730 index = BitIsSet (opcode, 24);
9731 add = BitIsSet (opcode, 23);
9732 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9733
9734 // if t == 15 then UNPREDICTABLE;
9735 if (t == 15)
9736 return false;
9737
9738 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9739 if (wback && ((n == 15) || (n == t)))
9740 return false;
9741
9742 break;
9743
9744 default:
9745 return false;
9746 }
9747
9748 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9749 uint32_t Rn = ReadCoreReg (n, &success);
9750 if (!success)
9751 return false;
9752
9753 addr_t offset_addr;
9754 if (add)
9755 offset_addr = Rn + imm32;
9756 else
9757 offset_addr = Rn - imm32;
9758
9759 // address = if index then offset_addr else R[n];
9760 addr_t address;
9761 if (index)
9762 address = offset_addr;
9763 else
9764 address = Rn;
9765
9766 // MemU[address,1] = R[t]<7:0>;
9767 uint32_t Rt = ReadCoreReg (t, &success);
9768 if (!success)
9769 return false;
9770
Greg Claytonc07d4512011-04-26 23:48:45 +00009771 RegisterInfo base_reg;
9772 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9773 RegisterInfo data_reg;
9774 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticeef440002011-03-30 05:40:56 +00009775 EmulateInstruction::Context context;
9776 context.type = eContextRegisterStore;
9777 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9778
9779 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9780 return false;
9781
9782 // if wback then R[n] = offset_addr;
9783 if (wback)
9784 {
Caroline Tice523c5542011-04-13 00:42:12 +00009785 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009786 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009787 }
9788 }
9789 return true;
9790}
9791
9792// A8.6.194 STR (immediate, ARM)
9793bool
9794EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9795{
9796#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009797 if ConditionPassed() then
9798 EncodingSpecificOperations();
9799 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9800 address = if index then offset_addr else R[n];
9801 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9802 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009803#endif
9804
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009805 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009806
9807 if (ConditionPassed(opcode))
9808 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009809 uint32_t t;
9810 uint32_t n;
9811 uint32_t imm32;
9812 bool index;
9813 bool add;
9814 bool wback;
9815
9816 const uint32_t addr_byte_size = GetAddressByteSize();
9817
Caroline Ticed05b4902011-03-29 21:24:06 +00009818 switch (encoding)
9819 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009820 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009821 // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
9822 // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009823 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9824 t = Bits32 (opcode, 15, 12);
9825 n = Bits32 (opcode, 19, 16);
9826 imm32 = Bits32 (opcode, 11, 0);
9827
Greg Clayton061b79d2011-05-09 20:18:18 +00009828 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009829 index = BitIsSet (opcode, 24);
9830 add = BitIsSet (opcode, 23);
9831 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9832
9833 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9834 if (wback && ((n == 15) || (n == t)))
9835 return false;
9836
9837 break;
9838
9839 default:
9840 return false;
9841 }
9842
9843 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9844 uint32_t Rn = ReadCoreReg (n, &success);
9845 if (!success)
9846 return false;
9847
9848 addr_t offset_addr;
9849 if (add)
9850 offset_addr = Rn + imm32;
9851 else
9852 offset_addr = Rn - imm32;
9853
9854 // address = if index then offset_addr else R[n];
9855 addr_t address;
9856 if (index)
9857 address = offset_addr;
9858 else
9859 address = Rn;
9860
Greg Claytonc07d4512011-04-26 23:48:45 +00009861 RegisterInfo base_reg;
9862 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9863 RegisterInfo data_reg;
9864 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009865 EmulateInstruction::Context context;
9866 context.type = eContextRegisterStore;
9867 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9868
9869 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9870 uint32_t Rt = ReadCoreReg (t, &success);
9871 if (!success)
9872 return false;
9873
9874 if (t == 15)
9875 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009876 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009877 if (!success)
9878 return false;
9879
9880 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9881 return false;
9882 }
9883 else
9884 {
9885 if (!MemUWrite (context, address, Rt, addr_byte_size))
9886 return false;
9887 }
9888
9889 // if wback then R[n] = offset_addr;
9890 if (wback)
9891 {
9892 context.type = eContextAdjustBaseRegister;
9893 context.SetImmediate (offset_addr);
9894
9895 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9896 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009897 }
9898 }
9899 return true;
9900}
9901
Caroline Ticed05b4902011-03-29 21:24:06 +00009902// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009903// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9904// 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 +00009905bool
9906EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9907{
9908#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009909 if ConditionPassed() then
9910 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9911 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9912 address = if index then offset_addr else R[n];
9913 R[t] = MemA[address,4];
9914 R[t2] = MemA[address+4,4];
9915 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009916#endif
9917
Caroline Tice1697dd72011-03-30 17:11:45 +00009918 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009919
9920 if (ConditionPassed(opcode))
9921 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009922 uint32_t t;
9923 uint32_t t2;
9924 uint32_t n;
9925 uint32_t imm32;
9926 bool index;
9927 bool add;
9928 bool wback;
9929
Caroline Ticed05b4902011-03-29 21:24:06 +00009930 switch (encoding)
9931 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009932 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009933 //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
9934 //if Rn == Ô1111Õ then SEE LDRD (literal);
9935 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice1697dd72011-03-30 17:11:45 +00009936 t = Bits32 (opcode, 15, 12);
9937 t2 = Bits32 (opcode, 11, 8);
9938 n = Bits32 (opcode, 19, 16);
9939 imm32 = Bits32 (opcode, 7, 0) << 2;
9940
Greg Clayton061b79d2011-05-09 20:18:18 +00009941 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +00009942 index = BitIsSet (opcode, 24);
9943 add = BitIsSet (opcode, 23);
9944 wback = BitIsSet (opcode, 21);
9945
9946 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9947 if (wback && ((n == t) || (n == t2)))
9948 return false;
9949
9950 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9951 if (BadReg (t) || BadReg (t2) || (t == t2))
9952 return false;
9953
9954 break;
9955
9956 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009957 //if Rn == Ô1111Õ then SEE LDRD (literal);
9958 //if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +00009959 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9960 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +00009961 if (BitIsSet (t, 0))
9962 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +00009963 t2 = t + 1;
9964 n = Bits32 (opcode, 19, 16);
9965 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9966
Greg Clayton061b79d2011-05-09 20:18:18 +00009967 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +00009968 index = BitIsSet (opcode, 24);
9969 add = BitIsSet (opcode, 23);
9970 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9971
Greg Clayton061b79d2011-05-09 20:18:18 +00009972 //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +00009973 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9974 return false;
9975
9976 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9977 if (wback && ((n == t) || (n == t2)))
9978 return false;
9979
9980 //if t2 == 15 then UNPREDICTABLE;
9981 if (t2 == 15)
9982 return false;
9983
9984 break;
9985
9986 default:
9987 return false;
9988 }
9989
9990 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9991 uint32_t Rn = ReadCoreReg (n, &success);
9992 if (!success)
9993 return false;
9994
9995 addr_t offset_addr;
9996 if (add)
9997 offset_addr = Rn + imm32;
9998 else
9999 offset_addr = Rn - imm32;
10000
10001 //address = if index then offset_addr else R[n];
10002 addr_t address;
10003 if (index)
10004 address = offset_addr;
10005 else
10006 address = Rn;
10007
10008 //R[t] = MemA[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +000010009 RegisterInfo base_reg;
10010 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1697dd72011-03-30 17:11:45 +000010011
10012 EmulateInstruction::Context context;
10013 context.type = eContextRegisterLoad;
10014 context.SetRegisterPlusOffset (base_reg, address - Rn);
10015
10016 const uint32_t addr_byte_size = GetAddressByteSize();
10017 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10018 if (!success)
10019 return false;
10020
10021 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10022 return false;
10023
10024 //R[t2] = MemA[address+4,4];
10025
10026 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10027 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10028 if (!success)
10029 return false;
10030
10031 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10032 return false;
10033
10034 //if wback then R[n] = offset_addr;
10035 if (wback)
10036 {
10037 context.type = eContextAdjustBaseRegister;
10038 context.SetAddress (offset_addr);
10039
10040 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10041 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010042 }
10043 }
10044 return true;
10045}
10046
Caroline Ticed05b4902011-03-29 21:24:06 +000010047// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010048// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10049// 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 +000010050bool
10051EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10052{
10053#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010054 if ConditionPassed() then
10055 EncodingSpecificOperations();
10056 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10057 address = if index then offset_addr else R[n];
10058 R[t] = MemA[address,4];
10059 R[t2] = MemA[address+4,4];
10060 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010061#endif
10062
Caroline Ticeeab301f2011-03-30 17:54:52 +000010063 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010064
10065 if (ConditionPassed(opcode))
10066 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010067 uint32_t t;
10068 uint32_t t2;
10069 uint32_t n;
10070 uint32_t m;
10071 bool index;
10072 bool add;
10073 bool wback;
10074
Caroline Ticed05b4902011-03-29 21:24:06 +000010075 switch (encoding)
10076 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010077 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010078 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010079 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10080 t = Bits32 (opcode, 15, 12);
10081 if (BitIsSet (t, 0))
10082 return false;
10083 t2 = t + 1;
10084 n = Bits32 (opcode, 19, 16);
10085 m = Bits32 (opcode, 3, 0);
10086
Greg Clayton061b79d2011-05-09 20:18:18 +000010087 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010088 index = BitIsSet (opcode, 24);
10089 add = BitIsSet (opcode, 23);
10090 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10091
Greg Clayton061b79d2011-05-09 20:18:18 +000010092 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010093 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10094 return false;
10095
10096 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10097 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10098 return false;
10099
10100 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10101 if (wback && ((n == 15) || (n == t) || (n == t2)))
10102 return false;
10103
10104 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10105 if ((ArchVersion() < 6) && wback && (m == n))
10106 return false;
10107 break;
10108
10109 default:
10110 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010111 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010112
Caroline Ticeeab301f2011-03-30 17:54:52 +000010113 uint32_t Rn = ReadCoreReg (n, &success);
10114 if (!success)
10115 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010116 RegisterInfo base_reg;
10117 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010118
Caroline Ticeeab301f2011-03-30 17:54:52 +000010119 uint32_t Rm = ReadCoreReg (m, &success);
10120 if (!success)
10121 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010122 RegisterInfo offset_reg;
10123 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010124
Caroline Ticeeab301f2011-03-30 17:54:52 +000010125 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10126 addr_t offset_addr;
10127 if (add)
10128 offset_addr = Rn + Rm;
10129 else
10130 offset_addr = Rn - Rm;
10131
10132 // address = if index then offset_addr else R[n];
10133 addr_t address;
10134 if (index)
10135 address = offset_addr;
10136 else
10137 address = Rn;
10138
10139 EmulateInstruction::Context context;
10140 context.type = eContextRegisterLoad;
10141 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10142
10143 // R[t] = MemA[address,4];
10144 const uint32_t addr_byte_size = GetAddressByteSize();
10145 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10146 if (!success)
10147 return false;
10148
10149 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10150 return false;
10151
10152 // R[t2] = MemA[address+4,4];
10153
10154 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10155 if (!success)
10156 return false;
10157
10158 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10159 return false;
10160
10161 // if wback then R[n] = offset_addr;
10162 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010163 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010164 context.type = eContextAdjustBaseRegister;
10165 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010166
Caroline Ticeeab301f2011-03-30 17:54:52 +000010167 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10168 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010169 }
10170 }
10171 return true;
10172}
Caroline Ticed05b4902011-03-29 21:24:06 +000010173
10174// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010175// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10176// 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 +000010177bool
10178EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10179{
10180#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010181 if ConditionPassed() then
10182 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10183 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10184 address = if index then offset_addr else R[n];
10185 MemA[address,4] = R[t];
10186 MemA[address+4,4] = R[t2];
10187 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010188#endif
10189
Caroline Tice74467fe2011-03-30 19:02:56 +000010190 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010191
Caroline Tice74467fe2011-03-30 19:02:56 +000010192 if (ConditionPassed(opcode))
10193 {
10194 uint32_t t;
10195 uint32_t t2;
10196 uint32_t n;
10197 uint32_t imm32;
10198 bool index;
10199 bool add;
10200 bool wback;
10201
10202 switch (encoding)
10203 {
10204 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010205 // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10206 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice74467fe2011-03-30 19:02:56 +000010207 t = Bits32 (opcode, 15, 12);
10208 t2 = Bits32 (opcode, 11, 8);
10209 n = Bits32 (opcode, 19, 16);
10210 imm32 = Bits32 (opcode, 7, 0) << 2;
10211
Greg Clayton061b79d2011-05-09 20:18:18 +000010212 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010213 index = BitIsSet (opcode, 24);
10214 add = BitIsSet (opcode, 23);
10215 wback = BitIsSet (opcode, 21);
10216
10217 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10218 if (wback && ((n == t) || (n == t2)))
10219 return false;
10220
10221 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10222 if ((n == 15) || BadReg (t) || BadReg (t2))
10223 return false;
10224
10225 break;
10226
10227 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010228 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010229 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10230 t = Bits32 (opcode, 15, 12);
10231 if (BitIsSet (t, 0))
10232 return false;
10233
10234 t2 = t + 1;
10235 n = Bits32 (opcode, 19, 16);
10236 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10237
Greg Clayton061b79d2011-05-09 20:18:18 +000010238 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010239 index = BitIsSet (opcode, 24);
10240 add = BitIsSet (opcode, 23);
10241 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10242
Greg Clayton061b79d2011-05-09 20:18:18 +000010243 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010244 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10245 return false;
10246
10247 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10248 if (wback && ((n == 15) || (n == t) || (n == t2)))
10249 return false;
10250
10251 // if t2 == 15 then UNPREDICTABLE;
10252 if (t2 == 15)
10253 return false;
10254
10255 break;
10256
10257 default:
10258 return false;
10259 }
10260
Greg Claytonc07d4512011-04-26 23:48:45 +000010261 RegisterInfo base_reg;
10262 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010263
10264 uint32_t Rn = ReadCoreReg (n, &success);
10265 if (!success)
10266 return false;
10267
10268 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10269 addr_t offset_addr;
10270 if (add)
10271 offset_addr = Rn + imm32;
10272 else
10273 offset_addr = Rn - imm32;
10274
10275 //address = if index then offset_addr else R[n];
10276 addr_t address;
10277 if (index)
10278 address = offset_addr;
10279 else
10280 address = Rn;
10281
10282 //MemA[address,4] = R[t];
Greg Claytonc07d4512011-04-26 23:48:45 +000010283 RegisterInfo data_reg;
10284 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010285
10286 uint32_t data = ReadCoreReg (t, &success);
10287 if (!success)
10288 return false;
10289
10290 EmulateInstruction::Context context;
10291 context.type = eContextRegisterStore;
10292 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10293
10294 const uint32_t addr_byte_size = GetAddressByteSize();
10295
10296 if (!MemAWrite (context, address, data, addr_byte_size))
10297 return false;
10298
10299 //MemA[address+4,4] = R[t2];
Greg Claytonc07d4512011-04-26 23:48:45 +000010300 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010301 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10302
10303 data = ReadCoreReg (t2, &success);
10304 if (!success)
10305 return false;
10306
10307 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10308 return false;
10309
10310 //if wback then R[n] = offset_addr;
10311 if (wback)
10312 {
10313 context.type = eContextAdjustBaseRegister;
10314 context.SetAddress (offset_addr);
10315
10316 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10317 return false;
10318 }
10319 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010320 return true;
10321}
10322
10323
10324// A8.6.201 STRD (register)
10325bool
10326EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10327{
10328#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010329 if ConditionPassed() then
10330 EncodingSpecificOperations();
10331 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10332 address = if index then offset_addr else R[n];
10333 MemA[address,4] = R[t];
10334 MemA[address+4,4] = R[t2];
10335 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010336#endif
10337
Caroline Tice74467fe2011-03-30 19:02:56 +000010338 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010339
Caroline Tice74467fe2011-03-30 19:02:56 +000010340 if (ConditionPassed(opcode))
10341 {
10342 uint32_t t;
10343 uint32_t t2;
10344 uint32_t n;
10345 uint32_t m;
10346 bool index;
10347 bool add;
10348 bool wback;
10349
10350 switch (encoding)
10351 {
10352 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010353 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010354 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10355 t = Bits32 (opcode, 15, 12);
10356 if (BitIsSet (t, 0))
10357 return false;
10358
10359 t2 = t+1;
10360 n = Bits32 (opcode, 19, 16);
10361 m = Bits32 (opcode, 3, 0);
10362
Greg Clayton061b79d2011-05-09 20:18:18 +000010363 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010364 index = BitIsSet (opcode, 24);
10365 add = BitIsSet (opcode, 23);
10366 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10367
Greg Clayton061b79d2011-05-09 20:18:18 +000010368 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010369 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10370 return false;
10371
10372 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10373 if ((t2 == 15) || (m == 15))
10374 return false;
10375
10376 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10377 if (wback && ((n == 15) || (n == t) || (n == t2)))
10378 return false;
10379
10380 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010381 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010382 return false;
10383
10384 break;
10385
10386 default:
10387 return false;
10388 }
10389
Greg Claytonc07d4512011-04-26 23:48:45 +000010390 RegisterInfo base_reg;
10391 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10392 RegisterInfo offset_reg;
10393 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10394 RegisterInfo data_reg;
Caroline Tice74467fe2011-03-30 19:02:56 +000010395
10396 uint32_t Rn = ReadCoreReg (n, &success);
10397 if (!success)
10398 return false;
10399
10400 uint32_t Rm = ReadCoreReg (m, &success);
10401 if (!success)
10402 return false;
10403
10404 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10405 addr_t offset_addr;
10406 if (add)
10407 offset_addr = Rn + Rm;
10408 else
10409 offset_addr = Rn - Rm;
10410
10411 // address = if index then offset_addr else R[n];
10412 addr_t address;
10413 if (index)
10414 address = offset_addr;
10415 else
10416 address = Rn;
10417 // MemA[address,4] = R[t];
10418 uint32_t Rt = ReadCoreReg (t, &success);
10419 if (!success)
10420 return false;
10421
10422 EmulateInstruction::Context context;
10423 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +000010424 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010425 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10426
10427 const uint32_t addr_byte_size = GetAddressByteSize();
10428
10429 if (!MemAWrite (context, address, Rt, addr_byte_size))
10430 return false;
10431
10432 // MemA[address+4,4] = R[t2];
10433 uint32_t Rt2 = ReadCoreReg (t2, &success);
10434 if (!success)
10435 return false;
10436
Greg Claytonc07d4512011-04-26 23:48:45 +000010437 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010438
10439 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10440
10441 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10442 return false;
10443
10444 // if wback then R[n] = offset_addr;
10445 if (wback)
10446 {
10447 context.type = eContextAdjustBaseRegister;
10448 context.SetAddress (offset_addr);
10449
10450 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10451 return false;
10452
10453 }
10454 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010455 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010456}
10457
Caroline Tice4f605582011-03-31 00:02:51 +000010458// A8.6.319 VLDM
10459// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10460// an ARM core register.
10461bool
10462EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10463{
10464#if 0
10465 if ConditionPassed() then
10466 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10467 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010468 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010469 for r = 0 to regs-1
10470 if single_regs then
10471 S[d+r] = MemA[address,4]; address = address+4;
10472 else
10473 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10474 // Combine the word-aligned words in the correct order for current endianness.
10475 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10476#endif
10477
10478 bool success = false;
10479
10480 if (ConditionPassed(opcode))
10481 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010482 bool single_regs;
10483 bool add;
10484 bool wback;
10485 uint32_t d;
10486 uint32_t n;
10487 uint32_t imm32;
10488 uint32_t regs;
10489
Caroline Tice4f605582011-03-31 00:02:51 +000010490 switch (encoding)
10491 {
10492 case eEncodingT1:
10493 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010494 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10495 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10496 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10497 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010498 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10499 return false;
10500
10501 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010502 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice4f605582011-03-31 00:02:51 +000010503 single_regs = false;
10504 add = BitIsSet (opcode, 23);
10505 wback = BitIsSet (opcode, 21);
10506
Greg Clayton061b79d2011-05-09 20:18:18 +000010507 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice4f605582011-03-31 00:02:51 +000010508 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10509 n = Bits32 (opcode, 19, 16);
10510 imm32 = Bits32 (opcode, 7, 0) << 2;
10511
Greg Clayton061b79d2011-05-09 20:18:18 +000010512 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
Caroline Tice4f605582011-03-31 00:02:51 +000010513 regs = Bits32 (opcode, 7, 0) / 2;
10514
10515 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10516 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10517 return false;
10518
10519 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10520 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10521 return false;
10522
10523 break;
10524
10525 case eEncodingT2:
10526 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010527 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10528 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10529 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10530 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010531 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10532 return false;
10533
10534 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010535 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Tice4f605582011-03-31 00:02:51 +000010536 single_regs = true;
10537 add = BitIsSet (opcode, 23);
10538 wback = BitIsSet (opcode, 21);
10539 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10540 n = Bits32 (opcode, 19, 16);
10541
Greg Clayton061b79d2011-05-09 20:18:18 +000010542 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Tice4f605582011-03-31 00:02:51 +000010543 imm32 = Bits32 (opcode, 7, 0) << 2;
10544 regs = Bits32 (opcode, 7, 0);
10545
10546 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10547 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10548 return false;
10549
10550 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10551 if ((regs == 0) || ((d + regs) > 32))
10552 return false;
10553 break;
10554
10555 default:
10556 return false;
10557 }
10558
Greg Claytonc07d4512011-04-26 23:48:45 +000010559 RegisterInfo base_reg;
10560 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4f605582011-03-31 00:02:51 +000010561
10562 uint32_t Rn = ReadCoreReg (n, &success);
10563 if (!success)
10564 return false;
10565
10566 // address = if add then R[n] else R[n]-imm32;
10567 addr_t address;
10568 if (add)
10569 address = Rn;
10570 else
10571 address = Rn - imm32;
10572
Greg Claytonc07d4512011-04-26 23:48:45 +000010573 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010574 EmulateInstruction::Context context;
10575
10576 if (wback)
10577 {
10578 uint32_t value;
10579 if (add)
10580 value = Rn + imm32;
10581 else
10582 value = Rn - imm32;
10583
10584 context.type = eContextAdjustBaseRegister;
10585 context.SetImmediateSigned (value - Rn);
10586 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10587 return false;
10588
10589 }
10590
10591 const uint32_t addr_byte_size = GetAddressByteSize();
10592 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10593
10594 context.type = eContextRegisterLoad;
10595
10596 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010597 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010598 {
10599 if (single_regs)
10600 {
10601 // S[d+r] = MemA[address,4]; address = address+4;
10602 context.SetRegisterPlusOffset (base_reg, address - Rn);
10603
10604 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10605 if (!success)
10606 return false;
10607
10608 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10609 return false;
10610
10611 address = address + 4;
10612 }
10613 else
10614 {
10615 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10616 context.SetRegisterPlusOffset (base_reg, address - Rn);
10617 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10618 if (!success)
10619 return false;
10620
10621 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10622 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10623 if (!success)
10624 return false;
10625
10626 address = address + 8;
10627 // // Combine the word-aligned words in the correct order for current endianness.
10628 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10629 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010630 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010631 {
10632 data = word1;
10633 data = (data << 32) | word2;
10634 }
10635 else
10636 {
10637 data = word2;
10638 data = (data << 32) | word1;
10639 }
10640
10641 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10642 return false;
10643 }
10644 }
10645 }
10646 return true;
10647}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010648
10649// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010650// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10651// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010652bool
10653EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10654{
10655#if 0
10656 if ConditionPassed() then
10657 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10658 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010659 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010660 for r = 0 to regs-1
10661 if single_regs then
10662 MemA[address,4] = S[d+r]; address = address+4;
10663 else
10664 // Store as two word-aligned words in the correct order for current endianness.
10665 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10666 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10667 address = address+8;
10668#endif
10669
10670 bool success = false;
10671
10672 if (ConditionPassed (opcode))
10673 {
10674 bool single_regs;
10675 bool add;
10676 bool wback;
10677 uint32_t d;
10678 uint32_t n;
10679 uint32_t imm32;
10680 uint32_t regs;
10681
10682 switch (encoding)
10683 {
10684 case eEncodingT1:
10685 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010686 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10687 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10688 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10689 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010690 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10691 return false;
10692
10693 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010694 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010695 single_regs = false;
10696 add = BitIsSet (opcode, 23);
10697 wback = BitIsSet (opcode, 21);
10698
Greg Clayton061b79d2011-05-09 20:18:18 +000010699 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010700 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10701 n = Bits32 (opcode, 19, 16);
10702 imm32 = Bits32 (opcode, 7, 0) << 2;
10703
Greg Clayton061b79d2011-05-09 20:18:18 +000010704 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010705 regs = Bits32 (opcode, 7, 0) / 2;
10706
10707 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10708 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10709 return false;
10710
10711 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10712 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10713 return false;
10714
10715 break;
10716
10717 case eEncodingT2:
10718 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010719 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10720 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10721 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10722 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010723 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10724 return false;
10725
10726 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010727 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010728 single_regs = true;
10729 add = BitIsSet (opcode, 23);
10730 wback = BitIsSet (opcode, 21);
10731 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10732 n = Bits32 (opcode, 19, 16);
10733
Greg Clayton061b79d2011-05-09 20:18:18 +000010734 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010735 imm32 = Bits32 (opcode, 7, 0) << 2;
10736 regs = Bits32 (opcode, 7, 0);
10737
10738 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10739 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10740 return false;
10741
10742 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10743 if ((regs == 0) || ((d + regs) > 32))
10744 return false;
10745
10746 break;
10747
10748 default:
10749 return false;
10750 }
10751
Greg Claytonc07d4512011-04-26 23:48:45 +000010752 RegisterInfo base_reg;
10753 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010754
10755 uint32_t Rn = ReadCoreReg (n, &success);
10756 if (!success)
10757 return false;
10758
10759 // address = if add then R[n] else R[n]-imm32;
10760 addr_t address;
10761 if (add)
10762 address = Rn;
10763 else
10764 address = Rn - imm32;
10765
10766 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +000010767 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010768 if (wback)
10769 {
10770 uint32_t value;
10771 if (add)
10772 value = Rn + imm32;
10773 else
10774 value = Rn - imm32;
10775
10776 context.type = eContextAdjustBaseRegister;
10777 context.SetRegisterPlusOffset (base_reg, value - Rn);
10778
10779 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10780 return false;
10781 }
10782
10783 const uint32_t addr_byte_size = GetAddressByteSize();
10784 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10785
10786 context.type = eContextRegisterStore;
10787 // for r = 0 to regs-1
10788 for (int r = 0; r < regs; ++r)
10789 {
Greg Claytonc07d4512011-04-26 23:48:45 +000010790
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010791 if (single_regs)
10792 {
10793 // MemA[address,4] = S[d+r]; address = address+4;
10794 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10795 if (!success)
10796 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010797
10798 RegisterInfo data_reg;
10799 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010800 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10801 if (!MemAWrite (context, address, data, addr_byte_size))
10802 return false;
10803
10804 address = address + 4;
10805 }
10806 else
10807 {
10808 // // Store as two word-aligned words in the correct order for current endianness.
10809 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10810 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10811 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10812 if (!success)
10813 return false;
10814
Greg Claytonc07d4512011-04-26 23:48:45 +000010815 RegisterInfo data_reg;
10816 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010817
Greg Clayton888a7332011-04-26 04:39:08 +000010818 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010819 {
10820 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10821 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10822 return false;
10823
10824 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10825 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10826 return false;
10827 }
10828 else
10829 {
10830 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10831 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10832 return false;
10833
10834 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10835 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10836 return false;
10837 }
10838 // address = address+8;
10839 address = address + 8;
10840 }
10841 }
10842 }
10843 return true;
10844}
10845
Caroline Tice917ad352011-03-31 05:05:30 +000010846// A8.6.320
10847// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10848// an optional offset.
10849bool
10850EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10851{
10852#if 0
10853 if ConditionPassed() then
10854 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10855 base = if n == 15 then Align(PC,4) else R[n];
10856 address = if add then (base + imm32) else (base - imm32);
10857 if single_reg then
10858 S[d] = MemA[address,4];
10859 else
10860 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10861 // Combine the word-aligned words in the correct order for current endianness.
10862 D[d] = if BigEndian() then word1:word2 else word2:word1;
10863#endif
10864
10865 bool success = false;
10866
10867 if (ConditionPassed (opcode))
10868 {
10869 bool single_reg;
10870 bool add;
10871 uint32_t imm32;
10872 uint32_t d;
10873 uint32_t n;
10874
10875 switch (encoding)
10876 {
10877 case eEncodingT1:
10878 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010879 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010880 single_reg = false;
10881 add = BitIsSet (opcode, 23);
10882 imm32 = Bits32 (opcode, 7, 0) << 2;
10883
10884 // d = UInt(D:Vd); n = UInt(Rn);
10885 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10886 n = Bits32 (opcode, 19, 16);
10887
10888 break;
10889
10890 case eEncodingT2:
10891 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010892 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000010893 single_reg = true;
10894 add = BitIsSet (opcode, 23);
10895 imm32 = Bits32 (opcode, 7, 0) << 2;
10896
10897 // d = UInt(Vd:D); n = UInt(Rn);
10898 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10899 n = Bits32 (opcode, 19, 16);
10900
10901 break;
10902
10903 default:
10904 return false;
10905 }
Greg Claytonc07d4512011-04-26 23:48:45 +000010906 RegisterInfo base_reg;
10907 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice917ad352011-03-31 05:05:30 +000010908
10909 uint32_t Rn = ReadCoreReg (n, &success);
10910 if (!success)
10911 return false;
10912
10913 // base = if n == 15 then Align(PC,4) else R[n];
10914 uint32_t base;
10915 if (n == 15)
10916 base = AlignPC (Rn);
10917 else
10918 base = Rn;
10919
10920 // address = if add then (base + imm32) else (base - imm32);
10921 addr_t address;
10922 if (add)
10923 address = base + imm32;
10924 else
10925 address = base - imm32;
10926
10927 const uint32_t addr_byte_size = GetAddressByteSize();
10928 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
10929
10930 EmulateInstruction::Context context;
10931 context.type = eContextRegisterLoad;
10932 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010933
Caroline Tice917ad352011-03-31 05:05:30 +000010934 if (single_reg)
10935 {
10936 // S[d] = MemA[address,4];
10937 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10938 if (!success)
10939 return false;
10940
10941 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
10942 return false;
10943 }
10944 else
10945 {
10946 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
10947 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10948 if (!success)
10949 return false;
10950
10951 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
10952 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10953 if (!success)
10954 return false;
10955 // // Combine the word-aligned words in the correct order for current endianness.
10956 // D[d] = if BigEndian() then word1:word2 else word2:word1;
10957 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000010958 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000010959 {
10960 data64 = word1;
10961 data64 = (data64 << 32) | word2;
10962 }
10963 else
10964 {
10965 data64 = word2;
10966 data64 = (data64 << 32) | word1;
10967 }
10968
10969 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
10970 return false;
10971 }
10972 }
10973 return true;
10974}
Caroline Tice424652f2011-03-31 05:38:36 +000010975
10976// A8.6.400 VSTR
10977// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
10978// optional offset.
10979bool
10980EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
10981{
10982#if 0
10983 if ConditionPassed() then
10984 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10985 address = if add then (R[n] + imm32) else (R[n] - imm32);
10986 if single_reg then
10987 MemA[address,4] = S[d];
10988 else
10989 // Store as two word-aligned words in the correct order for current endianness.
10990 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
10991 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
10992#endif
10993
10994 bool success = false;
10995
10996 if (ConditionPassed (opcode))
10997 {
10998 bool single_reg;
10999 bool add;
11000 uint32_t imm32;
11001 uint32_t d;
11002 uint32_t n;
11003
11004 switch (encoding)
11005 {
11006 case eEncodingT1:
11007 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011008 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011009 single_reg = false;
11010 add = BitIsSet (opcode, 23);
11011 imm32 = Bits32 (opcode, 7, 0) << 2;
11012
11013 // d = UInt(D:Vd); n = UInt(Rn);
11014 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11015 n = Bits32 (opcode, 19, 16);
11016
11017 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11018 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11019 return false;
11020
11021 break;
11022
11023 case eEncodingT2:
11024 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011025 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011026 single_reg = true;
11027 add = BitIsSet (opcode, 23);
11028 imm32 = Bits32 (opcode, 7, 0) << 2;
11029
11030 // d = UInt(Vd:D); n = UInt(Rn);
11031 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11032 n = Bits32 (opcode, 19, 16);
11033
11034 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11035 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11036 return false;
11037
11038 break;
11039
11040 default:
11041 return false;
11042 }
11043
Greg Claytonc07d4512011-04-26 23:48:45 +000011044 RegisterInfo base_reg;
11045 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011046
11047 uint32_t Rn = ReadCoreReg (n, &success);
11048 if (!success)
11049 return false;
11050
11051 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11052 addr_t address;
11053 if (add)
11054 address = Rn + imm32;
11055 else
11056 address = Rn - imm32;
11057
11058 const uint32_t addr_byte_size = GetAddressByteSize();
11059 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11060
Greg Claytonc07d4512011-04-26 23:48:45 +000011061 RegisterInfo data_reg;
11062 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011063 EmulateInstruction::Context context;
11064 context.type = eContextRegisterStore;
11065 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11066
11067 if (single_reg)
11068 {
11069 // MemA[address,4] = S[d];
11070 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11071 if (!success)
11072 return false;
11073
11074 if (!MemAWrite (context, address, data, addr_byte_size))
11075 return false;
11076 }
11077 else
11078 {
11079 // // Store as two word-aligned words in the correct order for current endianness.
11080 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11081 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11082 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11083 if (!success)
11084 return false;
11085
Greg Clayton888a7332011-04-26 04:39:08 +000011086 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011087 {
11088 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11089 return false;
11090
11091 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11092 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11093 return false;
11094 }
11095 else
11096 {
11097 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11098 return false;
11099
11100 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11101 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11102 return false;
11103 }
11104 }
11105 }
11106 return true;
11107}
Caroline Tice9121b352011-03-31 16:41:19 +000011108
11109// A8.6.307 VLDI1 (multiple single elements)
11110// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11111// element of each register is loaded.
11112bool
11113EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11114{
11115#if 0
11116 if ConditionPassed() then
11117 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11118 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11119 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11120 for r = 0 to regs-1
11121 for e = 0 to elements-1
11122 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11123 address = address + ebytes;
11124#endif
11125
11126 bool success = false;
11127
11128 if (ConditionPassed (opcode))
11129 {
11130 uint32_t regs;
11131 uint32_t alignment;
11132 uint32_t ebytes;
11133 uint32_t esize;
11134 uint32_t elements;
11135 uint32_t d;
11136 uint32_t n;
11137 uint32_t m;
11138 bool wback;
11139 bool register_index;
11140
11141 switch (encoding)
11142 {
11143 case eEncodingT1:
11144 case eEncodingA1:
11145 {
11146 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011147 // when Ô0111Õ
11148 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
11149 // when Ô1010Õ
11150 // regs = 2; if align == Ô11Õ then UNDEFINED;
11151 // when Ô0110Õ
11152 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
11153 // when Ô0010Õ
Caroline Tice9121b352011-03-31 16:41:19 +000011154 // regs = 4;
11155 // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011156 // SEE ÒRelated encodingsÓ;
Caroline Tice9121b352011-03-31 16:41:19 +000011157 uint32_t type = Bits32 (opcode, 11, 8);
11158 uint32_t align = Bits32 (opcode, 5, 4);
11159 if (type == 7) // '0111'
11160 {
11161 regs = 1;
11162 if (BitIsSet (align, 1))
11163 return false;
11164 }
11165 else if (type == 10) // '1010'
11166 {
11167 regs = 2;
11168 if (align == 3)
11169 return false;
11170
11171 }
11172 else if (type == 6) // '0110'
11173 {
11174 regs = 3;
11175 if (BitIsSet (align, 1))
11176 return false;
11177 }
11178 else if (type == 2) // '0010'
11179 {
11180 regs = 4;
11181 }
11182 else
11183 return false;
11184
Greg Clayton061b79d2011-05-09 20:18:18 +000011185 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice9121b352011-03-31 16:41:19 +000011186 if (align == 0)
11187 alignment = 1;
11188 else
11189 alignment = 4 << align;
11190
11191 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11192 ebytes = 1 << Bits32 (opcode, 7, 6);
11193 esize = 8 * ebytes;
11194 elements = 8 / ebytes;
11195
11196 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11197 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11198 n = Bits32 (opcode, 19, 15);
11199 m = Bits32 (opcode, 3, 0);
11200
11201 // wback = (m != 15); register_index = (m != 15 && m != 13);
11202 wback = (m != 15);
11203 register_index = ((m != 15) && (m != 13));
11204
11205 // if d+regs > 32 then UNPREDICTABLE;
11206 if ((d + regs) > 32)
11207 return false;
11208 }
11209 break;
11210
11211 default:
11212 return false;
11213 }
11214
Greg Claytonc07d4512011-04-26 23:48:45 +000011215 RegisterInfo base_reg;
11216 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice9121b352011-03-31 16:41:19 +000011217
11218 uint32_t Rn = ReadCoreReg (n, &success);
11219 if (!success)
11220 return false;
11221
11222 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11223 addr_t address = Rn;
11224 if ((address % alignment) != 0)
11225 return false;
11226
11227 EmulateInstruction::Context context;
11228 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11229 if (wback)
11230 {
11231 uint32_t Rm = ReadCoreReg (m, &success);
11232 if (!success)
11233 return false;
11234
11235 uint32_t offset;
11236 if (register_index)
11237 offset = Rm;
11238 else
11239 offset = 8 * regs;
11240
11241 uint32_t value = Rn + offset;
11242 context.type = eContextAdjustBaseRegister;
11243 context.SetRegisterPlusOffset (base_reg, offset);
11244
11245 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11246 return false;
11247
11248 }
11249
11250 // for r = 0 to regs-1
11251 for (int r = 0; r < regs; ++r)
11252 {
11253 // for e = 0 to elements-1
11254 uint64_t assembled_data = 0;
11255 for (int e = 0; e < elements; ++e)
11256 {
11257 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11258 context.type = eContextRegisterLoad;
11259 context.SetRegisterPlusOffset (base_reg, address - Rn);
11260 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11261 if (!success)
11262 return false;
11263
11264 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11265
11266 // address = address + ebytes;
11267 address = address + ebytes;
11268 }
11269 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11270 return false;
11271 }
11272 }
11273 return true;
11274}
11275
Caroline Ticeb6281b12011-03-31 17:58:23 +000011276// A8.6.308 VLD1 (single element to one lane)
11277//
11278bool
11279EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11280{
11281#if 0
11282 if ConditionPassed() then
11283 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11284 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11285 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11286 Elem[D[d],index,esize] = MemU[address,ebytes];
11287#endif
11288
11289 bool success = false;
11290
11291 if (ConditionPassed (opcode))
11292 {
11293 uint32_t ebytes;
11294 uint32_t esize;
11295 uint32_t index;
11296 uint32_t alignment;
11297 uint32_t d;
11298 uint32_t n;
11299 uint32_t m;
11300 bool wback;
11301 bool register_index;
11302
11303 switch (encoding)
11304 {
11305 case eEncodingT1:
11306 case eEncodingA1:
11307 {
11308 uint32_t size = Bits32 (opcode, 11, 10);
11309 uint32_t index_align = Bits32 (opcode, 7, 4);
Greg Clayton061b79d2011-05-09 20:18:18 +000011310 // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011311 if (size == 3)
11312 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011313 // case size of
11314 if (size == 0) // when '00'
11315 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011316 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011317 if (BitIsClear (index_align, 0))
11318 return false;
11319
11320 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11321 ebytes = 1;
11322 esize = 8;
11323 index = Bits32 (index_align, 3, 1);
11324 alignment = 1;
11325 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011326 else if (size == 1) // when Ô01Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011327 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011328 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011329 if (BitIsClear (index_align, 1))
11330 return false;
11331
11332 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11333 ebytes = 2;
11334 esize = 16;
11335 index = Bits32 (index_align, 3, 2);
11336
Greg Clayton061b79d2011-05-09 20:18:18 +000011337 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011338 if (BitIsClear (index_align, 0))
11339 alignment = 1;
11340 else
11341 alignment = 2;
11342 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011343 else if (size == 2) // when Ô10Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011344 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011345 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011346 if (BitIsClear (index_align, 2))
11347 return false;
11348
Greg Clayton061b79d2011-05-09 20:18:18 +000011349 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011350 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11351 return false;
11352
11353 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11354 ebytes = 4;
11355 esize = 32;
11356 index = Bit32 (index_align, 3);
11357
Greg Clayton061b79d2011-05-09 20:18:18 +000011358 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011359 if (Bits32 (index_align, 1, 0) == 0)
11360 alignment = 1;
11361 else
11362 alignment = 4;
11363 }
11364 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11365 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11366 n = Bits32 (opcode, 19, 16);
11367 m = Bits32 (opcode, 3, 0);
11368
11369 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11370 wback = (m != 15);
11371 register_index = ((m != 15) && (m != 13));
11372
11373 if (n == 15)
11374 return false;
11375
11376 }
11377 break;
11378
11379 default:
11380 return false;
11381 }
11382
Greg Claytonc07d4512011-04-26 23:48:45 +000011383 RegisterInfo base_reg;
11384 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011385
11386 uint32_t Rn = ReadCoreReg (n, &success);
11387 if (!success)
11388 return false;
11389
11390 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11391 addr_t address = Rn;
11392 if ((address % alignment) != 0)
11393 return false;
11394
11395 EmulateInstruction::Context context;
11396 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11397 if (wback)
11398 {
11399 uint32_t Rm = ReadCoreReg (m, &success);
11400 if (!success)
11401 return false;
11402
11403 uint32_t offset;
11404 if (register_index)
11405 offset = Rm;
11406 else
11407 offset = ebytes;
11408
11409 uint32_t value = Rn + offset;
11410
11411 context.type = eContextAdjustBaseRegister;
11412 context.SetRegisterPlusOffset (base_reg, offset);
11413
11414 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11415 return false;
11416 }
11417
11418 // Elem[D[d],index,esize] = MemU[address,ebytes];
11419 uint32_t element = MemURead (context, address, esize, 0, &success);
11420 if (!success)
11421 return false;
11422
11423 element = element << (index * esize);
11424
11425 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11426 if (!success)
11427 return false;
11428
11429 uint64_t all_ones = -1;
11430 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11431 // at element & to the right of element.
11432 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011433 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 +000011434 // now mask should be 0's where element goes & 1's
11435 // everywhere else.
11436
11437 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11438 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11439
11440 context.type = eContextRegisterLoad;
11441 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11442 return false;
11443 }
11444 return true;
11445}
11446
Caroline Tice1e542e32011-03-31 18:44:04 +000011447// A8.6.391 VST1 (multiple single elements)
11448// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11449// interleaving. Every element of each register is stored.
11450bool
11451EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11452{
11453#if 0
11454 if ConditionPassed() then
11455 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11456 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11457 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11458 for r = 0 to regs-1
11459 for e = 0 to elements-1
11460 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11461 address = address + ebytes;
11462#endif
11463
11464 bool success = false;
11465
11466 if (ConditionPassed (opcode))
11467 {
11468 uint32_t regs;
11469 uint32_t alignment;
11470 uint32_t ebytes;
11471 uint32_t esize;
11472 uint32_t elements;
11473 uint32_t d;
11474 uint32_t n;
11475 uint32_t m;
11476 bool wback;
11477 bool register_index;
11478
11479 switch (encoding)
11480 {
11481 case eEncodingT1:
11482 case eEncodingA1:
11483 {
11484 uint32_t type = Bits32 (opcode, 11, 8);
11485 uint32_t align = Bits32 (opcode, 5, 4);
11486
11487 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011488 if (type == 7) // when Ô0111Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011489 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011490 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011491 regs = 1;
11492 if (BitIsSet (align, 1))
11493 return false;
11494 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011495 else if (type == 10) // when Ô1010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011496 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011497 // regs = 2; if align == Ô11Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011498 regs = 2;
11499 if (align == 3)
11500 return false;
11501 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011502 else if (type == 6) // when Ô0110Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011503 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011504 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011505 regs = 3;
11506 if (BitIsSet (align, 1))
11507 return false;
11508 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011509 else if (type == 2) // when Ô0010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011510 // regs = 4;
11511 regs = 4;
11512 else // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011513 // SEE ÒRelated encodingsÓ;
Caroline Tice1e542e32011-03-31 18:44:04 +000011514 return false;
11515
Greg Clayton061b79d2011-05-09 20:18:18 +000011516 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice1e542e32011-03-31 18:44:04 +000011517 if (align == 0)
11518 alignment = 0;
11519 else
11520 alignment = 4 << align;
11521
11522 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11523 ebytes = 1 << Bits32 (opcode,7, 6);
11524 esize = 8 * ebytes;
11525 elements = 8 / ebytes;
11526
11527 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11528 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11529 n = Bits32 (opcode, 19, 16);
11530 m = Bits32 (opcode, 3, 0);
11531
11532 // wback = (m != 15); register_index = (m != 15 && m != 13);
11533 wback = (m != 15);
11534 register_index = ((m != 15) && (m != 13));
11535
11536 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11537 if ((d + regs) > 32)
11538 return false;
11539
11540 if (n == 15)
11541 return false;
11542
11543 }
11544 break;
11545
11546 default:
11547 return false;
11548 }
11549
Greg Claytonc07d4512011-04-26 23:48:45 +000011550 RegisterInfo base_reg;
11551 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011552
11553 uint32_t Rn = ReadCoreReg (n, &success);
11554 if (!success)
11555 return false;
11556
11557 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11558 addr_t address = Rn;
11559 if ((address % alignment) != 0)
11560 return false;
11561
11562 EmulateInstruction::Context context;
11563 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11564 if (wback)
11565 {
11566 uint32_t Rm = ReadCoreReg (m, &success);
11567 if (!success)
11568 return false;
11569
11570 uint32_t offset;
11571 if (register_index)
11572 offset = Rm;
11573 else
11574 offset = 8 * regs;
11575
11576 context.type = eContextAdjustBaseRegister;
11577 context.SetRegisterPlusOffset (base_reg, offset);
11578
11579 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11580 return false;
11581 }
11582
Greg Claytonc07d4512011-04-26 23:48:45 +000011583 RegisterInfo data_reg;
Caroline Tice1e542e32011-03-31 18:44:04 +000011584 context.type = eContextRegisterStore;
Caroline Tice1e542e32011-03-31 18:44:04 +000011585 // for r = 0 to regs-1
11586 for (int r = 0; r < regs; ++r)
11587 {
Greg Claytonc07d4512011-04-26 23:48:45 +000011588 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011589 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11590 if (!success)
11591 return false;
11592
11593 // for e = 0 to elements-1
11594 for (int e = 0; e < elements; ++e)
11595 {
11596 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011597 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011598
11599 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11600 if (!MemUWrite (context, address, word, ebytes))
11601 return false;
11602
11603 // address = address + ebytes;
11604 address = address + ebytes;
11605 }
11606 }
11607 }
11608 return true;
11609}
11610
Caroline Tice7b880942011-03-31 19:17:12 +000011611// A8.6.392 VST1 (single element from one lane)
11612// This instruction stores one element to memory from one element of a register.
11613bool
11614EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11615{
11616#if 0
11617 if ConditionPassed() then
11618 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11619 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11620 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11621 MemU[address,ebytes] = Elem[D[d],index,esize];
11622#endif
11623
11624 bool success = false;
11625
11626 if (ConditionPassed (opcode))
11627 {
11628 uint32_t ebytes;
11629 uint32_t esize;
11630 uint32_t index;
11631 uint32_t alignment;
11632 uint32_t d;
11633 uint32_t n;
11634 uint32_t m;
11635 bool wback;
11636 bool register_index;
11637
11638 switch (encoding)
11639 {
11640 case eEncodingT1:
11641 case eEncodingA1:
11642 {
11643 uint32_t size = Bits32 (opcode, 11, 10);
11644 uint32_t index_align = Bits32 (opcode, 7, 4);
11645
Greg Clayton061b79d2011-05-09 20:18:18 +000011646 // if size == Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011647 if (size == 3)
11648 return false;
11649
11650 // case size of
Greg Clayton061b79d2011-05-09 20:18:18 +000011651 if (size == 0) // when Ô00Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011652 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011653 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011654 if (BitIsClear (index_align, 0))
11655 return false;
11656 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11657 ebytes = 1;
11658 esize = 8;
11659 index = Bits32 (index_align, 3, 1);
11660 alignment = 1;
11661 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011662 else if (size == 1) // when Ô01Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011663 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011664 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011665 if (BitIsClear (index_align, 1))
11666 return false;
11667
11668 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11669 ebytes = 2;
11670 esize = 16;
11671 index = Bits32 (index_align, 3, 2);
11672
Greg Clayton061b79d2011-05-09 20:18:18 +000011673 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Tice7b880942011-03-31 19:17:12 +000011674 if (BitIsClear (index_align, 0))
11675 alignment = 1;
11676 else
11677 alignment = 2;
11678 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011679 else if (size == 2) // when Ô10Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011680 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011681 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011682 if (BitIsClear (index_align, 2))
11683 return false;
11684
Greg Clayton061b79d2011-05-09 20:18:18 +000011685 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011686 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11687 return false;
11688
11689 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11690 ebytes = 4;
11691 esize = 32;
11692 index = Bit32 (index_align, 3);
11693
Greg Clayton061b79d2011-05-09 20:18:18 +000011694 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Tice7b880942011-03-31 19:17:12 +000011695 if (Bits32 (index_align, 1, 0) == 0)
11696 alignment = 1;
11697 else
11698 alignment = 4;
11699 }
11700 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11701 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11702 n = Bits32 (opcode, 19, 16);
11703 m = Bits32 (opcode, 3, 0);
11704
11705 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11706 wback = (m != 15);
11707 register_index = ((m != 15) && (m != 13));
11708
11709 if (n == 15)
11710 return false;
11711 }
11712 break;
11713
11714 default:
11715 return false;
11716 }
11717
Greg Claytonc07d4512011-04-26 23:48:45 +000011718 RegisterInfo base_reg;
11719 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011720
11721 uint32_t Rn = ReadCoreReg (n, &success);
11722 if (!success)
11723 return false;
11724
11725 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11726 addr_t address = Rn;
11727 if ((address % alignment) != 0)
11728 return false;
11729
11730 EmulateInstruction::Context context;
11731 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11732 if (wback)
11733 {
11734 uint32_t Rm = ReadCoreReg (m, &success);
11735 if (!success)
11736 return false;
11737
11738 uint32_t offset;
11739 if (register_index)
11740 offset = Rm;
11741 else
11742 offset = ebytes;
11743
11744 context.type = eContextAdjustBaseRegister;
11745 context.SetRegisterPlusOffset (base_reg, offset);
11746
11747 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11748 return false;
11749 }
11750
11751 // MemU[address,ebytes] = Elem[D[d],index,esize];
11752 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11753 if (!success)
11754 return false;
11755
11756 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11757
Greg Claytonc07d4512011-04-26 23:48:45 +000011758 RegisterInfo data_reg;
11759 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011760 context.type = eContextRegisterStore;
11761 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11762
11763 if (!MemUWrite (context, address, word, ebytes))
11764 return false;
11765 }
11766 return true;
11767}
11768
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011769// A8.6.309 VLD1 (single element to all lanes)
11770// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011771bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011772EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011773{
11774#if 0
11775 if ConditionPassed() then
11776 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11777 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11778 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11779 replicated_element = Replicate(MemU[address,ebytes], elements);
11780 for r = 0 to regs-1
11781 D[d+r] = replicated_element;
11782#endif
11783
11784 bool success = false;
11785
11786 if (ConditionPassed (opcode))
11787 {
11788 uint32_t ebytes;
11789 uint32_t elements;
11790 uint32_t regs;
11791 uint32_t alignment;
11792 uint32_t d;
11793 uint32_t n;
11794 uint32_t m;
11795 bool wback;
11796 bool register_index;
11797
11798 switch (encoding)
11799 {
11800 case eEncodingT1:
11801 case eEncodingA1:
11802 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011803 //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
Caroline Tice93767b82011-03-31 21:15:29 +000011804 uint32_t size = Bits32 (opcode, 7, 6);
11805 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11806 return false;
11807
Greg Clayton061b79d2011-05-09 20:18:18 +000011808 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
Caroline Tice93767b82011-03-31 21:15:29 +000011809 ebytes = 1 << size;
11810 elements = 8 / ebytes;
11811 if (BitIsClear (opcode, 5))
11812 regs = 1;
11813 else
11814 regs = 2;
11815
Greg Clayton061b79d2011-05-09 20:18:18 +000011816 //alignment = if a == Ô0Õ then 1 else ebytes;
Caroline Tice93767b82011-03-31 21:15:29 +000011817 if (BitIsClear (opcode, 4))
11818 alignment = 1;
11819 else
11820 alignment = ebytes;
11821
11822 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11823 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11824 n = Bits32 (opcode, 19, 16);
11825 m = Bits32 (opcode, 3, 0);
11826
11827 //wback = (m != 15); register_index = (m != 15 && m != 13);
11828 wback = (m != 15);
11829 register_index = ((m != 15) && (m != 13));
11830
11831 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11832 if ((d + regs) > 32)
11833 return false;
11834
11835 if (n == 15)
11836 return false;
11837 }
11838 break;
11839
11840 default:
11841 break;
11842 }
11843
Greg Claytonc07d4512011-04-26 23:48:45 +000011844 RegisterInfo base_reg;
11845 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice93767b82011-03-31 21:15:29 +000011846
11847 uint32_t Rn = ReadCoreReg (n, &success);
11848 if (!success)
11849 return false;
11850
11851 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11852 addr_t address = Rn;
11853 if ((address % alignment) != 0)
11854 return false;
11855
11856 EmulateInstruction::Context context;
11857 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11858 if (wback)
11859 {
11860 uint32_t Rm = ReadCoreReg (m, &success);
11861 if (!success)
11862 return false;
11863
11864 uint32_t offset;
11865 if (register_index)
11866 offset = Rm;
11867 else
11868 offset = ebytes;
11869
11870 context.type = eContextAdjustBaseRegister;
11871 context.SetRegisterPlusOffset (base_reg, offset);
11872
11873 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11874 return false;
11875 }
11876
11877 // replicated_element = Replicate(MemU[address,ebytes], elements);
11878
11879 context.type = eContextRegisterLoad;
11880 uint64_t word = MemURead (context, address, ebytes, 0, &success);
11881 if (!success)
11882 return false;
11883
11884 uint64_t replicated_element;
11885 uint32_t esize = ebytes * 8;
11886 for (int e = 0; e < elements; ++e)
11887 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
11888
11889 // for r = 0 to regs-1
11890 for (int r = 0; r < regs; ++r)
11891 {
11892 // D[d+r] = replicated_element;
11893 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
11894 return false;
11895 }
11896 }
11897 return true;
11898}
11899
Caroline Tice1f954f52011-04-11 15:51:10 +000011900// B6.2.13 SUBS PC, LR and related instructions
11901//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
11902// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
11903bool
11904EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
11905{
11906#if 0
11907 if ConditionPassed() then
11908 EncodingSpecificOperations();
11909 if CurrentInstrSet() == InstrSet_ThumbEE then
11910 UNPREDICTABLE;
11911 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11912 case opcode of
Greg Clayton061b79d2011-05-09 20:18:18 +000011913 when Ô0000Õ result = R[n] AND operand2; // AND
11914 when Ô0001Õ result = R[n] EOR operand2; // EOR
11915 when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
11916 when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
11917 when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
11918 when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
11919 when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
11920 when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
11921 when Ô1100Õ result = R[n] OR operand2; // ORR
11922 when Ô1101Õ result = operand2; // MOV
11923 when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
11924 when Ô1111Õ result = NOT(operand2); // MVN
11925 CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000011926 BranchWritePC(result);
11927#endif
11928
11929 bool success = false;
11930
11931 if (ConditionPassed (opcode))
11932 {
11933 uint32_t n;
11934 uint32_t m;
11935 uint32_t imm32;
11936 bool register_form;
11937 ARM_ShifterType shift_t;
11938 uint32_t shift_n;
11939 uint32_t code;
11940
11941 switch (encoding)
11942 {
11943 case eEncodingT1:
11944 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
Greg Clayton061b79d2011-05-09 20:18:18 +000011945 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000011946 n = 14;
11947 imm32 = Bits32 (opcode, 7, 0);
11948 register_form = false;
11949 code = 2;
11950
11951 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
11952 if (InITBlock() && !LastInITBlock())
11953 return false;
11954
11955 break;
11956
11957 case eEncodingA1:
11958 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
11959 n = Bits32 (opcode, 19, 16);
11960 imm32 = ARMExpandImm (opcode);
11961 register_form = false;
11962 code = Bits32 (opcode, 24, 21);
11963
11964 break;
11965
11966 case eEncodingA2:
11967 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
11968 n = Bits32 (opcode, 19, 16);
11969 m = Bits32 (opcode, 3, 0);
11970 register_form = true;
11971
11972 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
11973 shift_n = DecodeImmShiftARM (opcode, shift_t);
11974
11975 break;
11976
11977 default:
11978 return false;
11979 }
11980
11981 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
11982 uint32_t operand2;
11983 if (register_form)
11984 {
11985 uint32_t Rm = ReadCoreReg (m, &success);
11986 if (!success)
11987 return false;
11988
11989 operand2 = Shift (Rm, shift_t, shift_n, APSR_C);
11990
11991 }
11992 else
11993 {
11994 operand2 = imm32;
11995 }
11996
11997 uint32_t Rn = ReadCoreReg (n, &success);
11998 if (!success)
11999 return false;
12000
12001 AddWithCarryResult result;
12002
12003 // case opcode of
12004 switch (code)
12005 {
Greg Clayton061b79d2011-05-09 20:18:18 +000012006 case 0: // when Ô0000Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012007 // result = R[n] AND operand2; // AND
12008 result.result = Rn & operand2;
12009 break;
12010
Greg Clayton061b79d2011-05-09 20:18:18 +000012011 case 1: // when Ô0001Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012012 // result = R[n] EOR operand2; // EOR
12013 result.result = Rn ^ operand2;
12014 break;
12015
Greg Clayton061b79d2011-05-09 20:18:18 +000012016 case 2: // when Ô0010Õ
12017 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012018 result = AddWithCarry (Rn, ~(operand2), 1);
12019 break;
12020
Greg Clayton061b79d2011-05-09 20:18:18 +000012021 case 3: // when Ô0011Õ
12022 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
Caroline Tice1f954f52011-04-11 15:51:10 +000012023 result = AddWithCarry (~(Rn), operand2, 1);
12024 break;
12025
Greg Clayton061b79d2011-05-09 20:18:18 +000012026 case 4: // when Ô0100Õ
12027 // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
Caroline Tice1f954f52011-04-11 15:51:10 +000012028 result = AddWithCarry (Rn, operand2, 0);
12029 break;
12030
Greg Clayton061b79d2011-05-09 20:18:18 +000012031 case 5: // when Ô0101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012032 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12033 result = AddWithCarry (Rn, operand2, APSR_C);
12034 break;
12035
Greg Clayton061b79d2011-05-09 20:18:18 +000012036 case 6: // when Ô0110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012037 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12038 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12039 break;
12040
Greg Clayton061b79d2011-05-09 20:18:18 +000012041 case 7: // when Ô0111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012042 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12043 result = AddWithCarry (~(Rn), operand2, APSR_C);
12044 break;
12045
Greg Clayton061b79d2011-05-09 20:18:18 +000012046 case 10: // when Ô1100Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012047 // result = R[n] OR operand2; // ORR
12048 result.result = Rn | operand2;
12049 break;
12050
Greg Clayton061b79d2011-05-09 20:18:18 +000012051 case 11: // when Ô1101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012052 // result = operand2; // MOV
12053 result.result = operand2;
12054 break;
12055
Greg Clayton061b79d2011-05-09 20:18:18 +000012056 case 12: // when Ô1110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012057 // result = R[n] AND NOT(operand2); // BIC
12058 result.result = Rn & ~(operand2);
12059 break;
12060
Greg Clayton061b79d2011-05-09 20:18:18 +000012061 case 15: // when Ô1111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012062 // result = NOT(operand2); // MVN
12063 result.result = ~(operand2);
12064 break;
12065
12066 default:
12067 return false;
12068 }
Greg Clayton061b79d2011-05-09 20:18:18 +000012069 // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012070
12071 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12072 // the best.
12073 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12074 if (!success)
12075 return false;
12076
12077 CPSRWriteByInstr (spsr, 15, true);
12078
12079 // BranchWritePC(result);
12080 EmulateInstruction::Context context;
12081 context.type = eContextAdjustPC;
12082 context.SetImmediate (result.result);
12083
12084 BranchWritePC (context, result.result);
12085 }
12086 return true;
12087}
12088
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012089EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012090EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012091{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012092 static ARMOpcode
12093 g_arm_opcodes[] =
12094 {
12095 //----------------------------------------------------------------------
12096 // Prologue instructions
12097 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012098
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012099 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012100 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12101 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012102
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012103 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012104 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12105 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012106 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012107 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12108 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12109 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012110
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012111 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012112 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12113 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012114
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012115 // push one register
12116 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012117 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012118
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012119 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012120 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12121 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012122
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012123 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012124 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012125 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012126
Caroline Tice4f605582011-03-31 00:02:51 +000012127 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12128 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12129 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12130 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012131
12132 //----------------------------------------------------------------------
12133 // Supervisor Call (previously Software Interrupt)
12134 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012135 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012136
12137 //----------------------------------------------------------------------
12138 // Branch instructions
12139 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012140 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012141 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012142 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12143 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12144 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012145 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012146 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012147 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012148 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012149
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012150 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012151 // Data-processing instructions
12152 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012153 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012154 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012155 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012156 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012157 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012158 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012159 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012160 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012161 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012162 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012163 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012164 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12165 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012166 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012167 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012168 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012169 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012170 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012171 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012172 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012173 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012174 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012175 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012176 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012177 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012178 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012179 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012180 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012181 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012182 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012183 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012184 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012185 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012186 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012187 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012188 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012189 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012190 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012191 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012192 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012193 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012194 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012195 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012196 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012197 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012198 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012199 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012200 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012201 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012202 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012203 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012204 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012205 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012206 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012207 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012208
Caroline Tice89c6d582011-03-29 19:53:44 +000012209 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012210 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12211 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012212 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012213 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012214 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012215 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012216 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012217 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012218 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012219 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012220 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012221 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012222 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012223 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012224 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012225 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012226 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012227 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012228 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012229 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012230 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012231 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012232 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012233 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012234 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012235 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012236 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012237 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012238 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012239 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012240 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012241 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012242 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012243 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012244 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012245 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012246
12247 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012248 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12249 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012250
12251 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012252 // Load instructions
12253 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012254 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12255 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12256 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12257 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12258 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12259 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12260 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12261 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12262 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12263 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12264 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12265 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12266 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12267 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12268 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12269 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12270 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12271 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012272 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12273 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12274 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12275 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012276 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12277 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012278 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012279
12280 //----------------------------------------------------------------------
12281 // Store instructions
12282 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012283 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12284 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12285 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12286 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12287 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12288 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12289 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12290 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12291 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012292 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012293 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012294 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12295 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12296 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12297 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12298 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012299 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012300
Caroline Tice6bf65162011-03-03 17:42:58 +000012301 //----------------------------------------------------------------------
12302 // Other instructions
12303 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012304 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12305 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12306 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12307 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12308 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012309
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012310 };
12311 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12312
12313 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12314 {
Greg Clayton888a7332011-04-26 04:39:08 +000012315 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12316 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012317 return &g_arm_opcodes[i];
12318 }
12319 return NULL;
12320}
Greg Clayton64c84432011-01-21 22:02:52 +000012321
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012322
12323EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012324EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012325{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012326
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012327 static ARMOpcode
12328 g_thumb_opcodes[] =
12329 {
12330 //----------------------------------------------------------------------
12331 // Prologue instructions
12332 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012333
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012334 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012335 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12336 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12337 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012338
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012339 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012340 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012341 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012342 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012343 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012344 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012345
Johnny Chen864a8e82011-02-18 00:07:39 +000012346 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012347 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012348
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012349 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012350 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12351 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12352 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12353 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12354 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012355
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012356 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012357 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12358 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012359
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012360 //----------------------------------------------------------------------
12361 // Epilogue instructions
12362 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012363
Caroline Tice4f605582011-03-31 00:02:51 +000012364 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12365 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12366 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12367 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12368 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12369 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12370 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012371
12372 //----------------------------------------------------------------------
12373 // Supervisor Call (previously Software Interrupt)
12374 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012375 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012376
12377 //----------------------------------------------------------------------
12378 // If Then makes up to four following instructions conditional.
12379 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012380 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012381
12382 //----------------------------------------------------------------------
12383 // Branch instructions
12384 //----------------------------------------------------------------------
12385 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012386 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12387 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12388 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12389 { 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 +000012390 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012391 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012392 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012393 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12394 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012395 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012396 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012397 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012398 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012399 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012400 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012401 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012402 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012403 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012404 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012405
12406 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012407 // Data-processing instructions
12408 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012409 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012410 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012411 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012412 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12413 { 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 +000012414 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012415 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012416 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012417 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012418 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012419 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12420 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12421 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012422 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012423 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012424 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012425 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12426 { 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 +000012427 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012428 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012429 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012430 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12431 { 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 +000012432 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012433 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012434 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012435 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12436 { 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 +000012437 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012438 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012439 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012440 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12441 { 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 +000012442 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012443 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12444 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012445 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012446 { 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 +000012447 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012448 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012449 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012450 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12451 { 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 +000012452 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012453 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12454 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12455 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12456 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012457 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012458 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12459 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12460 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12461 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012462 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012463 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12464 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012465 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012466 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12467 { 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 +000012468 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012469 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012470 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012471 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012472 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012473 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012474 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012475 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12476 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012477
Johnny Chen7c5234d2011-02-18 23:41:11 +000012478
Johnny Chen338bf542011-02-10 19:29:03 +000012479 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012480 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012481 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012482 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012483 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012484 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012485 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012486 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12487 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12488 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012489 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012490 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012491 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012492 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12493 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012494 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012495 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012496 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012497 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12498 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012499 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012500 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12501 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012502 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012503 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012504 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012505 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012506 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012507 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12508 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012509 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012510 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12511 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012512 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012513 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12514 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012515 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012516 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12517 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012518 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012519 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12520 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012521 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012522 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12523 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012524 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012525 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012526 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012527 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012528 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012529 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12530 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012531 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012532 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012533 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012534 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012535
12536 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012537 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012538
12539 //----------------------------------------------------------------------
12540 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12541 // otherwise the wrong instructions will be selected.
12542 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012543
Caroline Tice080bf612011-04-05 18:46:00 +000012544 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12545 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12546
Johnny Chen26863dc2011-02-09 23:43:29 +000012547 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012548 // Load instructions
12549 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012550 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12551 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12552 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12553 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12554 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12555 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12556 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012557 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012558 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12559 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12560 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12561 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12562 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012563 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012564 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12565 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12566 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12567 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12568 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12569 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12570 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12571 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12572 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12573 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12574 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12575 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12576 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12577 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12578 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12579 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12580 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12581 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12582 { 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 +000012583 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012584 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12585 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12586 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12587 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012588 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12589 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012590 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012591
12592 //----------------------------------------------------------------------
12593 // Store instructions
12594 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012595 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12596 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12597 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12598 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12599 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12600 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12601 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12602 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12603 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12604 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12605 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12606 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12607 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12608 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12609 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12610 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012611 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12612 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12613 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12614 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12615 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012616 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012617
12618 //----------------------------------------------------------------------
12619 // Other instructions
12620 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012621 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12622 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12623 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12624 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12625 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12626 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12627 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12628 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012629 };
12630
12631 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12632 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12633 {
Greg Clayton888a7332011-04-26 04:39:08 +000012634 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12635 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012636 return &g_thumb_opcodes[i];
12637 }
12638 return NULL;
12639}
Greg Clayton64c84432011-01-21 22:02:52 +000012640
Greg Clayton31e2a382011-01-30 20:03:56 +000012641bool
Greg Clayton395fc332011-02-15 21:59:32 +000012642EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012643{
Caroline Tice080bf612011-04-05 18:46:00 +000012644 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012645 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012646 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012647 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012648 {
Greg Clayton395fc332011-02-15 21:59:32 +000012649 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12650 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12651 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12652 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12653 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12654 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12655 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12656 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12657 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12658 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Johnny Chen1d29a852011-04-26 18:51:57 +000012659 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12660 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
Greg Clayton31e2a382011-01-30 20:03:56 +000012661 }
12662 return m_arm_isa != 0;
12663}
12664
Caroline Tice080bf612011-04-05 18:46:00 +000012665bool
Greg Clayton888a7332011-04-26 04:39:08 +000012666EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012667{
Greg Clayton888a7332011-04-26 04:39:08 +000012668 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12669 {
12670 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12671 m_opcode_mode = eModeThumb;
12672 else
12673 {
12674 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012675
Greg Clayton888a7332011-04-26 04:39:08 +000012676 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12677 m_opcode_mode = eModeARM;
12678 else if (addr_class == eAddressClassCodeAlternateISA)
12679 m_opcode_mode = eModeThumb;
12680 else
12681 return false;
12682 }
12683 if (m_opcode_mode == eModeThumb)
12684 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12685 else
12686 m_opcode_cpsr = CPSR_MODE_USR;
12687 return true;
12688 }
12689 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012690}
Greg Clayton31e2a382011-01-30 20:03:56 +000012691
Greg Clayton64c84432011-01-21 22:02:52 +000012692bool
12693EmulateInstructionARM::ReadInstruction ()
12694{
12695 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012696 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012697 if (success)
12698 {
12699 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12700 if (success)
12701 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012702 Context read_inst_context;
12703 read_inst_context.type = eContextReadOpcode;
12704 read_inst_context.SetNoArgs ();
12705
Greg Claytonb3448432011-03-24 21:19:54 +000012706 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012707 {
Greg Claytonb3448432011-03-24 21:19:54 +000012708 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012709 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012710
12711 if (success)
12712 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012713 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012714 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012715 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012716 }
12717 else
12718 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012719 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012720 }
12721 }
12722 }
12723 else
12724 {
Greg Claytonb3448432011-03-24 21:19:54 +000012725 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012726 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012727 }
12728 }
12729 }
12730 if (!success)
12731 {
Greg Claytonb3448432011-03-24 21:19:54 +000012732 m_opcode_mode = eModeInvalid;
Greg Clayton3063c952011-04-29 22:50:31 +000012733 m_addr = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012734 }
12735 return success;
12736}
12737
Johnny Chenee9b1f72011-02-09 01:00:31 +000012738uint32_t
12739EmulateInstructionARM::ArchVersion ()
12740{
12741 return m_arm_isa;
12742}
12743
Greg Clayton64c84432011-01-21 22:02:52 +000012744bool
Greg Clayton7bc39082011-03-24 23:53:38 +000012745EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000012746{
Greg Clayton888a7332011-04-26 04:39:08 +000012747 // If we are ignoring conditions, then always return true.
12748 // this allows us to iterate over disassembly code and still
12749 // emulate an instruction even if we don't have all the right
12750 // bits set in the CPSR register...
12751 if (m_ignore_conditions)
12752 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000012753
Greg Clayton7bc39082011-03-24 23:53:38 +000012754 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012755
12756 if (cond == UINT32_MAX)
12757 return false;
12758
12759 bool result = false;
12760 switch (UnsignedBits(cond, 3, 1))
12761 {
Caroline Tice080bf612011-04-05 18:46:00 +000012762 case 0:
12763 if (m_opcode_cpsr == 0)
12764 return true;
12765 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
12766 break;
12767 case 1:
12768 if (m_opcode_cpsr == 0)
12769 return true;
12770 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
12771 break;
12772 case 2:
12773 if (m_opcode_cpsr == 0)
12774 return true;
12775 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
12776 break;
12777 case 3:
12778 if (m_opcode_cpsr == 0)
12779 return true;
12780 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
12781 break;
12782 case 4:
12783 if (m_opcode_cpsr == 0)
12784 return true;
12785 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
12786 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012787 case 5:
Caroline Tice080bf612011-04-05 18:46:00 +000012788 if (m_opcode_cpsr == 0)
12789 return true;
12790 else
12791 {
Greg Claytonb3448432011-03-24 21:19:54 +000012792 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12793 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012794 result = n == v;
12795 }
12796 break;
12797 case 6:
Caroline Tice080bf612011-04-05 18:46:00 +000012798 if (m_opcode_cpsr == 0)
12799 return true;
12800 else
12801 {
Greg Claytonb3448432011-03-24 21:19:54 +000012802 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12803 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12804 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012805 }
12806 break;
12807 case 7:
12808 result = true;
12809 break;
12810 }
12811
12812 if (cond & 1)
12813 result = !result;
12814 return result;
12815}
12816
Johnny Chen9ee056b2011-02-08 00:06:35 +000012817uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012818EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012819{
Greg Claytonb3448432011-03-24 21:19:54 +000012820 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012821 {
12822 default:
12823 case eModeInvalid:
12824 break;
12825
12826 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012827 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012828
12829 case eModeThumb:
12830 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12831 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012832 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012833 const uint32_t byte_size = m_opcode.GetByteSize();
12834 if (byte_size == 2)
12835 {
12836 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12837 return Bits32(opcode, 11, 7);
12838 }
12839 else
12840 {
12841 assert (byte_size == 4);
12842 if (Bits32(opcode, 31, 27) == 0x1e &&
12843 Bits32(opcode, 15, 14) == 0x02 &&
12844 Bits32(opcode, 12, 12) == 0x00 &&
12845 Bits32(opcode, 25, 22) <= 0x0d)
12846 {
12847 return Bits32(opcode, 25, 22);
12848 }
12849 }
12850
12851 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012852 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012853 }
12854 return UINT32_MAX; // Return invalid value
12855}
12856
Johnny Chen9ee056b2011-02-08 00:06:35 +000012857bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000012858EmulateInstructionARM::InITBlock()
12859{
12860 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
12861}
12862
12863bool
12864EmulateInstructionARM::LastInITBlock()
12865{
12866 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
12867}
12868
Caroline Ticeb27771d2011-03-03 22:37:46 +000012869bool
12870EmulateInstructionARM::BadMode (uint32_t mode)
12871{
12872
12873 switch (mode)
12874 {
12875 case 16: return false; // '10000'
12876 case 17: return false; // '10001'
12877 case 18: return false; // '10010'
12878 case 19: return false; // '10011'
12879 case 22: return false; // '10110'
12880 case 23: return false; // '10111'
12881 case 27: return false; // '11011'
12882 case 31: return false; // '11111'
12883 default: return true;
12884 }
12885 return true;
12886}
12887
12888bool
12889EmulateInstructionARM::CurrentModeIsPrivileged ()
12890{
Greg Claytonb3448432011-03-24 21:19:54 +000012891 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012892
12893 if (BadMode (mode))
12894 return false;
12895
12896 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000012897 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012898
12899 return true;
12900}
12901
12902void
12903EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
12904{
12905 bool privileged = CurrentModeIsPrivileged();
12906
12907 uint32_t tmp_cpsr = 0;
12908
Greg Claytonb3448432011-03-24 21:19:54 +000012909 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000012910
12911 if (BitIsSet (bytemask, 3))
12912 {
12913 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
12914 if (affect_execstate)
12915 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
12916 }
12917
12918 if (BitIsSet (bytemask, 2))
12919 {
12920 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
12921 }
12922
12923 if (BitIsSet (bytemask, 1))
12924 {
12925 if (affect_execstate)
12926 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
12927 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
12928 if (privileged)
12929 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
12930 }
12931
12932 if (BitIsSet (bytemask, 0))
12933 {
12934 if (privileged)
12935 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
12936 if (affect_execstate)
12937 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
12938 if (privileged)
12939 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
12940 }
12941
Greg Claytonb3448432011-03-24 21:19:54 +000012942 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000012943}
12944
12945
Johnny Chen098ae2d2011-02-12 00:50:05 +000012946bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000012947EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
12948{
12949 addr_t target;
12950
Johnny Chenee9b1f72011-02-09 01:00:31 +000012951 // Check the current instruction set.
12952 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012953 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012954 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000012955 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000012956
Johnny Chen9ee056b2011-02-08 00:06:35 +000012957 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000012958 return false;
12959
12960 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012961}
12962
12963// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
12964bool
Johnny Chen668b4512011-02-15 21:08:58 +000012965EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012966{
12967 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000012968 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
12969 // we want to record it and issue a WriteRegister callback so the clients
12970 // can track the mode changes accordingly.
12971 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000012972
12973 if (BitIsSet(addr, 0))
12974 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012975 if (CurrentInstrSet() != eModeThumb)
12976 {
12977 SelectInstrSet(eModeThumb);
12978 cpsr_changed = true;
12979 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012980 target = addr & 0xfffffffe;
Greg Claytonc07d4512011-04-26 23:48:45 +000012981 context.SetISA (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012982 }
12983 else if (BitIsClear(addr, 1))
12984 {
Johnny Chen0f309db2011-02-09 19:11:32 +000012985 if (CurrentInstrSet() != eModeARM)
12986 {
12987 SelectInstrSet(eModeARM);
12988 cpsr_changed = true;
12989 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012990 target = addr & 0xfffffffc;
Greg Claytonc07d4512011-04-26 23:48:45 +000012991 context.SetISA (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012992 }
12993 else
12994 return false; // address<1:0> == '10' => UNPREDICTABLE
12995
Johnny Chen0f309db2011-02-09 19:11:32 +000012996 if (cpsr_changed)
12997 {
Johnny Chen558133b2011-02-09 23:59:17 +000012998 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000012999 return false;
13000 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013001 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013002 return false;
13003
13004 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013005}
Greg Clayton64c84432011-01-21 22:02:52 +000013006
Johnny Chenee9b1f72011-02-09 01:00:31 +000013007// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13008bool
Johnny Chen668b4512011-02-15 21:08:58 +000013009EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000013010{
13011 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000013012 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000013013 else
13014 return BranchWritePC((const Context)context, addr);
13015}
13016
Johnny Chen26863dc2011-02-09 23:43:29 +000013017// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13018bool
Johnny Chen668b4512011-02-15 21:08:58 +000013019EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000013020{
13021 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013022 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013023 else
13024 return BranchWritePC((const Context)context, addr);
13025}
13026
Johnny Chenee9b1f72011-02-09 01:00:31 +000013027EmulateInstructionARM::Mode
13028EmulateInstructionARM::CurrentInstrSet ()
13029{
Greg Claytonb3448432011-03-24 21:19:54 +000013030 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013031}
13032
Greg Claytonb3448432011-03-24 21:19:54 +000013033// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013034// ReadInstruction() is performed. This function has a side effect of updating
13035// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013036bool
13037EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13038{
Greg Claytonb3448432011-03-24 21:19:54 +000013039 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013040 switch (arm_or_thumb)
13041 {
13042 default:
13043 return false;
13044 eModeARM:
13045 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013046 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013047 break;
13048 eModeThumb:
13049 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013050 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013051 break;
13052 }
13053 return true;
13054}
13055
Johnny Chenef21b592011-02-10 01:52:38 +000013056// This function returns TRUE if the processor currently provides support for
13057// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13058// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13059bool
13060EmulateInstructionARM::UnalignedSupport()
13061{
13062 return (ArchVersion() >= ARMv7);
13063}
13064
Johnny Chenbf6ad172011-02-11 01:29:53 +000013065// The main addition and subtraction instructions can produce status information
13066// about both unsigned carry and signed overflow conditions. This status
13067// information can be used to synthesize multi-word additions and subtractions.
13068EmulateInstructionARM::AddWithCarryResult
13069EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13070{
13071 uint32_t result;
13072 uint8_t carry_out;
13073 uint8_t overflow;
13074
13075 uint64_t unsigned_sum = x + y + carry_in;
13076 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13077
13078 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013079// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013080 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013081
13082 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013083 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013084 else
13085 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013086
13087 AddWithCarryResult res = { result, carry_out, overflow };
13088 return res;
13089}
13090
Johnny Chen157b9592011-02-18 21:13:05 +000013091uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013092EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013093{
Johnny Chene39f22d2011-02-19 01:36:13 +000013094 uint32_t reg_kind, reg_num;
13095 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013096 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013097 case SP_REG:
13098 reg_kind = eRegisterKindGeneric;
13099 reg_num = LLDB_REGNUM_GENERIC_SP;
13100 break;
13101 case LR_REG:
13102 reg_kind = eRegisterKindGeneric;
13103 reg_num = LLDB_REGNUM_GENERIC_RA;
13104 break;
13105 case PC_REG:
13106 reg_kind = eRegisterKindGeneric;
13107 reg_num = LLDB_REGNUM_GENERIC_PC;
13108 break;
13109 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013110 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013111 {
13112 reg_kind = eRegisterKindDWARF;
13113 reg_num = dwarf_r0 + num;
13114 }
Johnny Chen157b9592011-02-18 21:13:05 +000013115 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013116 {
13117 assert(0 && "Invalid register number");
13118 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013119 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013120 }
13121 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013122 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013123
13124 // Read our register.
13125 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13126
13127 // When executing an ARM instruction , PC reads as the address of the current
13128 // instruction plus 8.
13129 // When executing a Thumb instruction , PC reads as the address of the current
13130 // instruction plus 4.
13131 if (num == 15)
13132 {
13133 if (CurrentInstrSet() == eModeARM)
13134 val += 8;
13135 else
13136 val += 4;
13137 }
Johnny Chen157b9592011-02-18 21:13:05 +000013138
13139 return val;
13140}
13141
Johnny Chenca67d1c2011-02-17 01:35:27 +000013142// Write the result to the ARM core register Rd, and optionally update the
13143// condition flags based on the result.
13144//
13145// This helper method tries to encapsulate the following pseudocode from the
13146// ARM Architecture Reference Manual:
13147//
13148// if d == 15 then // Can only occur for encoding A1
13149// ALUWritePC(result); // setflags is always FALSE here
13150// else
13151// R[d] = result;
13152// if setflags then
13153// APSR.N = result<31>;
13154// APSR.Z = IsZeroBit(result);
13155// APSR.C = carry;
13156// // APSR.V unchanged
13157//
13158// In the above case, the API client does not pass in the overflow arg, which
13159// defaults to ~0u.
13160bool
Johnny Chen10530c22011-02-17 22:37:12 +000013161EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13162 const uint32_t result,
13163 const uint32_t Rd,
13164 bool setflags,
13165 const uint32_t carry,
13166 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013167{
13168 if (Rd == 15)
13169 {
13170 if (!ALUWritePC (context, result))
13171 return false;
13172 }
13173 else
13174 {
Johnny Chena695f952011-02-23 21:24:25 +000013175 uint32_t reg_kind, reg_num;
13176 switch (Rd)
13177 {
13178 case SP_REG:
13179 reg_kind = eRegisterKindGeneric;
13180 reg_num = LLDB_REGNUM_GENERIC_SP;
13181 break;
13182 case LR_REG:
13183 reg_kind = eRegisterKindGeneric;
13184 reg_num = LLDB_REGNUM_GENERIC_RA;
13185 break;
13186 default:
13187 reg_kind = eRegisterKindDWARF;
13188 reg_num = dwarf_r0 + Rd;
13189 }
13190 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013191 return false;
13192 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013193 return WriteFlags (context, result, carry, overflow);
13194 }
13195 return true;
13196}
13197
13198// This helper method tries to encapsulate the following pseudocode from the
13199// ARM Architecture Reference Manual:
13200//
13201// APSR.N = result<31>;
13202// APSR.Z = IsZeroBit(result);
13203// APSR.C = carry;
13204// APSR.V = overflow
13205//
13206// Default arguments can be specified for carry and overflow parameters, which means
13207// not to update the respective flags.
13208bool
13209EmulateInstructionARM::WriteFlags (Context &context,
13210 const uint32_t result,
13211 const uint32_t carry,
13212 const uint32_t overflow)
13213{
Greg Claytonb3448432011-03-24 21:19:54 +000013214 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013215 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13216 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013217 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013218 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013219 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013220 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013221 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013222 {
13223 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13224 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013225 }
13226 return true;
13227}
13228
Greg Clayton64c84432011-01-21 22:02:52 +000013229bool
Greg Clayton888a7332011-04-26 04:39:08 +000013230EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013231{
Johnny Chenc315f862011-02-05 00:46:10 +000013232 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013233 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013234 m_it_session.ITAdvance();
13235
Greg Clayton888a7332011-04-26 04:39:08 +000013236 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013237
13238 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013239 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013240 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013241 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13242
13243 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013244 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013245
Greg Clayton888a7332011-04-26 04:39:08 +000013246 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13247 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013248
Greg Clayton888a7332011-04-26 04:39:08 +000013249 bool success = false;
13250 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013251 {
Greg Clayton888a7332011-04-26 04:39:08 +000013252 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
Greg Clayton061b79d2011-05-09 20:18:18 +000013253 dwarf_cpsr,
13254 0,
13255 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013256 }
13257
Greg Clayton888a7332011-04-26 04:39:08 +000013258 // Only return false if we are unable to read the CPSR if we care about conditions
13259 if (success == false && m_ignore_conditions == false)
13260 return false;
13261
13262 uint32_t orig_pc_value = 0;
13263 if (auto_advance_pc)
13264 {
13265 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13266 if (!success)
13267 return false;
13268 }
13269
13270 // Call the Emulate... function.
13271 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13272 if (!success)
13273 return false;
13274
13275 if (auto_advance_pc)
13276 {
13277 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13278 if (!success)
13279 return false;
13280
13281 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13282 {
13283 if (opcode_data->size == eSize32)
13284 after_pc_value += 4;
13285 else if (opcode_data->size == eSize16)
13286 after_pc_value += 2;
13287
13288 EmulateInstruction::Context context;
13289 context.type = eContextAdvancePC;
13290 context.SetNoArgs();
13291 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13292 return false;
13293
13294 }
13295 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013296 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013297}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013298
13299bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013300EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013301{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013302 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013303 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013304 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013305 return false;
13306 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013307
13308 static ConstString opcode_key ("opcode");
13309 static ConstString before_key ("before_state");
13310 static ConstString after_key ("after_state");
13311
13312 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013313
13314 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013315 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013316 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013317 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013318 return false;
13319 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013320 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013321
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013322 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13323 {
13324 m_opcode_mode = eModeARM;
13325 m_opcode.SetOpcode32 (test_opcode);
13326 }
13327 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13328 {
13329 m_opcode_mode = eModeThumb;
13330 if (test_opcode < 0x10000)
13331 m_opcode.SetOpcode16 (test_opcode);
13332 else
13333 m_opcode.SetOpcode32 (test_opcode);
13334
13335 }
13336 else
13337 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013338 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013339 return false;
13340 }
13341
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013342 EmulationStateARM before_state;
13343 EmulationStateARM after_state;
13344
Caroline Ticedfb2e202011-04-22 05:08:45 +000013345 value_sp = test_data->GetValueForKey (before_key);
13346 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013347 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013348 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013349 return false;
13350 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013351
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013352 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013353 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013354 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013355 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013356 return false;
13357 }
13358
Caroline Ticedfb2e202011-04-22 05:08:45 +000013359 value_sp = test_data->GetValueForKey (after_key);
13360 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013361 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013362 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013363 return false;
13364 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013365
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013366 state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013367 if (!after_state.LoadStateFromDictionary (state_dictionary))
13368 {
13369 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13370 return false;
13371 }
13372
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013373 SetBaton ((void *) &before_state);
13374 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13375 &EmulationStateARM::WritePseudoMemory,
13376 &EmulationStateARM::ReadPseudoRegister,
13377 &EmulationStateARM::WritePseudoRegister);
13378
Greg Clayton888a7332011-04-26 04:39:08 +000013379 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013380 if (!success)
13381 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013382 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013383 return false;
13384 }
13385
13386 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013387 if (!success)
13388 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13389
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013390 return success;
13391}
Greg Claytonc07d4512011-04-26 23:48:45 +000013392//
13393//
13394//const char *
13395//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13396//{
13397// if (reg_kind == eRegisterKindGeneric)
13398// {
13399// switch (reg_num)
13400// {
13401// case LLDB_REGNUM_GENERIC_PC: return "pc";
13402// case LLDB_REGNUM_GENERIC_SP: return "sp";
13403// case LLDB_REGNUM_GENERIC_FP: return "fp";
13404// case LLDB_REGNUM_GENERIC_RA: return "lr";
13405// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13406// default: return NULL;
13407// }
13408// }
13409// else if (reg_kind == eRegisterKindDWARF)
13410// {
13411// return GetARMDWARFRegisterName (reg_num);
13412// }
13413// return NULL;
13414//}
13415//
13416bool
13417EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
Greg Clayton888a7332011-04-26 04:39:08 +000013418{
Greg Clayton75906e42011-05-11 18:39:18 +000013419 unwind_plan.Clear();
Greg Claytonc07d4512011-04-26 23:48:45 +000013420 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13421
13422 UnwindPlan::Row row;
Greg Claytonc07d4512011-04-26 23:48:45 +000013423
13424 // Our previous Call Frame Address is the stack pointer
13425 row.SetCFARegister (dwarf_sp);
13426
13427 // Our previous PC is in the LR
Greg Clayton75906e42011-05-11 18:39:18 +000013428 row.SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
Greg Claytonc07d4512011-04-26 23:48:45 +000013429 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