blob: daaac46b3178dfd39de86797d51448dbc21f104d [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013#include "EmulationStateARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000014#include "lldb/Core/ArchSpec.h"
Caroline Tice080bf612011-04-05 18:46:00 +000015#include "lldb/Core/Address.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000016#include "lldb/Core/ConstString.h"
Caroline Tice080bf612011-04-05 18:46:00 +000017#include "lldb/Core/PluginManager.h"
Caroline Tice6b8d3b52011-04-19 23:30:03 +000018#include "lldb/Core/Stream.h"
Greg Claytonc07d4512011-04-26 23:48:45 +000019#include "lldb/Symbol/UnwindPlan.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000020
Greg Claytonf29a08f2011-02-09 17:41:27 +000021#include "Plugins/Process/Utility/ARMDefines.h"
22#include "Plugins/Process/Utility/ARMUtils.h"
23#include "Utility/ARM_DWARF_Registers.h"
24
Johnny Chen9b8d7832011-02-02 01:13:56 +000025#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000026 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000027
28using namespace lldb;
29using namespace lldb_private;
30
Johnny Chene97c0d52011-02-18 19:32:20 +000031// Convenient macro definitions.
Greg Claytonb3448432011-03-24 21:19:54 +000032#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
33#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000034
Caroline Ticef55261f2011-02-18 22:24:22 +000035#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
36
Johnny Chen0e00af22011-02-10 19:40:42 +000037//----------------------------------------------------------------------
38//
39// ITSession implementation
40//
41//----------------------------------------------------------------------
42
Johnny Chen93070472011-02-04 23:02:47 +000043// A8.6.50
44// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
Greg Clayton04d397c2011-05-23 18:04:09 +000045static uint32_t
46CountITSize (uint32_t ITMask) {
Johnny Chen93070472011-02-04 23:02:47 +000047 // First count the trailing zeros of the IT mask.
Greg Clayton04d397c2011-05-23 18:04:09 +000048 uint32_t TZ = llvm::CountTrailingZeros_32(ITMask);
Johnny Chen93070472011-02-04 23:02:47 +000049 if (TZ > 3)
50 {
51 printf("Encoding error: IT Mask '0000'\n");
52 return 0;
53 }
54 return (4 - TZ);
55}
56
57// Init ITState. Note that at least one bit is always 1 in mask.
Greg Clayton04d397c2011-05-23 18:04:09 +000058bool ITSession::InitIT(uint32_t bits7_0)
Johnny Chen93070472011-02-04 23:02:47 +000059{
60 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
61 if (ITCounter == 0)
62 return false;
63
64 // A8.6.50 IT
65 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
66 if (FirstCond == 0xF)
67 {
68 printf("Encoding error: IT FirstCond '1111'\n");
69 return false;
70 }
71 if (FirstCond == 0xE && ITCounter != 1)
72 {
73 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
74 return false;
75 }
76
77 ITState = bits7_0;
78 return true;
79}
80
81// Update ITState if necessary.
82void ITSession::ITAdvance()
83{
Greg Claytone1f47bb2011-06-02 22:23:35 +000084 //assert(ITCounter);
Johnny Chen93070472011-02-04 23:02:47 +000085 --ITCounter;
86 if (ITCounter == 0)
87 ITState = 0;
88 else
89 {
90 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
91 SetBits32(ITState, 4, 0, NewITState4_0);
92 }
93}
94
95// Return true if we're inside an IT Block.
96bool ITSession::InITBlock()
97{
98 return ITCounter != 0;
99}
100
Johnny Chenc315f862011-02-05 00:46:10 +0000101// Return true if we're the last instruction inside an IT Block.
102bool ITSession::LastInITBlock()
103{
104 return ITCounter == 1;
105}
106
Johnny Chen93070472011-02-04 23:02:47 +0000107// Get condition bits for the current thumb instruction.
108uint32_t ITSession::GetCond()
109{
Johnny Chenc315f862011-02-05 00:46:10 +0000110 if (InITBlock())
111 return Bits32(ITState, 7, 4);
112 else
113 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000114}
115
Greg Clayton64c84432011-01-21 22:02:52 +0000116// ARM constants used during decoding
117#define REG_RD 0
118#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000119#define SP_REG 13
120#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000121#define PC_REG 15
122#define PC_REGLIST_BIT 0x8000
123
Johnny Chen251af6a2011-01-21 22:47:25 +0000124#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000125#define ARMv4T (1u << 1)
126#define ARMv5T (1u << 2)
127#define ARMv5TE (1u << 3)
128#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000129#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000130#define ARMv6K (1u << 6)
131#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000132#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000133#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000134#define ARMvAll (0xffffffffu)
135
Johnny Chen9b8d7832011-02-02 01:13:56 +0000136#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
137#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice1697dd72011-03-30 17:11:45 +0000138#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000139#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000140#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000141#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton04d397c2011-05-23 18:04:09 +0000142#define ARMV7_ABOVE (ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000143
Caroline Tice4f605582011-03-31 00:02:51 +0000144#define No_VFP 0
145#define VFPv1 (1u << 1)
146#define VFPv2 (1u << 2)
147#define VFPv3 (1u << 3)
148#define AdvancedSIMD (1u << 4)
149
150#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
151#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
152#define VFPv2v3 (VFPv2 | VFPv3)
153
Johnny Chen0e00af22011-02-10 19:40:42 +0000154//----------------------------------------------------------------------
155//
156// EmulateInstructionARM implementation
157//
158//----------------------------------------------------------------------
159
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000160void
161EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000162{
Caroline Tice080bf612011-04-05 18:46:00 +0000163 PluginManager::RegisterPlugin (GetPluginNameStatic (),
164 GetPluginDescriptionStatic (),
165 CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000166}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000167
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000168void
169EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000170{
Caroline Tice080bf612011-04-05 18:46:00 +0000171 PluginManager::UnregisterPlugin (CreateInstance);
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000172}
173
Caroline Tice080bf612011-04-05 18:46:00 +0000174const char *
175EmulateInstructionARM::GetPluginNameStatic ()
176{
177 return "lldb.emulate-instruction.arm";
178}
179
180const char *
181EmulateInstructionARM::GetPluginDescriptionStatic ()
182{
183 return "Emulate instructions for the ARM architecture.";
184}
185
186EmulateInstruction *
Greg Clayton888a7332011-04-26 04:39:08 +0000187EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
Caroline Tice080bf612011-04-05 18:46:00 +0000188{
Greg Clayton888a7332011-04-26 04:39:08 +0000189 if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
Caroline Tice080bf612011-04-05 18:46:00 +0000190 {
Greg Clayton888a7332011-04-26 04:39:08 +0000191 if (arch.GetTriple().getArch() == llvm::Triple::arm)
192 {
193 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
194
195 if (emulate_insn_ap.get())
196 return emulate_insn_ap.release();
197 }
198 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
199 {
200 std::auto_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
201
202 if (emulate_insn_ap.get())
203 return emulate_insn_ap.release();
204 }
Caroline Tice080bf612011-04-05 18:46:00 +0000205 }
206
207 return NULL;
208}
209
210bool
211EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
212{
213 if (arch.GetTriple().getArch () == llvm::Triple::arm)
214 return true;
215 else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
216 return true;
217
218 return false;
219}
220
Caroline Ticefa172202011-02-11 22:49:54 +0000221// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
222bool
223EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
224{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000225 EmulateInstruction::Context context;
226 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
227 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000228
229 uint32_t random_data = rand ();
230 const uint32_t addr_byte_size = GetAddressByteSize();
231
Caroline Ticecc96eb52011-02-17 19:20:40 +0000232 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000233 return false;
234
235 return true;
236}
237
Caroline Tice713c2662011-02-11 17:59:55 +0000238// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
239bool
240EmulateInstructionARM::WriteBits32Unknown (int n)
241{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000242 EmulateInstruction::Context context;
243 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
244 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000245
Johnny Chen62ff6f52011-02-11 18:11:22 +0000246 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000247 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
248
249 if (!success)
250 return false;
251
252 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
253 return false;
254
255 return true;
256}
257
Greg Claytonc07d4512011-04-26 23:48:45 +0000258bool
259EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
260{
261 if (reg_kind == eRegisterKindGeneric)
262 {
263 switch (reg_num)
264 {
265 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break;
266 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break;
267 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break;
268 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break;
269 case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break;
270 default: return false;
271 }
272 }
273
274 if (reg_kind == eRegisterKindDWARF)
275 return GetARMDWARFRegisterInfo(reg_num, reg_info);
276 return false;
277}
278
Greg Clayton04d397c2011-05-23 18:04:09 +0000279uint32_t
280EmulateInstructionARM::GetFramePointerRegisterNumber () const
281{
282 if (m_opcode_mode == eModeThumb || m_arch.GetTriple().getOS() == llvm::Triple::Darwin)
283 return 7;
284 else
285 return 11;
286}
287
288uint32_t
289EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const
290{
291 if (m_opcode_mode == eModeThumb || m_arch.GetTriple().getOS() == llvm::Triple::Darwin)
292 return dwarf_r7;
293 else
294 return dwarf_r11;
295}
296
Johnny Chen08c25e82011-01-31 18:02:28 +0000297// Push Multiple Registers stores multiple registers to the stack, storing to
298// consecutive memory locations ending just below the address in SP, and updates
299// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000300bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000301EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000302{
303#if 0
304 // ARM pseudo code...
305 if (ConditionPassed())
306 {
307 EncodingSpecificOperations();
308 NullCheckIfThumbEE(13);
309 address = SP - 4*BitCount(registers);
310
311 for (i = 0 to 14)
312 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000313 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000314 {
315 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
316 MemA[address,4] = bits(32) UNKNOWN;
317 else
318 MemA[address,4] = R[i];
319 address = address + 4;
320 }
321 }
322
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000323 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000324 MemA[address,4] = PCStoreValue();
325
326 SP = SP - 4*BitCount(registers);
327 }
328#endif
329
Greg Clayton107e53d2011-07-06 04:07:21 +0000330 bool conditional = false;
Greg Clayton64c84432011-01-21 22:02:52 +0000331 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +0000332 if (ConditionPassed(opcode, &conditional))
Greg Clayton64c84432011-01-21 22:02:52 +0000333 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000334 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000335 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000336 if (!success)
337 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000338 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000339 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000340 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000341 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000342 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000343 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000344 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000345 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000346 // if BitCount(registers) < 1 then UNPREDICTABLE;
347 if (BitCount(registers) < 1)
348 return false;
349 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000350 case eEncodingT2:
351 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000352 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000353 // if BitCount(registers) < 2 then UNPREDICTABLE;
354 if (BitCount(registers) < 2)
355 return false;
356 break;
357 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000358 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000359 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000360 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000361 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000362 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000363 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000364 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000365 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000366 // Instead of return false, let's handle the following case as well,
367 // which amounts to pushing one reg onto the full descending stacks.
368 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000369 break;
370 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000371 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000372 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000373 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000374 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000375 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000376 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000377 default:
378 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000379 }
Johnny Chence1ca772011-01-25 01:13:00 +0000380 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000381 addr_t addr = sp - sp_offset;
382 uint32_t i;
383
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000384 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +0000385 if (conditional)
386 context.type = EmulateInstruction::eContextRegisterStore;
387 else
388 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000389 RegisterInfo reg_info;
390 RegisterInfo sp_reg;
391 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Clayton64c84432011-01-21 22:02:52 +0000392 for (i=0; i<15; ++i)
393 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000394 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000395 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000396 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
397 context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000398 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000399 if (!success)
400 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000401 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000402 return false;
403 addr += addr_byte_size;
404 }
405 }
406
Johnny Chen7c1bf922011-02-08 23:49:37 +0000407 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000408 {
Greg Claytonc07d4512011-04-26 23:48:45 +0000409 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info);
410 context.SetRegisterPlusOffset (reg_info, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000411 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000412 if (!success)
413 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000414 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000415 return false;
416 }
417
418 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000419 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000420
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000421 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000422 return false;
423 }
424 return true;
425}
426
Johnny Chenef85e912011-01-31 23:07:40 +0000427// Pop Multiple Registers loads multiple registers from the stack, loading from
428// consecutive memory locations staring at the address in SP, and updates
429// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000430bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000431EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000432{
433#if 0
434 // ARM pseudo code...
435 if (ConditionPassed())
436 {
437 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
438 address = SP;
439 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000440 if registers<i> == '1' then
Greg Claytonc07d4512011-04-26 23:48:45 +0000441 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000442 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000443 if UnalignedAllowed then
444 LoadWritePC(MemU[address,4]);
445 else
446 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000447 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
448 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000449 }
450#endif
451
452 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000453
Greg Clayton107e53d2011-07-06 04:07:21 +0000454 bool conditional = false;
455 if (ConditionPassed(opcode, &conditional))
456 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000457 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000458 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000459 if (!success)
460 return false;
461 uint32_t registers = 0;
462 uint32_t Rt; // the destination register
463 switch (encoding) {
464 case eEncodingT1:
465 registers = Bits32(opcode, 7, 0);
466 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000467 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000468 registers |= (1u << 15);
469 // if BitCount(registers) < 1 then UNPREDICTABLE;
470 if (BitCount(registers) < 1)
471 return false;
472 break;
473 case eEncodingT2:
474 // Ignore bit 13.
475 registers = Bits32(opcode, 15, 0) & ~0x2000;
476 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000477 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000478 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000479 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
480 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
481 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000482 break;
483 case eEncodingT3:
484 Rt = Bits32(opcode, 15, 12);
485 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000486 if (Rt == 13)
487 return false;
488 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000489 return false;
490 registers = (1u << Rt);
491 break;
492 case eEncodingA1:
493 registers = Bits32(opcode, 15, 0);
494 // Instead of return false, let's handle the following case as well,
495 // which amounts to popping one reg from the full descending stacks.
496 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
497
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000498 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000499 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000500 return false;
501 break;
502 case eEncodingA2:
503 Rt = Bits32(opcode, 15, 12);
504 // if t == 13 then UNPREDICTABLE;
505 if (Rt == dwarf_sp)
506 return false;
507 registers = (1u << Rt);
508 break;
509 default:
510 return false;
511 }
512 addr_t sp_offset = addr_byte_size * BitCount (registers);
513 addr_t addr = sp;
514 uint32_t i, data;
515
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000516 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +0000517 if (conditional)
518 context.type = EmulateInstruction::eContextRegisterLoad;
519 else
520 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +0000521
522 RegisterInfo sp_reg;
523 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
524
Johnny Chenef85e912011-01-31 23:07:40 +0000525 for (i=0; i<15; ++i)
526 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000527 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000528 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000529 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000530 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000531 if (!success)
532 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +0000533 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000534 return false;
535 addr += addr_byte_size;
536 }
537 }
538
Johnny Chen7c1bf922011-02-08 23:49:37 +0000539 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000540 {
Caroline Tice8ce836d2011-03-16 22:46:55 +0000541 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000542 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000543 if (!success)
544 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000545 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000546 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000547 return false;
548 addr += addr_byte_size;
549 }
550
551 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000552 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000553
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000554 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000555 return false;
556 }
557 return true;
558}
559
Johnny Chen5b442b72011-01-27 19:34:30 +0000560// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000561// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000562bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000563EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000564{
565#if 0
566 // ARM pseudo code...
567 if (ConditionPassed())
568 {
569 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000570 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000571 if d == 15 then
572 ALUWritePC(result); // setflags is always FALSE here
573 else
574 R[d] = result;
575 if setflags then
576 APSR.N = result<31>;
577 APSR.Z = IsZeroBit(result);
578 APSR.C = carry;
579 APSR.V = overflow;
580 }
581#endif
582
583 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000584
Greg Clayton7bc39082011-03-24 23:53:38 +0000585 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000586 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000587 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000588 if (!success)
589 return false;
590 uint32_t Rd; // the destination register
591 uint32_t imm32;
592 switch (encoding) {
593 case eEncodingT1:
594 Rd = 7;
595 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
596 break;
597 case eEncodingA1:
598 Rd = Bits32(opcode, 15, 12);
599 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
600 break;
601 default:
602 return false;
603 }
604 addr_t sp_offset = imm32;
605 addr_t addr = sp + sp_offset; // a pointer to the stack area
606
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000607 EmulateInstruction::Context context;
Greg Clayton75906e42011-05-11 18:39:18 +0000608 context.type = eContextSetFramePointer;
Greg Claytonc07d4512011-04-26 23:48:45 +0000609 RegisterInfo sp_reg;
610 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000611 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000612
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000613 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000614 return false;
615 }
616 return true;
617}
618
Johnny Chen2ccad832011-01-28 19:57:25 +0000619// Set r7 or ip to the current stack pointer.
620// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000621bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000622EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000623{
624#if 0
625 // ARM pseudo code...
626 if (ConditionPassed())
627 {
628 EncodingSpecificOperations();
629 result = R[m];
630 if d == 15 then
631 ALUWritePC(result); // setflags is always FALSE here
632 else
633 R[d] = result;
634 if setflags then
635 APSR.N = result<31>;
636 APSR.Z = IsZeroBit(result);
637 // APSR.C unchanged
638 // APSR.V unchanged
639 }
640#endif
641
642 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000643
Greg Clayton7bc39082011-03-24 23:53:38 +0000644 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000645 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000646 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000647 if (!success)
648 return false;
649 uint32_t Rd; // the destination register
650 switch (encoding) {
651 case eEncodingT1:
652 Rd = 7;
653 break;
654 case eEncodingA1:
655 Rd = 12;
656 break;
657 default:
658 return false;
659 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000660
661 EmulateInstruction::Context context;
Greg Clayton04d397c2011-05-23 18:04:09 +0000662 if (Rd == GetFramePointerRegisterNumber())
663 context.type = EmulateInstruction::eContextSetFramePointer;
664 else
665 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +0000666 RegisterInfo sp_reg;
667 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000668 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000669
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000670 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000671 return false;
672 }
673 return true;
674}
675
Johnny Chen1c13b622011-01-29 00:11:15 +0000676// Move from high register (r8-r15) to low register (r0-r7).
677// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000678bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000679EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000680{
Greg Clayton7bc39082011-03-24 23:53:38 +0000681 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000682}
683
684// Move from register to register.
685// MOV (register)
686bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000687EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000688{
Johnny Chen1c13b622011-01-29 00:11:15 +0000689#if 0
690 // ARM pseudo code...
691 if (ConditionPassed())
692 {
693 EncodingSpecificOperations();
694 result = R[m];
695 if d == 15 then
696 ALUWritePC(result); // setflags is always FALSE here
697 else
698 R[d] = result;
699 if setflags then
700 APSR.N = result<31>;
701 APSR.Z = IsZeroBit(result);
702 // APSR.C unchanged
703 // APSR.V unchanged
704 }
705#endif
706
707 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000708
Greg Clayton7bc39082011-03-24 23:53:38 +0000709 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000710 {
711 uint32_t Rm; // the source register
712 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000713 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000714 switch (encoding) {
715 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000716 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000717 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000718 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000719 if (Rd == 15 && InITBlock() && !LastInITBlock())
720 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000721 break;
722 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000723 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000724 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000725 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000726 if (InITBlock())
727 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000728 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000729 case eEncodingT3:
730 Rd = Bits32(opcode, 11, 8);
731 Rm = Bits32(opcode, 3, 0);
732 setflags = BitIsSet(opcode, 20);
733 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
734 if (setflags && (BadReg(Rd) || BadReg(Rm)))
735 return false;
736 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
737 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
738 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000739 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000740 case eEncodingA1:
741 Rd = Bits32(opcode, 15, 12);
742 Rm = Bits32(opcode, 3, 0);
743 setflags = BitIsSet(opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +0000744
Johnny Chen01d61572011-02-25 00:23:25 +0000745 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen01d61572011-02-25 00:23:25 +0000746 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +0000747 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen01d61572011-02-25 00:23:25 +0000748 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000749 default:
750 return false;
751 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000752 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000753 if (!success)
754 return false;
755
756 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000757 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000758 context.type = EmulateInstruction::eContextRegisterLoad;
Greg Claytonc07d4512011-04-26 23:48:45 +0000759 RegisterInfo dwarf_reg;
760 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000761 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000762
Johnny Chen10530c22011-02-17 22:37:12 +0000763 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000764 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000765 }
766 return true;
767}
768
Johnny Chen357c30f2011-02-14 22:04:25 +0000769// Move (immediate) writes an immediate value to the destination register. It
770// can optionally update the condition flags based on the value.
771// MOV (immediate)
772bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000773EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000774{
775#if 0
776 // ARM pseudo code...
777 if (ConditionPassed())
778 {
779 EncodingSpecificOperations();
780 result = imm32;
781 if d == 15 then // Can only occur for ARM encoding
782 ALUWritePC(result); // setflags is always FALSE here
783 else
784 R[d] = result;
785 if setflags then
786 APSR.N = result<31>;
787 APSR.Z = IsZeroBit(result);
788 APSR.C = carry;
789 // APSR.V unchanged
790 }
791#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000792
Greg Clayton7bc39082011-03-24 23:53:38 +0000793 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000794 {
795 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000796 uint32_t imm32; // the immediate value to be written to Rd
797 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
798 bool setflags;
799 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000800 case eEncodingT1:
801 Rd = Bits32(opcode, 10, 8);
802 setflags = !InITBlock();
803 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
804 carry = APSR_C;
805
806 break;
807
808 case eEncodingT2:
809 Rd = Bits32(opcode, 11, 8);
810 setflags = BitIsSet(opcode, 20);
811 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
812 if (BadReg(Rd))
813 return false;
814
815 break;
816
817 case eEncodingT3:
818 {
819 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
820 Rd = Bits32 (opcode, 11, 8);
821 setflags = false;
822 uint32_t imm4 = Bits32 (opcode, 19, 16);
823 uint32_t imm3 = Bits32 (opcode, 14, 12);
824 uint32_t i = Bit32 (opcode, 26);
825 uint32_t imm8 = Bits32 (opcode, 7, 0);
826 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
827
828 // if BadReg(d) then UNPREDICTABLE;
829 if (BadReg (Rd))
830 return false;
831 }
832 break;
833
834 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +0000835 // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
Caroline Tice89c6d582011-03-29 19:53:44 +0000836 Rd = Bits32 (opcode, 15, 12);
837 setflags = BitIsSet (opcode, 20);
838 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +0000839
Greg Clayton061b79d2011-05-09 20:18:18 +0000840 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +0000841 if ((Rd == 15) && setflags)
842 return EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice89c6d582011-03-29 19:53:44 +0000843
844 break;
845
846 case eEncodingA2:
847 {
848 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
849 Rd = Bits32 (opcode, 15, 12);
850 setflags = false;
851 uint32_t imm4 = Bits32 (opcode, 19, 16);
852 uint32_t imm12 = Bits32 (opcode, 11, 0);
853 imm32 = (imm4 << 12) | imm12;
854
855 // if d == 15 then UNPREDICTABLE;
856 if (Rd == 15)
857 return false;
858 }
859 break;
860
861 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000862 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000863 }
864 uint32_t result = imm32;
865
866 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000867 EmulateInstruction::Context context;
868 context.type = EmulateInstruction::eContextImmediate;
869 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000870
Johnny Chen10530c22011-02-17 22:37:12 +0000871 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000872 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000873 }
874 return true;
875}
876
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000877// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
878// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
879// unsigned values.
880//
881// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
882// limited to only a few forms of the instruction.
883bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000884EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000885{
886#if 0
887 if ConditionPassed() then
888 EncodingSpecificOperations();
889 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
890 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
891 result = operand1 * operand2;
892 R[d] = result<31:0>;
893 if setflags then
894 APSR.N = result<31>;
895 APSR.Z = IsZeroBit(result);
896 if ArchVersion() == 4 then
897 APSR.C = bit UNKNOWN;
898 // else APSR.C unchanged
899 // APSR.V always unchanged
900#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000901
Greg Clayton7bc39082011-03-24 23:53:38 +0000902 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000903 {
904 uint32_t d;
905 uint32_t n;
906 uint32_t m;
907 bool setflags;
908
909 // EncodingSpecificOperations();
910 switch (encoding)
911 {
912 case eEncodingT1:
913 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
914 d = Bits32 (opcode, 2, 0);
915 n = Bits32 (opcode, 5, 3);
916 m = Bits32 (opcode, 2, 0);
917 setflags = !InITBlock();
918
919 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
920 if ((ArchVersion() < ARMv6) && (d == n))
921 return false;
922
923 break;
924
925 case eEncodingT2:
926 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
927 d = Bits32 (opcode, 11, 8);
928 n = Bits32 (opcode, 19, 16);
929 m = Bits32 (opcode, 3, 0);
930 setflags = false;
931
932 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
933 if (BadReg (d) || BadReg (n) || BadReg (m))
934 return false;
935
936 break;
937
938 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000939 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000940 d = Bits32 (opcode, 19, 16);
941 n = Bits32 (opcode, 3, 0);
942 m = Bits32 (opcode, 11, 8);
943 setflags = BitIsSet (opcode, 20);
944
945 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
946 if ((d == 15) || (n == 15) || (m == 15))
947 return false;
948
949 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
950 if ((ArchVersion() < ARMv6) && (d == n))
951 return false;
952
953 break;
954
955 default:
956 return false;
957 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000958
959 bool success = false;
960
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000961 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
962 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
963 if (!success)
964 return false;
965
966 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
967 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
968 if (!success)
969 return false;
970
971 // result = operand1 * operand2;
972 uint64_t result = operand1 * operand2;
973
974 // R[d] = result<31:0>;
Greg Claytonc07d4512011-04-26 23:48:45 +0000975 RegisterInfo op1_reg;
976 RegisterInfo op2_reg;
977 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
978 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000979
980 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +0000981 context.type = eContextArithmetic;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000982 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
983
984 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
985 return false;
986
987 // if setflags then
988 if (setflags)
989 {
990 // APSR.N = result<31>;
991 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000992 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000993 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
994 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000995 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000996 {
997 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
998 return false;
999 }
1000
1001 // if ArchVersion() == 4 then
1002 // APSR.C = bit UNKNOWN;
1003 }
1004 }
1005 return true;
1006}
1007
Johnny Chend642a6a2011-02-22 01:01:03 +00001008// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
1009// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +00001010bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001011EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +00001012{
1013#if 0
1014 // ARM pseudo code...
1015 if (ConditionPassed())
1016 {
1017 EncodingSpecificOperations();
1018 result = NOT(imm32);
1019 if d == 15 then // Can only occur for ARM encoding
1020 ALUWritePC(result); // setflags is always FALSE here
1021 else
1022 R[d] = result;
1023 if setflags then
1024 APSR.N = result<31>;
1025 APSR.Z = IsZeroBit(result);
1026 APSR.C = carry;
1027 // APSR.V unchanged
1028 }
1029#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001030
Greg Clayton7bc39082011-03-24 23:53:38 +00001031 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001032 {
1033 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +00001034 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1035 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001036 bool setflags;
1037 switch (encoding) {
1038 case eEncodingT1:
1039 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001040 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001041 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001042 break;
1043 case eEncodingA1:
1044 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001045 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +00001046 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
Caroline Tice1f954f52011-04-11 15:51:10 +00001047
Johnny Chend642a6a2011-02-22 01:01:03 +00001048 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chend642a6a2011-02-22 01:01:03 +00001049 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001050 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001051 break;
1052 default:
1053 return false;
1054 }
1055 uint32_t result = ~imm32;
1056
1057 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001058 EmulateInstruction::Context context;
1059 context.type = EmulateInstruction::eContextImmediate;
1060 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00001061
Johnny Chen10530c22011-02-17 22:37:12 +00001062 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00001063 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +00001064 }
1065 return true;
Johnny Chen28070c32011-02-12 01:27:26 +00001066}
1067
Johnny Chend642a6a2011-02-22 01:01:03 +00001068// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
1069// It can optionally update the condition flags based on the result.
1070bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001071EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +00001072{
1073#if 0
1074 // ARM pseudo code...
1075 if (ConditionPassed())
1076 {
1077 EncodingSpecificOperations();
1078 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1079 result = NOT(shifted);
1080 if d == 15 then // Can only occur for ARM encoding
1081 ALUWritePC(result); // setflags is always FALSE here
1082 else
1083 R[d] = result;
1084 if setflags then
1085 APSR.N = result<31>;
1086 APSR.Z = IsZeroBit(result);
1087 APSR.C = carry;
1088 // APSR.V unchanged
1089 }
1090#endif
1091
Greg Clayton7bc39082011-03-24 23:53:38 +00001092 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +00001093 {
1094 uint32_t Rm; // the source register
1095 uint32_t Rd; // the destination register
1096 ARM_ShifterType shift_t;
1097 uint32_t shift_n; // the shift applied to the value read from Rm
1098 bool setflags;
1099 uint32_t carry; // the carry bit after the shift operation
1100 switch (encoding) {
1101 case eEncodingT1:
1102 Rd = Bits32(opcode, 2, 0);
1103 Rm = Bits32(opcode, 5, 3);
1104 setflags = !InITBlock();
1105 shift_t = SRType_LSL;
1106 shift_n = 0;
1107 if (InITBlock())
1108 return false;
1109 break;
1110 case eEncodingT2:
1111 Rd = Bits32(opcode, 11, 8);
1112 Rm = Bits32(opcode, 3, 0);
1113 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001114 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001115 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +00001116 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +00001117 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001118 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001119 case eEncodingA1:
1120 Rd = Bits32(opcode, 15, 12);
1121 Rm = Bits32(opcode, 3, 0);
1122 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001123 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001124 break;
1125 default:
1126 return false;
1127 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001128 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001129 uint32_t value = ReadCoreReg(Rm, &success);
1130 if (!success)
1131 return false;
1132
Johnny Chena4438a72011-06-02 22:50:51 +00001133 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1134 if (!success)
1135 return false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001136 uint32_t result = ~shifted;
1137
1138 // The context specifies that an immediate is to be moved into Rd.
1139 EmulateInstruction::Context context;
1140 context.type = EmulateInstruction::eContextImmediate;
1141 context.SetNoArgs ();
1142
1143 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1144 return false;
1145 }
1146 return true;
1147}
1148
Johnny Chen788e0552011-01-27 22:52:23 +00001149// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1150// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001151bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001152EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001153{
1154#if 0
1155 // ARM pseudo code...
1156 if (ConditionPassed())
1157 {
1158 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1159 base = Align(PC,4);
1160 address = if add then (base + imm32) else (base - imm32);
1161 data = MemU[address,4];
1162 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001163 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1164 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001165 R[t] = data;
1166 else // Can only apply before ARMv7
1167 if CurrentInstrSet() == InstrSet_ARM then
1168 R[t] = ROR(data, 8*UInt(address<1:0>));
1169 else
1170 R[t] = bits(32) UNKNOWN;
1171 }
1172#endif
1173
Greg Clayton7bc39082011-03-24 23:53:38 +00001174 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001175 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001176 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001177 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001178 if (!success)
1179 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001180
1181 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001182 EmulateInstruction::Context context;
1183 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001184 RegisterInfo pc_reg;
1185 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001186 context.SetRegisterPlusOffset (pc_reg, 0);
1187
Johnny Chenc9de9102011-02-11 19:12:30 +00001188 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001189 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001190 bool add; // +imm32 or -imm32?
1191 addr_t base; // the base address
1192 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001193 uint32_t data; // the literal data value from the PC relative load
1194 switch (encoding) {
1195 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001196 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001197 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001198 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001199 break;
1200 case eEncodingT2:
1201 Rt = Bits32(opcode, 15, 12);
1202 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1203 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001204 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001205 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001206 break;
1207 default:
1208 return false;
1209 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001210
Johnny Chene39f22d2011-02-19 01:36:13 +00001211 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001212 if (add)
1213 address = base + imm32;
1214 else
1215 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001216
1217 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001218 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001219 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001220 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001221
1222 if (Rt == 15)
1223 {
1224 if (Bits32(address, 1, 0) == 0)
1225 {
1226 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001227 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001228 return false;
1229 }
1230 else
1231 return false;
1232 }
1233 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1234 {
1235 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1236 return false;
1237 }
1238 else // We don't handle ARM for now.
1239 return false;
1240
Johnny Chen788e0552011-01-27 22:52:23 +00001241 }
1242 return true;
1243}
1244
Johnny Chen5b442b72011-01-27 19:34:30 +00001245// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001246// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001247bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001248EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001249{
1250#if 0
1251 // ARM pseudo code...
1252 if (ConditionPassed())
1253 {
1254 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001255 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001256 if d == 15 then // Can only occur for ARM encoding
1257 ALUWritePC(result); // setflags is always FALSE here
1258 else
1259 R[d] = result;
1260 if setflags then
1261 APSR.N = result<31>;
1262 APSR.Z = IsZeroBit(result);
1263 APSR.C = carry;
1264 APSR.V = overflow;
1265 }
1266#endif
1267
1268 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001269
Greg Clayton7bc39082011-03-24 23:53:38 +00001270 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001271 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001272 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001273 if (!success)
1274 return false;
1275 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001276 uint32_t d;
1277 bool setflags;
1278 switch (encoding)
1279 {
1280 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001281 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001282 d = Bits32 (opcode, 10, 8);
1283 setflags = false;
1284 imm32 = (Bits32 (opcode, 7, 0) << 2);
1285
1286 break;
1287
1288 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001289 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001290 d = 13;
1291 setflags = false;
1292 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1293
1294 break;
1295
1296 default:
1297 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001298 }
1299 addr_t sp_offset = imm32;
1300 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1301
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001302 EmulateInstruction::Context context;
1303 context.type = EmulateInstruction::eContextAdjustStackPointer;
Greg Claytonc07d4512011-04-26 23:48:45 +00001304 RegisterInfo sp_reg;
1305 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001306 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001307
Caroline Ticee2212882011-03-22 22:38:28 +00001308 if (d == 15)
1309 {
1310 if (!ALUWritePC (context, addr))
1311 return false;
1312 }
1313 else
1314 {
1315 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1316 return false;
1317 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001318 }
1319 return true;
1320}
1321
1322// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001323// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001324bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001325EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001326{
1327#if 0
1328 // ARM pseudo code...
1329 if (ConditionPassed())
1330 {
1331 EncodingSpecificOperations();
1332 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001333 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001334 if d == 15 then
1335 ALUWritePC(result); // setflags is always FALSE here
1336 else
1337 R[d] = result;
1338 if setflags then
1339 APSR.N = result<31>;
1340 APSR.Z = IsZeroBit(result);
1341 APSR.C = carry;
1342 APSR.V = overflow;
1343 }
1344#endif
1345
1346 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001347
Greg Clayton7bc39082011-03-24 23:53:38 +00001348 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001349 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001350 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001351 if (!success)
1352 return false;
1353 uint32_t Rm; // the second operand
1354 switch (encoding) {
1355 case eEncodingT2:
1356 Rm = Bits32(opcode, 6, 3);
1357 break;
1358 default:
1359 return false;
1360 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001361 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001362 if (!success)
1363 return false;
1364
1365 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1366
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001367 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00001368 context.type = eContextArithmetic;
1369 RegisterInfo sp_reg;
1370 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
1371
1372 RegisterInfo other_reg;
1373 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00001374 context.SetRegisterRegisterOperands (sp_reg, other_reg);
Johnny Chen5b442b72011-01-27 19:34:30 +00001375
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001376 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001377 return false;
1378 }
1379 return true;
1380}
1381
Johnny Chen9b8d7832011-02-02 01:13:56 +00001382// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1383// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1384// from Thumb to ARM.
1385// BLX (immediate)
1386bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001387EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001388{
1389#if 0
1390 // ARM pseudo code...
1391 if (ConditionPassed())
1392 {
1393 EncodingSpecificOperations();
1394 if CurrentInstrSet() == InstrSet_ARM then
1395 LR = PC - 4;
1396 else
1397 LR = PC<31:1> : '1';
1398 if targetInstrSet == InstrSet_ARM then
1399 targetAddress = Align(PC,4) + imm32;
1400 else
1401 targetAddress = PC + imm32;
1402 SelectInstrSet(targetInstrSet);
1403 BranchWritePC(targetAddress);
1404 }
1405#endif
1406
Greg Clayton7bc39082011-03-24 23:53:38 +00001407 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001408
Greg Clayton7bc39082011-03-24 23:53:38 +00001409 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001410 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001411 EmulateInstruction::Context context;
1412 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001413 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001414 if (!success)
1415 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001416 addr_t lr; // next instruction address
1417 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001418 int32_t imm32; // PC-relative offset
1419 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001420 case eEncodingT1:
1421 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001422 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001423 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001424 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001425 uint32_t J1 = Bit32(opcode, 13);
1426 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001427 uint32_t imm11 = Bits32(opcode, 10, 0);
1428 uint32_t I1 = !(J1 ^ S);
1429 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001430 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001431 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001432 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001433 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001434 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001435 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001436 break;
1437 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001438 case eEncodingT2:
1439 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001440 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001441 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001442 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001443 uint32_t J1 = Bit32(opcode, 13);
1444 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001445 uint32_t imm10L = Bits32(opcode, 10, 1);
1446 uint32_t I1 = !(J1 ^ S);
1447 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001448 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001449 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001450 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001451 context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001452 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001453 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001454 break;
1455 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001456 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001457 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001458 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001459 target = Align(pc, 4) + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001460 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001461 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001462 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001463 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001464 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001465 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00001466 context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001467 break;
1468 default:
1469 return false;
1470 }
1471 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1472 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001473 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001474 return false;
1475 }
1476 return true;
1477}
1478
1479// Branch with Link and Exchange (register) calls a subroutine at an address and
1480// instruction set specified by a register.
1481// BLX (register)
1482bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001483EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001484{
1485#if 0
1486 // ARM pseudo code...
1487 if (ConditionPassed())
1488 {
1489 EncodingSpecificOperations();
1490 target = R[m];
1491 if CurrentInstrSet() == InstrSet_ARM then
1492 next_instr_addr = PC - 4;
1493 LR = next_instr_addr;
1494 else
1495 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001496 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001497 BXWritePC(target);
1498 }
1499#endif
1500
1501 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001502
Greg Clayton7bc39082011-03-24 23:53:38 +00001503 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001504 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001505 EmulateInstruction::Context context;
1506 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001507 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001508 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001509 if (!success)
1510 return false;
1511 uint32_t Rm; // the register with the target address
1512 switch (encoding) {
1513 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001514 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001515 Rm = Bits32(opcode, 6, 3);
1516 // if m == 15 then UNPREDICTABLE;
1517 if (Rm == 15)
1518 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001519 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001520 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001521 break;
1522 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001523 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001524 Rm = Bits32(opcode, 3, 0);
1525 // if m == 15 then UNPREDICTABLE;
1526 if (Rm == 15)
1527 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001528 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001529 default:
1530 return false;
1531 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001532 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001533 if (!success)
1534 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001535 RegisterInfo dwarf_reg;
1536 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001537 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001538 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1539 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001540 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001541 return false;
1542 }
1543 return true;
1544}
1545
Johnny Chenab3b3512011-02-12 00:10:51 +00001546// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001547bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001548EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001549{
1550#if 0
1551 // ARM pseudo code...
1552 if (ConditionPassed())
1553 {
1554 EncodingSpecificOperations();
1555 BXWritePC(R[m]);
1556 }
1557#endif
1558
Greg Clayton7bc39082011-03-24 23:53:38 +00001559 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001560 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001561 EmulateInstruction::Context context;
1562 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001563 uint32_t Rm; // the register with the target address
1564 switch (encoding) {
1565 case eEncodingT1:
1566 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001567 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001568 return false;
1569 break;
1570 case eEncodingA1:
1571 Rm = Bits32(opcode, 3, 0);
1572 break;
1573 default:
1574 return false;
1575 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001576 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001577 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001578 if (!success)
1579 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +00001580
1581 RegisterInfo dwarf_reg;
1582 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen668b4512011-02-15 21:08:58 +00001583 context.SetRegister (dwarf_reg);
1584 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001585 return false;
1586 }
1587 return true;
1588}
1589
Johnny Chen59e6ab72011-02-24 21:01:20 +00001590// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1591// address and instruction set specified by a register as though it were a BX instruction.
1592//
1593// TODO: Emulate Jazelle architecture?
1594// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1595bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001596EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001597{
1598#if 0
1599 // ARM pseudo code...
1600 if (ConditionPassed())
1601 {
1602 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001603 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001604 BXWritePC(R[m]);
1605 else
1606 if JazelleAcceptsExecution() then
1607 SwitchToJazelleExecution();
1608 else
1609 SUBARCHITECTURE_DEFINED handler call;
1610 }
1611#endif
1612
Greg Clayton7bc39082011-03-24 23:53:38 +00001613 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001614 {
1615 EmulateInstruction::Context context;
1616 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1617 uint32_t Rm; // the register with the target address
1618 switch (encoding) {
1619 case eEncodingT1:
1620 Rm = Bits32(opcode, 19, 16);
1621 if (BadReg(Rm))
1622 return false;
1623 if (InITBlock() && !LastInITBlock())
1624 return false;
1625 break;
1626 case eEncodingA1:
1627 Rm = Bits32(opcode, 3, 0);
1628 if (Rm == 15)
1629 return false;
1630 break;
1631 default:
1632 return false;
1633 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001634 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001635 addr_t target = ReadCoreReg (Rm, &success);
1636 if (!success)
1637 return false;
1638
Greg Claytonc07d4512011-04-26 23:48:45 +00001639 RegisterInfo dwarf_reg;
1640 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
Johnny Chen59e6ab72011-02-24 21:01:20 +00001641 context.SetRegister (dwarf_reg);
1642 if (!BXWritePC(context, target))
1643 return false;
1644 }
1645 return true;
1646}
1647
Johnny Chen0d0148e2011-01-28 02:26:08 +00001648// Set r7 to point to some ip offset.
1649// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001650bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001651EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001652{
1653#if 0
1654 // ARM pseudo code...
1655 if (ConditionPassed())
1656 {
1657 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001658 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001659 if d == 15 then // Can only occur for ARM encoding
1660 ALUWritePC(result); // setflags is always FALSE here
1661 else
1662 R[d] = result;
1663 if setflags then
1664 APSR.N = result<31>;
1665 APSR.Z = IsZeroBit(result);
1666 APSR.C = carry;
1667 APSR.V = overflow;
1668 }
1669#endif
1670
Greg Clayton7bc39082011-03-24 23:53:38 +00001671 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001672 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001673 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001674 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001675 if (!success)
1676 return false;
1677 uint32_t imm32;
1678 switch (encoding) {
1679 case eEncodingA1:
1680 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1681 break;
1682 default:
1683 return false;
1684 }
1685 addr_t ip_offset = imm32;
1686 addr_t addr = ip - ip_offset; // the adjusted ip value
1687
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001688 EmulateInstruction::Context context;
1689 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001690 RegisterInfo dwarf_reg;
1691 GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001692 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001693
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001694 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001695 return false;
1696 }
1697 return true;
1698}
1699
1700// Set ip to point to some stack offset.
1701// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001702bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001703EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001704{
1705#if 0
1706 // ARM pseudo code...
1707 if (ConditionPassed())
1708 {
1709 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001710 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001711 if d == 15 then // Can only occur for ARM encoding
1712 ALUWritePC(result); // setflags is always FALSE here
1713 else
1714 R[d] = result;
1715 if setflags then
1716 APSR.N = result<31>;
1717 APSR.Z = IsZeroBit(result);
1718 APSR.C = carry;
1719 APSR.V = overflow;
1720 }
1721#endif
1722
Greg Clayton7bc39082011-03-24 23:53:38 +00001723 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001724 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001725 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001726 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001727 if (!success)
1728 return false;
1729 uint32_t imm32;
1730 switch (encoding) {
1731 case eEncodingA1:
1732 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1733 break;
1734 default:
1735 return false;
1736 }
1737 addr_t sp_offset = imm32;
1738 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1739
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001740 EmulateInstruction::Context context;
1741 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00001742 RegisterInfo dwarf_reg;
1743 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001744 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001745
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001746 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001747 return false;
1748 }
1749 return true;
1750}
1751
Johnny Chenc9e747f2011-02-23 01:55:07 +00001752// This instruction subtracts an immediate value from the SP value, and writes
1753// the result to the destination register.
1754//
1755// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001756bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001757EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001758{
1759#if 0
1760 // ARM pseudo code...
1761 if (ConditionPassed())
1762 {
1763 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001764 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001765 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001766 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001767 else
1768 R[d] = result;
1769 if setflags then
1770 APSR.N = result<31>;
1771 APSR.Z = IsZeroBit(result);
1772 APSR.C = carry;
1773 APSR.V = overflow;
1774 }
1775#endif
1776
1777 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001778 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001779 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001780 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001781 if (!success)
1782 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001783
1784 uint32_t Rd;
1785 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001786 uint32_t imm32;
1787 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001788 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001789 Rd = 13;
1790 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001791 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001792 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001793 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001794 Rd = Bits32(opcode, 11, 8);
1795 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001796 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001797 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001798 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001799 if (Rd == 15 && !setflags)
1800 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001801 break;
1802 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001803 Rd = Bits32(opcode, 11, 8);
1804 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001805 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001806 if (Rd == 15)
1807 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001808 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001809 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001810 Rd = Bits32(opcode, 15, 12);
1811 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001812 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00001813
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001814 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001815 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00001816 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001817 break;
1818 default:
1819 return false;
1820 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001821 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1822
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001823 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001824 if (Rd == 13)
1825 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001826 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1827 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001828 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001829 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001830 }
1831 else
1832 {
1833 context.type = EmulateInstruction::eContextImmediate;
1834 context.SetNoArgs ();
1835 }
1836
1837 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001838 return false;
1839 }
1840 return true;
1841}
1842
Johnny Chen08c25e82011-01-31 18:02:28 +00001843// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001844bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001845EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001846{
1847#if 0
1848 // ARM pseudo code...
1849 if (ConditionPassed())
1850 {
1851 EncodingSpecificOperations();
1852 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1853 address = if index then offset_addr else R[n];
1854 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1855 if wback then R[n] = offset_addr;
1856 }
1857#endif
1858
Greg Clayton107e53d2011-07-06 04:07:21 +00001859 bool conditional = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001860 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +00001861 if (ConditionPassed(opcode, &conditional))
Johnny Chence1ca772011-01-25 01:13:00 +00001862 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001863 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001864 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001865 if (!success)
1866 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001867 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001868 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001869 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1870
1871 bool index;
1872 bool add;
1873 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001874 switch (encoding) {
1875 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001876 Rt = Bits32(opcode, 15, 12);
1877 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001878 Rn = Bits32 (opcode, 19, 16);
1879
1880 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1881 return false;
1882
1883 index = BitIsSet (opcode, 24);
1884 add = BitIsSet (opcode, 23);
1885 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1886
1887 if (wback && ((Rn == 15) || (Rn == Rt)))
1888 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001889 break;
1890 default:
1891 return false;
1892 }
Caroline Tice3e407972011-03-18 19:41:00 +00001893 addr_t offset_addr;
1894 if (add)
1895 offset_addr = sp + imm12;
1896 else
1897 offset_addr = sp - imm12;
1898
1899 addr_t addr;
1900 if (index)
1901 addr = offset_addr;
1902 else
1903 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001904
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001905 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +00001906 if (conditional)
1907 context.type = EmulateInstruction::eContextRegisterStore;
1908 else
1909 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00001910 RegisterInfo sp_reg;
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001911 RegisterInfo dwarf_reg;
1912
Greg Claytonc07d4512011-04-26 23:48:45 +00001913 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Greg Claytonb9e8f6e2011-05-18 01:58:14 +00001914 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
1915 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001916 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001917 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001918 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001919 if (!success)
1920 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001921 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001922 return false;
1923 }
1924 else
1925 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001926 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001927 if (!success)
1928 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001929 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001930 return false;
1931 }
1932
Caroline Tice3e407972011-03-18 19:41:00 +00001933
1934 if (wback)
1935 {
1936 context.type = EmulateInstruction::eContextAdjustStackPointer;
1937 context.SetImmediateSigned (addr - sp);
1938 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1939 return false;
1940 }
Johnny Chence1ca772011-01-25 01:13:00 +00001941 }
1942 return true;
1943}
1944
Johnny Chen08c25e82011-01-31 18:02:28 +00001945// Vector Push stores multiple extension registers to the stack.
1946// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001947bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001948EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001949{
1950#if 0
1951 // ARM pseudo code...
1952 if (ConditionPassed())
1953 {
1954 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1955 address = SP - imm32;
1956 SP = SP - imm32;
1957 if single_regs then
1958 for r = 0 to regs-1
1959 MemA[address,4] = S[d+r]; address = address+4;
1960 else
1961 for r = 0 to regs-1
1962 // Store as two word-aligned words in the correct order for current endianness.
1963 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1964 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1965 address = address+8;
1966 }
1967#endif
1968
1969 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +00001970 bool conditional = false;
1971 if (ConditionPassed(opcode, &conditional))
Johnny Chen799dfd02011-01-26 23:14:33 +00001972 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001973 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001974 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001975 if (!success)
1976 return false;
1977 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001978 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001979 uint32_t imm32; // stack offset
1980 uint32_t regs; // number of registers
1981 switch (encoding) {
1982 case eEncodingT1:
1983 case eEncodingA1:
1984 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001985 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001986 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1987 // If UInt(imm8) is odd, see "FSTMX".
1988 regs = Bits32(opcode, 7, 0) / 2;
1989 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1990 if (regs == 0 || regs > 16 || (d + regs) > 32)
1991 return false;
1992 break;
1993 case eEncodingT2:
1994 case eEncodingA2:
1995 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001996 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001997 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1998 regs = Bits32(opcode, 7, 0);
1999 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2000 if (regs == 0 || regs > 16 || (d + regs) > 32)
2001 return false;
2002 break;
2003 default:
2004 return false;
2005 }
2006 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2007 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2008 addr_t sp_offset = imm32;
2009 addr_t addr = sp - sp_offset;
2010 uint32_t i;
2011
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002012 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +00002013 if (conditional)
2014 context.type = EmulateInstruction::eContextRegisterStore;
2015 else
2016 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002017 RegisterInfo dwarf_reg;
2018 RegisterInfo sp_reg;
2019 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002020 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00002021 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002022 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002023 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00002024 // uint64_t to accommodate 64-bit registers.
Greg Clayton061b79d2011-05-09 20:18:18 +00002025 uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00002026 if (!success)
2027 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002028 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00002029 return false;
2030 addr += reg_byte_size;
2031 }
2032
2033 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002034 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00002035
Greg Clayton2b8e8b02011-02-01 00:49:32 +00002036 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00002037 return false;
2038 }
2039 return true;
2040}
2041
Johnny Chen587a0a42011-02-01 18:35:28 +00002042// Vector Pop loads multiple extension registers from the stack.
2043// It also updates SP to point just above the loaded data.
2044bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002045EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00002046{
2047#if 0
2048 // ARM pseudo code...
2049 if (ConditionPassed())
2050 {
2051 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2052 address = SP;
2053 SP = SP + imm32;
2054 if single_regs then
2055 for r = 0 to regs-1
2056 S[d+r] = MemA[address,4]; address = address+4;
2057 else
2058 for r = 0 to regs-1
2059 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2060 // Combine the word-aligned words in the correct order for current endianness.
2061 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2062 }
2063#endif
2064
2065 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +00002066 bool conditional = false;
2067 if (ConditionPassed(opcode, &conditional))
Johnny Chen587a0a42011-02-01 18:35:28 +00002068 {
2069 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00002070 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002071 if (!success)
2072 return false;
2073 bool single_regs;
2074 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2075 uint32_t imm32; // stack offset
2076 uint32_t regs; // number of registers
2077 switch (encoding) {
2078 case eEncodingT1:
2079 case eEncodingA1:
2080 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00002081 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00002082 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2083 // If UInt(imm8) is odd, see "FLDMX".
2084 regs = Bits32(opcode, 7, 0) / 2;
2085 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2086 if (regs == 0 || regs > 16 || (d + regs) > 32)
2087 return false;
2088 break;
2089 case eEncodingT2:
2090 case eEncodingA2:
2091 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00002092 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00002093 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2094 regs = Bits32(opcode, 7, 0);
2095 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2096 if (regs == 0 || regs > 16 || (d + regs) > 32)
2097 return false;
2098 break;
2099 default:
2100 return false;
2101 }
2102 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2103 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2104 addr_t sp_offset = imm32;
2105 addr_t addr = sp;
2106 uint32_t i;
2107 uint64_t data; // uint64_t to accomodate 64-bit registers.
2108
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002109 EmulateInstruction::Context context;
Greg Clayton107e53d2011-07-06 04:07:21 +00002110 if (conditional)
2111 context.type = EmulateInstruction::eContextRegisterLoad;
2112 else
2113 context.type = EmulateInstruction::eContextPopRegisterOffStack;
Greg Claytonc07d4512011-04-26 23:48:45 +00002114 RegisterInfo dwarf_reg;
2115 RegisterInfo sp_reg;
2116 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002117 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00002118 {
Greg Claytonc07d4512011-04-26 23:48:45 +00002119 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002120 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00002121 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00002122 if (!success)
2123 return false;
Greg Clayton061b79d2011-05-09 20:18:18 +00002124 if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00002125 return false;
2126 addr += reg_byte_size;
2127 }
2128
2129 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002130 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00002131
2132 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2133 return false;
2134 }
2135 return true;
2136}
2137
Johnny Chenb77be412011-02-04 00:40:18 +00002138// SVC (previously SWI)
2139bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002140EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002141{
2142#if 0
2143 // ARM pseudo code...
2144 if (ConditionPassed())
2145 {
2146 EncodingSpecificOperations();
2147 CallSupervisor();
2148 }
2149#endif
2150
2151 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002152
Greg Clayton7bc39082011-03-24 23:53:38 +00002153 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002154 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002155 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002156 addr_t lr; // next instruction address
2157 if (!success)
2158 return false;
2159 uint32_t imm32; // the immediate constant
2160 uint32_t mode; // ARM or Thumb mode
2161 switch (encoding) {
2162 case eEncodingT1:
2163 lr = (pc + 2) | 1u; // return address
2164 imm32 = Bits32(opcode, 7, 0);
2165 mode = eModeThumb;
2166 break;
2167 case eEncodingA1:
2168 lr = pc + 4; // return address
2169 imm32 = Bits32(opcode, 23, 0);
2170 mode = eModeARM;
2171 break;
2172 default:
2173 return false;
2174 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002175
2176 EmulateInstruction::Context context;
2177 context.type = EmulateInstruction::eContextSupervisorCall;
Greg Claytonc07d4512011-04-26 23:48:45 +00002178 context.SetISAAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002179 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2180 return false;
2181 }
2182 return true;
2183}
2184
Johnny Chenc315f862011-02-05 00:46:10 +00002185// If Then makes up to four following instructions (the IT block) conditional.
2186bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002187EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002188{
2189#if 0
2190 // ARM pseudo code...
2191 EncodingSpecificOperations();
2192 ITSTATE.IT<7:0> = firstcond:mask;
2193#endif
2194
Johnny Chenc315f862011-02-05 00:46:10 +00002195 m_it_session.InitIT(Bits32(opcode, 7, 0));
2196 return true;
2197}
2198
Greg Clayton04d397c2011-05-23 18:04:09 +00002199bool
2200EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding)
2201{
2202 // NOP, nothing to do...
2203 return true;
2204}
2205
Johnny Chen3b620b32011-02-07 20:11:47 +00002206// Branch causes a branch to a target address.
2207bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002208EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002209{
2210#if 0
2211 // ARM pseudo code...
2212 if (ConditionPassed())
2213 {
2214 EncodingSpecificOperations();
2215 BranchWritePC(PC + imm32);
2216 }
2217#endif
2218
2219 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002220
Greg Clayton7bc39082011-03-24 23:53:38 +00002221 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002222 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002223 EmulateInstruction::Context context;
2224 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002225 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002226 if (!success)
2227 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002228 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002229 int32_t imm32; // PC-relative offset
2230 switch (encoding) {
2231 case eEncodingT1:
2232 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2233 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002234 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002235 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002236 break;
2237 case eEncodingT2:
2238 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002239 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002240 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002241 break;
2242 case eEncodingT3:
2243 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2244 {
Johnny Chenbd599902011-02-10 21:39:01 +00002245 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002246 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002247 uint32_t J1 = Bit32(opcode, 13);
2248 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002249 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002250 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002251 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002252 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002253 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002254 break;
2255 }
2256 case eEncodingT4:
2257 {
Johnny Chenbd599902011-02-10 21:39:01 +00002258 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002259 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002260 uint32_t J1 = Bit32(opcode, 13);
2261 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002262 uint32_t imm11 = Bits32(opcode, 10, 0);
2263 uint32_t I1 = !(J1 ^ S);
2264 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002265 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002266 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002267 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002268 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002269 break;
2270 }
2271 case eEncodingA1:
2272 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002273 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002274 context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002275 break;
2276 default:
2277 return false;
2278 }
2279 if (!BranchWritePC(context, target))
2280 return false;
2281 }
2282 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002283}
2284
Johnny Chen53ebab72011-02-08 23:21:57 +00002285// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2286// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2287// CBNZ, CBZ
2288bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002289EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002290{
2291#if 0
2292 // ARM pseudo code...
2293 EncodingSpecificOperations();
2294 if nonzero ^ IsZero(R[n]) then
2295 BranchWritePC(PC + imm32);
2296#endif
2297
2298 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002299
2300 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002301 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002302 if (!success)
2303 return false;
2304
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002305 EmulateInstruction::Context context;
2306 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002307 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002308 if (!success)
2309 return false;
2310
2311 addr_t target; // target address
2312 uint32_t imm32; // PC-relative offset to branch forward
2313 bool nonzero;
2314 switch (encoding) {
2315 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002316 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002317 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002318 target = pc + imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +00002319 context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002320 break;
2321 default:
2322 return false;
2323 }
2324 if (nonzero ^ (reg_val == 0))
2325 if (!BranchWritePC(context, target))
2326 return false;
2327
2328 return true;
2329}
2330
Johnny Chen60299ec2011-02-17 19:34:27 +00002331// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2332// A base register provides a pointer to the table, and a second register supplies an index into the table.
2333// The branch length is twice the value of the byte returned from the table.
2334//
2335// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2336// A base register provides a pointer to the table, and a second register supplies an index into the table.
2337// The branch length is twice the value of the halfword returned from the table.
2338// TBB, TBH
2339bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002340EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002341{
2342#if 0
2343 // ARM pseudo code...
2344 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2345 if is_tbh then
2346 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2347 else
2348 halfwords = UInt(MemU[R[n]+R[m], 1]);
2349 BranchWritePC(PC + 2*halfwords);
2350#endif
2351
2352 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002353
2354 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2355 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2356 bool is_tbh; // true if table branch halfword
2357 switch (encoding) {
2358 case eEncodingT1:
2359 Rn = Bits32(opcode, 19, 16);
2360 Rm = Bits32(opcode, 3, 0);
2361 is_tbh = BitIsSet(opcode, 4);
2362 if (Rn == 13 || BadReg(Rm))
2363 return false;
2364 if (InITBlock() && !LastInITBlock())
2365 return false;
2366 break;
2367 default:
2368 return false;
2369 }
2370
2371 // Read the address of the table from the operand register Rn.
2372 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002373 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002374 if (!success)
2375 return false;
2376
2377 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002378 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002379 if (!success)
2380 return false;
2381
2382 // the offsetted table address
2383 addr_t addr = base + (is_tbh ? index*2 : index);
2384
2385 // PC-relative offset to branch forward
2386 EmulateInstruction::Context context;
2387 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002388 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002389 if (!success)
2390 return false;
2391
Johnny Chene39f22d2011-02-19 01:36:13 +00002392 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002393 if (!success)
2394 return false;
2395
2396 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002397 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002398 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Greg Claytonc07d4512011-04-26 23:48:45 +00002399 context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
Johnny Chen60299ec2011-02-17 19:34:27 +00002400
2401 if (!BranchWritePC(context, target))
2402 return false;
2403
2404 return true;
2405}
2406
Caroline Ticedcc11b32011-03-02 23:57:02 +00002407// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2408// It can optionally update the condition flags based on the result.
2409bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002410EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002411{
2412#if 0
2413 if ConditionPassed() then
2414 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002415 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002416 R[d] = result;
2417 if setflags then
2418 APSR.N = result<31>;
2419 APSR.Z = IsZeroBit(result);
2420 APSR.C = carry;
2421 APSR.V = overflow;
2422#endif
2423
2424 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002425
Greg Clayton7bc39082011-03-24 23:53:38 +00002426 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002427 {
2428 uint32_t d;
2429 uint32_t n;
2430 bool setflags;
2431 uint32_t imm32;
2432 uint32_t carry_out;
2433
2434 //EncodingSpecificOperations();
2435 switch (encoding)
2436 {
2437 case eEncodingT1:
2438 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2439 d = Bits32 (opcode, 2, 0);
2440 n = Bits32 (opcode, 5, 3);
2441 setflags = !InITBlock();
2442 imm32 = Bits32 (opcode, 8,6);
2443
2444 break;
2445
2446 case eEncodingT2:
2447 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2448 d = Bits32 (opcode, 10, 8);
2449 n = Bits32 (opcode, 10, 8);
2450 setflags = !InITBlock();
2451 imm32 = Bits32 (opcode, 7, 0);
2452
2453 break;
2454
2455 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002456 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2457 // if Rn == '1101' then SEE ADD (SP plus immediate);
2458 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002459 d = Bits32 (opcode, 11, 8);
2460 n = Bits32 (opcode, 19, 16);
2461 setflags = BitIsSet (opcode, 20);
2462 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2463
2464 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2465 if (BadReg (d) || (n == 15))
2466 return false;
2467
2468 break;
2469
2470 case eEncodingT4:
2471 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002472 // if Rn == '1111' then SEE ADR;
2473 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002474 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2475 d = Bits32 (opcode, 11, 8);
2476 n = Bits32 (opcode, 19, 16);
2477 setflags = false;
2478 uint32_t i = Bit32 (opcode, 26);
2479 uint32_t imm3 = Bits32 (opcode, 14, 12);
2480 uint32_t imm8 = Bits32 (opcode, 7, 0);
2481 imm32 = (i << 11) | (imm3 << 8) | imm8;
2482
2483 // if BadReg(d) then UNPREDICTABLE;
2484 if (BadReg (d))
2485 return false;
2486
2487 break;
2488 }
2489 default:
2490 return false;
2491 }
2492
2493 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2494 if (!success)
2495 return false;
2496
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002497 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002498 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2499
Greg Claytonc07d4512011-04-26 23:48:45 +00002500 RegisterInfo reg_n;
2501 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002502
2503 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002504 context.type = eContextArithmetic;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002505 context.SetRegisterPlusOffset (reg_n, imm32);
2506
2507 //R[d] = result;
2508 //if setflags then
2509 //APSR.N = result<31>;
2510 //APSR.Z = IsZeroBit(result);
2511 //APSR.C = carry;
2512 //APSR.V = overflow;
2513 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2514 return false;
2515
2516 }
2517 return true;
2518}
2519
Johnny Chen8fa20592011-02-18 01:22:22 +00002520// This instruction adds an immediate value to a register value, and writes the result to the destination
2521// register. It can optionally update the condition flags based on the result.
2522bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002523EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002524{
2525#if 0
2526 // ARM pseudo code...
2527 if ConditionPassed() then
2528 EncodingSpecificOperations();
2529 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2530 if d == 15 then
2531 ALUWritePC(result); // setflags is always FALSE here
2532 else
2533 R[d] = result;
2534 if setflags then
2535 APSR.N = result<31>;
2536 APSR.Z = IsZeroBit(result);
2537 APSR.C = carry;
2538 APSR.V = overflow;
2539#endif
2540
2541 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002542
Greg Clayton7bc39082011-03-24 23:53:38 +00002543 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002544 {
2545 uint32_t Rd, Rn;
2546 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2547 bool setflags;
2548 switch (encoding)
2549 {
2550 case eEncodingA1:
2551 Rd = Bits32(opcode, 15, 12);
2552 Rn = Bits32(opcode, 19, 16);
2553 setflags = BitIsSet(opcode, 20);
2554 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2555 break;
2556 default:
2557 return false;
2558 }
2559
Johnny Chen8fa20592011-02-18 01:22:22 +00002560 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002561 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002562 if (!success)
2563 return false;
2564
2565 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2566
2567 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002568 context.type = eContextArithmetic;
2569 RegisterInfo dwarf_reg;
2570 GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
Caroline Tice080bf612011-04-05 18:46:00 +00002571 context.SetRegisterPlusOffset (dwarf_reg, imm32);
Johnny Chen8fa20592011-02-18 01:22:22 +00002572
2573 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2574 return false;
2575 }
2576 return true;
2577}
2578
Johnny Chend761dcf2011-02-17 22:03:29 +00002579// This instruction adds a register value and an optionally-shifted register value, and writes the result
2580// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002581bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002582EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002583{
2584#if 0
2585 // ARM pseudo code...
2586 if ConditionPassed() then
2587 EncodingSpecificOperations();
2588 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2589 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2590 if d == 15 then
2591 ALUWritePC(result); // setflags is always FALSE here
2592 else
2593 R[d] = result;
2594 if setflags then
2595 APSR.N = result<31>;
2596 APSR.Z = IsZeroBit(result);
2597 APSR.C = carry;
2598 APSR.V = overflow;
2599#endif
2600
2601 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002602
Greg Clayton7bc39082011-03-24 23:53:38 +00002603 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002604 {
2605 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002606 ARM_ShifterType shift_t;
2607 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002608 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002609 switch (encoding)
2610 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002611 case eEncodingT1:
2612 Rd = Bits32(opcode, 2, 0);
2613 Rn = Bits32(opcode, 5, 3);
2614 Rm = Bits32(opcode, 8, 6);
2615 setflags = !InITBlock();
2616 shift_t = SRType_LSL;
2617 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002618 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002619 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002620 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002621 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002622 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002623 shift_t = SRType_LSL;
2624 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002625 if (Rn == 15 && Rm == 15)
2626 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002627 if (Rd == 15 && InITBlock() && !LastInITBlock())
2628 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002629 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002630 case eEncodingA1:
2631 Rd = Bits32(opcode, 15, 12);
2632 Rn = Bits32(opcode, 19, 16);
2633 Rm = Bits32(opcode, 3, 0);
2634 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002635 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002636 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002637 default:
2638 return false;
2639 }
2640
Johnny Chen26863dc2011-02-09 23:43:29 +00002641 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002642 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002643 if (!success)
2644 return false;
2645
2646 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002647 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002648 if (!success)
2649 return false;
2650
Johnny Chena4438a72011-06-02 22:50:51 +00002651 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2652 if (!success)
2653 return false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002654 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002655
2656 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00002657 context.type = eContextArithmetic;
2658 RegisterInfo op1_reg;
2659 RegisterInfo op2_reg;
2660 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
2661 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00002662 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002663
Johnny Chen10530c22011-02-17 22:37:12 +00002664 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002665 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002666 }
2667 return true;
2668}
2669
Johnny Chen34075cb2011-02-22 01:56:31 +00002670// Compare Negative (immediate) adds a register value and an immediate value.
2671// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002672bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002673EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002674{
2675#if 0
2676 // ARM pseudo code...
2677 if ConditionPassed() then
2678 EncodingSpecificOperations();
2679 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2680 APSR.N = result<31>;
2681 APSR.Z = IsZeroBit(result);
2682 APSR.C = carry;
2683 APSR.V = overflow;
2684#endif
2685
2686 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002687
2688 uint32_t Rn; // the first operand
2689 uint32_t imm32; // the immediate value to be compared with
2690 switch (encoding) {
2691 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002692 Rn = Bits32(opcode, 19, 16);
2693 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2694 if (Rn == 15)
2695 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002696 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002697 case eEncodingA1:
2698 Rn = Bits32(opcode, 19, 16);
2699 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2700 break;
2701 default:
2702 return false;
2703 }
2704 // Read the register value from the operand register Rn.
2705 uint32_t reg_val = ReadCoreReg(Rn, &success);
2706 if (!success)
2707 return false;
2708
Johnny Chen078fbc62011-02-22 19:48:22 +00002709 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002710
2711 EmulateInstruction::Context context;
2712 context.type = EmulateInstruction::eContextImmediate;
2713 context.SetNoArgs ();
2714 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2715 return false;
2716
2717 return true;
2718}
2719
2720// Compare Negative (register) adds a register value and an optionally-shifted register value.
2721// It updates the condition flags based on the result, and discards the result.
2722bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002723EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002724{
2725#if 0
2726 // ARM pseudo code...
2727 if ConditionPassed() then
2728 EncodingSpecificOperations();
2729 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2730 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2731 APSR.N = result<31>;
2732 APSR.Z = IsZeroBit(result);
2733 APSR.C = carry;
2734 APSR.V = overflow;
2735#endif
2736
2737 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002738
2739 uint32_t Rn; // the first operand
2740 uint32_t Rm; // the second operand
2741 ARM_ShifterType shift_t;
2742 uint32_t shift_n; // the shift applied to the value read from Rm
2743 switch (encoding) {
2744 case eEncodingT1:
2745 Rn = Bits32(opcode, 2, 0);
2746 Rm = Bits32(opcode, 5, 3);
2747 shift_t = SRType_LSL;
2748 shift_n = 0;
2749 break;
2750 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002751 Rn = Bits32(opcode, 19, 16);
2752 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002753 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002754 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2755 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002756 return false;
2757 break;
2758 case eEncodingA1:
2759 Rn = Bits32(opcode, 19, 16);
2760 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002761 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002762 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002763 default:
2764 return false;
2765 }
2766 // Read the register value from register Rn.
2767 uint32_t val1 = ReadCoreReg(Rn, &success);
2768 if (!success)
2769 return false;
2770
2771 // Read the register value from register Rm.
2772 uint32_t val2 = ReadCoreReg(Rm, &success);
2773 if (!success)
2774 return false;
2775
Johnny Chena4438a72011-06-02 22:50:51 +00002776 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2777 if (!success)
2778 return false;
Johnny Chen078fbc62011-02-22 19:48:22 +00002779 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002780
2781 EmulateInstruction::Context context;
2782 context.type = EmulateInstruction::eContextImmediate;
2783 context.SetNoArgs();
2784 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2785 return false;
2786
2787 return true;
2788}
2789
2790// Compare (immediate) subtracts an immediate value from a register value.
2791// It updates the condition flags based on the result, and discards the result.
2792bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002793EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002794{
2795#if 0
2796 // ARM pseudo code...
2797 if ConditionPassed() then
2798 EncodingSpecificOperations();
2799 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2800 APSR.N = result<31>;
2801 APSR.Z = IsZeroBit(result);
2802 APSR.C = carry;
2803 APSR.V = overflow;
2804#endif
2805
2806 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002807
2808 uint32_t Rn; // the first operand
2809 uint32_t imm32; // the immediate value to be compared with
2810 switch (encoding) {
2811 case eEncodingT1:
2812 Rn = Bits32(opcode, 10, 8);
2813 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002814 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002815 case eEncodingT2:
2816 Rn = Bits32(opcode, 19, 16);
2817 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2818 if (Rn == 15)
2819 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002820 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002821 case eEncodingA1:
2822 Rn = Bits32(opcode, 19, 16);
2823 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002824 break;
2825 default:
2826 return false;
2827 }
2828 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002829 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002830 if (!success)
2831 return false;
2832
Johnny Chen10530c22011-02-17 22:37:12 +00002833 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2834
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002835 EmulateInstruction::Context context;
2836 context.type = EmulateInstruction::eContextImmediate;
2837 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002838 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2839 return false;
2840
Johnny Chend4dc4442011-02-11 02:02:56 +00002841 return true;
2842}
2843
Johnny Chen34075cb2011-02-22 01:56:31 +00002844// Compare (register) subtracts an optionally-shifted register value from a register value.
2845// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002846bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002847EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002848{
2849#if 0
2850 // ARM pseudo code...
2851 if ConditionPassed() then
2852 EncodingSpecificOperations();
2853 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2854 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2855 APSR.N = result<31>;
2856 APSR.Z = IsZeroBit(result);
2857 APSR.C = carry;
2858 APSR.V = overflow;
2859#endif
2860
2861 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002862
2863 uint32_t Rn; // the first operand
2864 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002865 ARM_ShifterType shift_t;
2866 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002867 switch (encoding) {
2868 case eEncodingT1:
2869 Rn = Bits32(opcode, 2, 0);
2870 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002871 shift_t = SRType_LSL;
2872 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002873 break;
2874 case eEncodingT2:
2875 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2876 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002877 shift_t = SRType_LSL;
2878 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002879 if (Rn < 8 && Rm < 8)
2880 return false;
2881 if (Rn == 15 || Rm == 15)
2882 return false;
2883 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002884 case eEncodingA1:
2885 Rn = Bits32(opcode, 19, 16);
2886 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002887 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002888 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002889 default:
2890 return false;
2891 }
2892 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002893 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002894 if (!success)
2895 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002896
Johnny Chene4a4d302011-02-11 21:53:58 +00002897 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002898 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002899 if (!success)
2900 return false;
2901
Johnny Chena4438a72011-06-02 22:50:51 +00002902 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
2903 if (!success)
2904 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002905 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002906
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002907 EmulateInstruction::Context context;
2908 context.type = EmulateInstruction::eContextImmediate;
2909 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002910 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2911 return false;
2912
Johnny Chene4a4d302011-02-11 21:53:58 +00002913 return true;
2914}
2915
Johnny Chen82f16aa2011-02-15 20:10:55 +00002916// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2917// shifting in copies of its sign bit, and writes the result to the destination register. It can
2918// optionally update the condition flags based on the result.
2919bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002920EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002921{
2922#if 0
2923 // ARM pseudo code...
2924 if ConditionPassed() then
2925 EncodingSpecificOperations();
2926 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2927 if d == 15 then // Can only occur for ARM encoding
2928 ALUWritePC(result); // setflags is always FALSE here
2929 else
2930 R[d] = result;
2931 if setflags then
2932 APSR.N = result<31>;
2933 APSR.Z = IsZeroBit(result);
2934 APSR.C = carry;
2935 // APSR.V unchanged
2936#endif
2937
Greg Clayton7bc39082011-03-24 23:53:38 +00002938 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002939}
2940
2941// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2942// shifting in copies of its sign bit, and writes the result to the destination register.
2943// The variable number of bits is read from the bottom byte of a register. It can optionally update
2944// the condition flags based on the result.
2945bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002946EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002947{
2948#if 0
2949 // ARM pseudo code...
2950 if ConditionPassed() then
2951 EncodingSpecificOperations();
2952 shift_n = UInt(R[m]<7:0>);
2953 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2954 R[d] = result;
2955 if setflags then
2956 APSR.N = result<31>;
2957 APSR.Z = IsZeroBit(result);
2958 APSR.C = carry;
2959 // APSR.V unchanged
2960#endif
2961
Greg Clayton7bc39082011-03-24 23:53:38 +00002962 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002963}
2964
2965// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2966// shifting in zeros, and writes the result to the destination register. It can optionally
2967// update the condition flags based on the result.
2968bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002969EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002970{
2971#if 0
2972 // ARM pseudo code...
2973 if ConditionPassed() then
2974 EncodingSpecificOperations();
2975 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2976 if d == 15 then // Can only occur for ARM encoding
2977 ALUWritePC(result); // setflags is always FALSE here
2978 else
2979 R[d] = result;
2980 if setflags then
2981 APSR.N = result<31>;
2982 APSR.Z = IsZeroBit(result);
2983 APSR.C = carry;
2984 // APSR.V unchanged
2985#endif
2986
Greg Clayton7bc39082011-03-24 23:53:38 +00002987 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002988}
2989
2990// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2991// shifting in zeros, and writes the result to the destination register. The variable number
2992// of bits is read from the bottom byte of a register. It can optionally update the condition
2993// flags based on the result.
2994bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002995EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002996{
2997#if 0
2998 // ARM pseudo code...
2999 if ConditionPassed() then
3000 EncodingSpecificOperations();
3001 shift_n = UInt(R[m]<7:0>);
3002 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3003 R[d] = result;
3004 if setflags then
3005 APSR.N = result<31>;
3006 APSR.Z = IsZeroBit(result);
3007 APSR.C = carry;
3008 // APSR.V unchanged
3009#endif
3010
Greg Clayton7bc39082011-03-24 23:53:38 +00003011 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00003012}
3013
3014// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
3015// shifting in zeros, and writes the result to the destination register. It can optionally
3016// update the condition flags based on the result.
3017bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003018EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003019{
3020#if 0
3021 // ARM pseudo code...
3022 if ConditionPassed() then
3023 EncodingSpecificOperations();
3024 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3025 if d == 15 then // Can only occur for ARM encoding
3026 ALUWritePC(result); // setflags is always FALSE here
3027 else
3028 R[d] = result;
3029 if setflags then
3030 APSR.N = result<31>;
3031 APSR.Z = IsZeroBit(result);
3032 APSR.C = carry;
3033 // APSR.V unchanged
3034#endif
3035
Greg Clayton7bc39082011-03-24 23:53:38 +00003036 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003037}
3038
3039// Logical Shift Right (register) shifts a register value right by a variable number of bits,
3040// shifting in zeros, and writes the result to the destination register. The variable number
3041// of bits is read from the bottom byte of a register. It can optionally update the condition
3042// flags based on the result.
3043bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003044EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00003045{
3046#if 0
3047 // ARM pseudo code...
3048 if ConditionPassed() then
3049 EncodingSpecificOperations();
3050 shift_n = UInt(R[m]<7:0>);
3051 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3052 R[d] = result;
3053 if setflags then
3054 APSR.N = result<31>;
3055 APSR.Z = IsZeroBit(result);
3056 APSR.C = carry;
3057 // APSR.V unchanged
3058#endif
3059
Greg Clayton7bc39082011-03-24 23:53:38 +00003060 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00003061}
3062
Johnny Cheneeab4852011-02-16 22:14:44 +00003063// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
3064// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3065// It can optionally update the condition flags based on the result.
3066bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003067EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003068{
3069#if 0
3070 // ARM pseudo code...
3071 if ConditionPassed() then
3072 EncodingSpecificOperations();
3073 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3074 if d == 15 then // Can only occur for ARM encoding
3075 ALUWritePC(result); // setflags is always FALSE here
3076 else
3077 R[d] = result;
3078 if setflags then
3079 APSR.N = result<31>;
3080 APSR.Z = IsZeroBit(result);
3081 APSR.C = carry;
3082 // APSR.V unchanged
3083#endif
3084
Greg Clayton7bc39082011-03-24 23:53:38 +00003085 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003086}
3087
3088// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
3089// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
3090// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
3091// flags based on the result.
3092bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003093EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003094{
3095#if 0
3096 // ARM pseudo code...
3097 if ConditionPassed() then
3098 EncodingSpecificOperations();
3099 shift_n = UInt(R[m]<7:0>);
3100 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3101 R[d] = result;
3102 if setflags then
3103 APSR.N = result<31>;
3104 APSR.Z = IsZeroBit(result);
3105 APSR.C = carry;
3106 // APSR.V unchanged
3107#endif
3108
Greg Clayton7bc39082011-03-24 23:53:38 +00003109 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00003110}
3111
3112// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3113// with the carry flag shifted into bit [31].
3114//
3115// RRX can optionally update the condition flags based on the result.
3116// In that case, bit [0] is shifted into the carry flag.
3117bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003118EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00003119{
3120#if 0
3121 // ARM pseudo code...
3122 if ConditionPassed() then
3123 EncodingSpecificOperations();
3124 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3125 if d == 15 then // Can only occur for ARM encoding
3126 ALUWritePC(result); // setflags is always FALSE here
3127 else
3128 R[d] = result;
3129 if setflags then
3130 APSR.N = result<31>;
3131 APSR.Z = IsZeroBit(result);
3132 APSR.C = carry;
3133 // APSR.V unchanged
3134#endif
3135
Greg Clayton7bc39082011-03-24 23:53:38 +00003136 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00003137}
3138
Johnny Chen41a0a152011-02-16 01:27:54 +00003139bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003140EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00003141{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003142// assert(shift_type == SRType_ASR
3143// || shift_type == SRType_LSL
3144// || shift_type == SRType_LSR
3145// || shift_type == SRType_ROR
3146// || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00003147
Johnny Chen82f16aa2011-02-15 20:10:55 +00003148 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003149
Greg Clayton7bc39082011-03-24 23:53:38 +00003150 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00003151 {
Johnny Chene7f89532011-02-15 23:22:46 +00003152 uint32_t Rd; // the destination register
3153 uint32_t Rm; // the first operand register
3154 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003155 uint32_t carry; // the carry bit after the shift operation
3156 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003157
3158 // Special case handling!
3159 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003160 ARMEncoding use_encoding = encoding;
3161 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003162 {
3163 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3164 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003165 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003166 }
3167
Greg Clayton7bc39082011-03-24 23:53:38 +00003168 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003169 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003170 // Due to the above special case handling!
Johnny Chen6cc60972011-06-02 23:07:03 +00003171 if (shift_type == SRType_ROR)
3172 return false;
Johnny Cheneeab4852011-02-16 22:14:44 +00003173
Johnny Chen82f16aa2011-02-15 20:10:55 +00003174 Rd = Bits32(opcode, 2, 0);
3175 Rm = Bits32(opcode, 5, 3);
3176 setflags = !InITBlock();
3177 imm5 = Bits32(opcode, 10, 6);
3178 break;
3179 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003180 // A8.6.141 RRX
Johnny Chen6cc60972011-06-02 23:07:03 +00003181 // There's no imm form of RRX instructions.
3182 if (shift_type == SRType_RRX)
3183 return false;
Johnny Cheneeab4852011-02-16 22:14:44 +00003184
Johnny Chen82f16aa2011-02-15 20:10:55 +00003185 Rd = Bits32(opcode, 11, 8);
3186 Rm = Bits32(opcode, 3, 0);
3187 setflags = BitIsSet(opcode, 20);
3188 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3189 if (BadReg(Rd) || BadReg(Rm))
3190 return false;
3191 break;
3192 case eEncodingA1:
3193 Rd = Bits32(opcode, 15, 12);
3194 Rm = Bits32(opcode, 3, 0);
3195 setflags = BitIsSet(opcode, 20);
3196 imm5 = Bits32(opcode, 11, 7);
3197 break;
3198 default:
3199 return false;
3200 }
3201
Johnny Cheneeab4852011-02-16 22:14:44 +00003202 // A8.6.139 ROR (immediate)
3203 if (shift_type == SRType_ROR && imm5 == 0)
3204 shift_type = SRType_RRX;
3205
Johnny Chen82f16aa2011-02-15 20:10:55 +00003206 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003207 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003208 if (!success)
3209 return false;
3210
Johnny Cheneeab4852011-02-16 22:14:44 +00003211 // Decode the shift amount if not RRX.
3212 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003213
Johnny Chena4438a72011-06-02 22:50:51 +00003214 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3215 if (!success)
3216 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003217
3218 // The context specifies that an immediate is to be moved into Rd.
3219 EmulateInstruction::Context context;
3220 context.type = EmulateInstruction::eContextImmediate;
3221 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003222
Johnny Chen10530c22011-02-17 22:37:12 +00003223 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003224 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003225 }
3226 return true;
3227}
3228
Johnny Chene7f89532011-02-15 23:22:46 +00003229bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003230EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003231{
Greg Claytone1f47bb2011-06-02 22:23:35 +00003232 // assert(shift_type == SRType_ASR
3233 // || shift_type == SRType_LSL
3234 // || shift_type == SRType_LSR
3235 // || shift_type == SRType_ROR);
Johnny Chene7f89532011-02-15 23:22:46 +00003236
3237 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003238
Greg Clayton7bc39082011-03-24 23:53:38 +00003239 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003240 {
3241 uint32_t Rd; // the destination register
3242 uint32_t Rn; // the first operand register
3243 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3244 uint32_t carry; // the carry bit after the shift operation
3245 bool setflags;
3246 switch (encoding) {
3247 case eEncodingT1:
3248 Rd = Bits32(opcode, 2, 0);
3249 Rn = Rd;
3250 Rm = Bits32(opcode, 5, 3);
3251 setflags = !InITBlock();
3252 break;
3253 case eEncodingT2:
3254 Rd = Bits32(opcode, 11, 8);
3255 Rn = Bits32(opcode, 19, 16);
3256 Rm = Bits32(opcode, 3, 0);
3257 setflags = BitIsSet(opcode, 20);
3258 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3259 return false;
3260 break;
3261 case eEncodingA1:
3262 Rd = Bits32(opcode, 15, 12);
3263 Rn = Bits32(opcode, 3, 0);
3264 Rm = Bits32(opcode, 11, 8);
3265 setflags = BitIsSet(opcode, 20);
3266 if (Rd == 15 || Rn == 15 || Rm == 15)
3267 return false;
3268 break;
3269 default:
3270 return false;
3271 }
3272
3273 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003274 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003275 if (!success)
3276 return false;
3277 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003278 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003279 if (!success)
3280 return false;
3281
3282 // Get the shift amount.
3283 uint32_t amt = Bits32(val, 7, 0);
3284
Johnny Chena4438a72011-06-02 22:50:51 +00003285 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3286 if (!success)
3287 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003288
3289 // The context specifies that an immediate is to be moved into Rd.
3290 EmulateInstruction::Context context;
3291 context.type = EmulateInstruction::eContextImmediate;
3292 context.SetNoArgs ();
3293
Johnny Chen10530c22011-02-17 22:37:12 +00003294 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003295 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003296 }
3297 return true;
3298}
3299
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003300// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003301// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003302// can be written back to the base register.
3303bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003304EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003305{
3306#if 0
3307 // ARM pseudo code...
3308 if ConditionPassed()
3309 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3310 address = R[n];
3311
3312 for i = 0 to 14
3313 if registers<i> == '1' then
3314 R[i] = MemA[address, 4]; address = address + 4;
3315 if registers<15> == '1' then
3316 LoadWritePC (MemA[address, 4]);
3317
3318 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3319 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3320
3321#endif
3322
3323 bool success = false;
Greg Clayton107e53d2011-07-06 04:07:21 +00003324 bool conditional = false;
3325 if (ConditionPassed(opcode, &conditional))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003326 {
3327 uint32_t n;
3328 uint32_t registers = 0;
3329 bool wback;
3330 const uint32_t addr_byte_size = GetAddressByteSize();
3331 switch (encoding)
3332 {
3333 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003334 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003335 n = Bits32 (opcode, 10, 8);
3336 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003337 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003338 wback = BitIsClear (registers, n);
3339 // if BitCount(registers) < 1 then UNPREDICTABLE;
3340 if (BitCount(registers) < 1)
3341 return false;
3342 break;
3343 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003344 // if W == '1' && Rn == '1101' then SEE POP;
3345 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003346 n = Bits32 (opcode, 19, 16);
3347 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003348 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003349 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003350
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003351 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003352 if ((n == 15)
3353 || (BitCount (registers) < 2)
3354 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3355 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003356
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003357 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003358 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003359 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003360
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003361 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003362 if (wback
3363 && BitIsSet (registers, n))
3364 return false;
3365 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003366
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003367 case eEncodingA1:
3368 n = Bits32 (opcode, 19, 16);
3369 registers = Bits32 (opcode, 15, 0);
3370 wback = BitIsSet (opcode, 21);
3371 if ((n == 15)
3372 || (BitCount (registers) < 1))
3373 return false;
3374 break;
3375 default:
3376 return false;
3377 }
3378
3379 int32_t offset = 0;
3380 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3381 if (!success)
3382 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003383
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003384 EmulateInstruction::Context context;
3385 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003386 RegisterInfo dwarf_reg;
3387 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003388 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003389
3390 for (int i = 0; i < 14; ++i)
3391 {
3392 if (BitIsSet (registers, i))
3393 {
Caroline Tice85aab332011-02-08 23:56:10 +00003394 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003395 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003396 if (wback && (n == 13)) // Pop Instruction
Greg Clayton107e53d2011-07-06 04:07:21 +00003397 {
3398 if (conditional)
3399 context.type = EmulateInstruction::eContextRegisterLoad;
3400 else
3401 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3402 }
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003403
3404 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003405 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003406 if (!success)
3407 return false;
3408
3409 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3410 return false;
3411
3412 offset += addr_byte_size;
3413 }
3414 }
3415
3416 if (BitIsSet (registers, 15))
3417 {
3418 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003419 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003420 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003421 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003422 if (!success)
3423 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003424 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003425 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003426 return false;
3427 }
3428
3429 if (wback && BitIsClear (registers, n))
3430 {
Caroline Ticefa172202011-02-11 22:49:54 +00003431 // R[n] = R[n] + 4 * BitCount (registers)
3432 int32_t offset = addr_byte_size * BitCount (registers);
3433 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003434 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003435
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003436 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3437 return false;
3438 }
3439 if (wback && BitIsSet (registers, n))
3440 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003441 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003442 }
3443 return true;
3444}
Caroline Tice713c2662011-02-11 17:59:55 +00003445
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003446// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3447// The consecutive memory locations end at this address and the address just below the lowest of those locations
3448// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003449bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003450EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003451{
3452#if 0
3453 // ARM pseudo code...
3454 if ConditionPassed() then
3455 EncodingSpecificOperations();
3456 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003457
Caroline Tice713c2662011-02-11 17:59:55 +00003458 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003459 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003460 R[i] = MemA[address,4]; address = address + 4;
3461
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003462 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003463 LoadWritePC(MemA[address,4]);
3464
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003465 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3466 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003467#endif
3468
3469 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003470
Greg Clayton7bc39082011-03-24 23:53:38 +00003471 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003472 {
3473 uint32_t n;
3474 uint32_t registers = 0;
3475 bool wback;
3476 const uint32_t addr_byte_size = GetAddressByteSize();
3477
3478 // EncodingSpecificOperations();
3479 switch (encoding)
3480 {
3481 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003482 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003483 n = Bits32 (opcode, 19, 16);
3484 registers = Bits32 (opcode, 15, 0);
3485 wback = BitIsSet (opcode, 21);
3486
3487 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3488 if ((n == 15) || (BitCount (registers) < 1))
3489 return false;
3490
3491 break;
3492
3493 default:
3494 return false;
3495 }
3496 // address = R[n] - 4*BitCount(registers) + 4;
3497
3498 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003499 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003500
3501 if (!success)
3502 return false;
3503
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003504 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003505
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003506 EmulateInstruction::Context context;
3507 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003508 RegisterInfo dwarf_reg;
3509 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003510 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003511
3512 // for i = 0 to 14
3513 for (int i = 0; i < 14; ++i)
3514 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003515 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003516 if (BitIsSet (registers, i))
3517 {
3518 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003519 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003520 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003521 if (!success)
3522 return false;
3523 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3524 return false;
3525 offset += addr_byte_size;
3526 }
3527 }
3528
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003529 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003530 // LoadWritePC(MemA[address,4]);
3531 if (BitIsSet (registers, 15))
3532 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003533 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003534 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003535 if (!success)
3536 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003537 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003538 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003539 return false;
3540 }
3541
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003542 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003543 if (wback && BitIsClear (registers, n))
3544 {
Caroline Tice713c2662011-02-11 17:59:55 +00003545 if (!success)
3546 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003547
3548 offset = (addr_byte_size * BitCount (registers)) * -1;
3549 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003550 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003551 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003552 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3553 return false;
3554 }
3555
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003556 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003557 if (wback && BitIsSet (registers, n))
3558 return WriteBits32Unknown (n);
3559 }
3560 return true;
3561}
3562
3563// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3564// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3565// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003566bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003567EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003568{
3569#if 0
3570 // ARM pseudo code...
3571 if ConditionPassed() then
3572 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3573 address = R[n] - 4*BitCount(registers);
3574
3575 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003576 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003577 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003578 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003579 LoadWritePC(MemA[address,4]);
3580
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003581 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3582 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003583#endif
3584
3585 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003586
Greg Clayton7bc39082011-03-24 23:53:38 +00003587 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003588 {
3589 uint32_t n;
3590 uint32_t registers = 0;
3591 bool wback;
3592 const uint32_t addr_byte_size = GetAddressByteSize();
3593 switch (encoding)
3594 {
3595 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003596 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003597 n = Bits32 (opcode, 19, 16);
3598 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003599 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003600 wback = BitIsSet (opcode, 21);
3601
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003602 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003603 if ((n == 15)
3604 || (BitCount (registers) < 2)
3605 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3606 return false;
3607
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003608 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003609 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003610 return false;
3611
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003612 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003613 if (wback && BitIsSet (registers, n))
3614 return false;
3615
3616 break;
3617
3618 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003619 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003620 n = Bits32 (opcode, 19, 16);
3621 registers = Bits32 (opcode, 15, 0);
3622 wback = BitIsSet (opcode, 21);
3623
3624 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3625 if ((n == 15) || (BitCount (registers) < 1))
3626 return false;
3627
3628 break;
3629
3630 default:
3631 return false;
3632 }
3633
Caroline Tice713c2662011-02-11 17:59:55 +00003634 // address = R[n] - 4*BitCount(registers);
3635
Caroline Tice0b29e242011-02-08 23:16:02 +00003636 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003637 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003638
3639 if (!success)
3640 return false;
3641
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003642 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003643 EmulateInstruction::Context context;
3644 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003645 RegisterInfo dwarf_reg;
3646 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003647 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003648
3649 for (int i = 0; i < 14; ++i)
3650 {
3651 if (BitIsSet (registers, i))
3652 {
3653 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003654 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003655 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003656 if (!success)
3657 return false;
3658
3659 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3660 return false;
3661
3662 offset += addr_byte_size;
3663 }
3664 }
3665
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003666 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003667 // LoadWritePC(MemA[address,4]);
3668 if (BitIsSet (registers, 15))
3669 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003670 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003671 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003672 if (!success)
3673 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003674 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003675 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003676 return false;
3677 }
3678
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003679 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003680 if (wback && BitIsClear (registers, n))
3681 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003682 if (!success)
3683 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003684
3685 offset = (addr_byte_size * BitCount (registers)) * -1;
3686 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003687 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003688 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003689 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3690 return false;
3691 }
3692
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003693 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003694 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003695 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003696 }
3697 return true;
3698}
Caroline Tice85aab332011-02-08 23:56:10 +00003699
Caroline Tice713c2662011-02-11 17:59:55 +00003700// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3701// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3702// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003703bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003704EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003705{
3706#if 0
3707 if ConditionPassed() then
3708 EncodingSpecificOperations();
3709 address = R[n] + 4;
3710
3711 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003712 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003713 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003714 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003715 LoadWritePC(MemA[address,4]);
3716
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003717 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3718 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003719#endif
3720
3721 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003722
Greg Clayton7bc39082011-03-24 23:53:38 +00003723 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003724 {
3725 uint32_t n;
3726 uint32_t registers = 0;
3727 bool wback;
3728 const uint32_t addr_byte_size = GetAddressByteSize();
3729 switch (encoding)
3730 {
3731 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003732 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003733 n = Bits32 (opcode, 19, 16);
3734 registers = Bits32 (opcode, 15, 0);
3735 wback = BitIsSet (opcode, 21);
3736
3737 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3738 if ((n == 15) || (BitCount (registers) < 1))
3739 return false;
3740
3741 break;
3742 default:
3743 return false;
3744 }
3745 // address = R[n] + 4;
3746
3747 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003748 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003749
3750 if (!success)
3751 return false;
3752
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003753 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003754
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003755 EmulateInstruction::Context context;
3756 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Greg Claytonc07d4512011-04-26 23:48:45 +00003757 RegisterInfo dwarf_reg;
3758 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003759 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003760
3761 for (int i = 0; i < 14; ++i)
3762 {
3763 if (BitIsSet (registers, i))
3764 {
3765 // R[i] = MemA[address,4]; address = address + 4;
3766
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003767 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003768 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003769 if (!success)
3770 return false;
3771
3772 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3773 return false;
3774
3775 offset += addr_byte_size;
3776 }
3777 }
3778
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003779 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003780 // LoadWritePC(MemA[address,4]);
3781 if (BitIsSet (registers, 15))
3782 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003783 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003784 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003785 if (!success)
3786 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003787 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003788 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003789 return false;
3790 }
3791
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003792 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003793 if (wback && BitIsClear (registers, n))
3794 {
Caroline Tice85aab332011-02-08 23:56:10 +00003795 if (!success)
3796 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003797
3798 offset = addr_byte_size * BitCount (registers);
3799 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003800 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003801 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003802 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3803 return false;
3804 }
3805
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003806 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003807 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003808 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003809 }
3810 return true;
3811}
Caroline Tice0b29e242011-02-08 23:16:02 +00003812
Johnny Chenef21b592011-02-10 01:52:38 +00003813// Load Register (immediate) calculates an address from a base register value and
3814// an immediate offset, loads a word from memory, and writes to a register.
3815// LDR (immediate, Thumb)
3816bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003817EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003818{
3819#if 0
3820 // ARM pseudo code...
3821 if (ConditionPassed())
3822 {
3823 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3824 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3825 address = if index then offset_addr else R[n];
3826 data = MemU[address,4];
3827 if wback then R[n] = offset_addr;
3828 if t == 15 then
3829 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3830 elsif UnalignedSupport() || address<1:0> = '00' then
3831 R[t] = data;
3832 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3833 }
3834#endif
3835
3836 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003837
Greg Clayton7bc39082011-03-24 23:53:38 +00003838 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003839 {
3840 uint32_t Rt; // the destination register
3841 uint32_t Rn; // the base register
3842 uint32_t imm32; // the immediate offset used to form the address
3843 addr_t offset_addr; // the offset address
3844 addr_t address; // the calculated address
3845 uint32_t data; // the literal data value from memory load
3846 bool add, index, wback;
3847 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003848 case eEncodingT1:
Caroline Tice55e569e2011-04-13 21:49:04 +00003849 Rt = Bits32(opcode, 2, 0);
3850 Rn = Bits32(opcode, 5, 3);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003851 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3852 // index = TRUE; add = TRUE; wback = FALSE
3853 add = true;
3854 index = true;
3855 wback = false;
3856
3857 break;
3858
3859 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003860 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003861 Rt = Bits32 (opcode, 10, 8);
3862 Rn = 13;
3863 imm32 = Bits32 (opcode, 7, 0) << 2;
3864
3865 // index = TRUE; add = TRUE; wback = FALSE;
3866 index = true;
3867 add = true;
3868 wback = false;
3869
3870 break;
3871
3872 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003873 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003874 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3875 Rt = Bits32 (opcode, 15, 12);
3876 Rn = Bits32 (opcode, 19, 16);
3877 imm32 = Bits32 (opcode, 11, 0);
3878
3879 // index = TRUE; add = TRUE; wback = FALSE;
3880 index = true;
3881 add = true;
3882 wback = false;
3883
3884 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3885 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3886 return false;
3887
3888 break;
3889
3890 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003891 // if Rn == '1111' then SEE LDR (literal);
3892 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3893 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3894 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003895 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3896 return false;
3897
3898 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3899 Rt = Bits32 (opcode, 15, 12);
3900 Rn = Bits32 (opcode, 19, 16);
3901 imm32 = Bits32 (opcode, 7, 0);
3902
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003903 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003904 index = BitIsSet (opcode, 10);
3905 add = BitIsSet (opcode, 9);
3906 wback = BitIsSet (opcode, 8);
3907
3908 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3909 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3910 return false;
3911
3912 break;
3913
3914 default:
3915 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003916 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003917 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003918 if (!success)
3919 return false;
3920 if (add)
3921 offset_addr = base + imm32;
3922 else
3923 offset_addr = base - imm32;
3924
3925 address = (index ? offset_addr : base);
3926
Greg Claytonc07d4512011-04-26 23:48:45 +00003927 RegisterInfo base_reg;
3928 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
Johnny Chenef21b592011-02-10 01:52:38 +00003929 if (wback)
3930 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003931 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003932 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3933 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003934
Johnny Chenef21b592011-02-10 01:52:38 +00003935 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3936 return false;
3937 }
3938
3939 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003940 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003941 context.type = EmulateInstruction::eContextRegisterLoad;
3942 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003943
3944 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003945 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003946 if (!success)
3947 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003948
3949 if (Rt == 15)
3950 {
3951 if (Bits32(address, 1, 0) == 0)
3952 {
Johnny Chen668b4512011-02-15 21:08:58 +00003953 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003954 return false;
3955 }
3956 else
3957 return false;
3958 }
3959 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3960 {
3961 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3962 return false;
3963 }
3964 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003965 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003966 }
3967 return true;
3968}
3969
Caroline Ticeaf556562011-02-15 18:42:15 +00003970// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3971// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3972// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003973bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003974EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003975{
3976#if 0
3977 if ConditionPassed() then
3978 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3979 address = R[n];
3980
3981 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003982 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003983 if i == n && wback && i != LowestSetBit(registers) then
3984 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3985 else
3986 MemA[address,4] = R[i];
3987 address = address + 4;
3988
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003989 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003990 MemA[address,4] = PCStoreValue();
3991 if wback then R[n] = R[n] + 4*BitCount(registers);
3992#endif
3993
3994 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003995
Greg Clayton7bc39082011-03-24 23:53:38 +00003996 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003997 {
3998 uint32_t n;
3999 uint32_t registers = 0;
4000 bool wback;
4001 const uint32_t addr_byte_size = GetAddressByteSize();
4002
4003 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4004 switch (encoding)
4005 {
4006 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004007 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00004008 n = Bits32 (opcode, 10, 8);
4009 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004010 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00004011 wback = true;
4012
4013 // if BitCount(registers) < 1 then UNPREDICTABLE;
4014 if (BitCount (registers) < 1)
4015 return false;
4016
4017 break;
4018
4019 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004020 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00004021 n = Bits32 (opcode, 19, 16);
4022 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004023 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00004024 wback = BitIsSet (opcode, 21);
4025
4026 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4027 if ((n == 15) || (BitCount (registers) < 2))
4028 return false;
4029
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004030 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00004031 if (wback && BitIsSet (registers, n))
4032 return false;
4033
4034 break;
4035
4036 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004037 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00004038 n = Bits32 (opcode, 19, 16);
4039 registers = Bits32 (opcode, 15, 0);
4040 wback = BitIsSet (opcode, 21);
4041
4042 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4043 if ((n == 15) || (BitCount (registers) < 1))
4044 return false;
4045
4046 break;
4047
4048 default:
4049 return false;
4050 }
4051
4052 // address = R[n];
4053 int32_t offset = 0;
4054 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4055 if (!success)
4056 return false;
4057
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004058 EmulateInstruction::Context context;
4059 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004060 RegisterInfo base_reg;
4061 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefa172202011-02-11 22:49:54 +00004062
4063 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004064 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00004065 for (int i = 0; i < 14; ++i)
4066 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004067 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00004068 if (BitIsSet (registers, i))
4069 {
4070 if (i < lowest_set_bit)
4071 lowest_set_bit = i;
4072 // if i == n && wback && i != LowestSetBit(registers) then
4073 if ((i == n) && wback && (i != lowest_set_bit))
4074 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4075 WriteBits32UnknownToMemory (address + offset);
4076 else
4077 {
4078 // MemA[address,4] = R[i];
4079 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4080 if (!success)
4081 return false;
4082
Greg Claytonc07d4512011-04-26 23:48:45 +00004083 RegisterInfo data_reg;
4084 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004085 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004086 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004087 return false;
4088 }
4089
4090 // address = address + 4;
4091 offset += addr_byte_size;
4092 }
4093 }
4094
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004095 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00004096 // MemA[address,4] = PCStoreValue();
4097 if (BitIsSet (registers, 15))
4098 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004099 RegisterInfo pc_reg;
4100 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004101 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004102 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00004103 if (!success)
4104 return false;
4105
Caroline Tice8d681f52011-03-17 23:50:16 +00004106 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00004107 return false;
4108 }
4109
4110 // if wback then R[n] = R[n] + 4*BitCount(registers);
4111 if (wback)
4112 {
4113 offset = addr_byte_size * BitCount (registers);
4114 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00004115 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00004116 addr_t data = address + offset;
4117 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4118 return false;
4119 }
4120 }
4121 return true;
4122}
4123
Caroline Ticeaf556562011-02-15 18:42:15 +00004124// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
4125// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
4126// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00004127bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004128EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00004129{
4130#if 0
4131 if ConditionPassed() then
4132 EncodingSpecificOperations();
4133 address = R[n] - 4*BitCount(registers) + 4;
4134
4135 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004136 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004137 if i == n && wback && i != LowestSetBit(registers) then
4138 MemA[address,4] = bits(32) UNKNOWN;
4139 else
4140 MemA[address,4] = R[i];
4141 address = address + 4;
4142
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004143 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004144 MemA[address,4] = PCStoreValue();
4145
4146 if wback then R[n] = R[n] - 4*BitCount(registers);
4147#endif
4148
4149 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00004150
Greg Clayton7bc39082011-03-24 23:53:38 +00004151 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00004152 {
4153 uint32_t n;
4154 uint32_t registers = 0;
4155 bool wback;
4156 const uint32_t addr_byte_size = GetAddressByteSize();
4157
4158 // EncodingSpecificOperations();
4159 switch (encoding)
4160 {
4161 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004162 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00004163 n = Bits32 (opcode, 19, 16);
4164 registers = Bits32 (opcode, 15, 0);
4165 wback = BitIsSet (opcode, 21);
4166
4167 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4168 if ((n == 15) || (BitCount (registers) < 1))
4169 return false;
4170 break;
4171 default:
4172 return false;
4173 }
4174
4175 // address = R[n] - 4*BitCount(registers) + 4;
4176 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004177 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004178 if (!success)
4179 return false;
4180
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004181 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004182
4183 EmulateInstruction::Context context;
4184 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004185 RegisterInfo base_reg;
4186 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004187
4188 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004189 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004190 for (int i = 0; i < 14; ++i)
4191 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004192 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004193 if (BitIsSet (registers, i))
4194 {
4195 if (i < lowest_bit_set)
4196 lowest_bit_set = i;
4197 //if i == n && wback && i != LowestSetBit(registers) then
4198 if ((i == n) && wback && (i != lowest_bit_set))
4199 // MemA[address,4] = bits(32) UNKNOWN;
4200 WriteBits32UnknownToMemory (address + offset);
4201 else
4202 {
4203 // MemA[address,4] = R[i];
4204 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4205 if (!success)
4206 return false;
4207
Greg Claytonc07d4512011-04-26 23:48:45 +00004208 RegisterInfo data_reg;
4209 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004210 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004211 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004212 return false;
4213 }
4214
4215 // address = address + 4;
4216 offset += addr_byte_size;
4217 }
4218 }
4219
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004220 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004221 // MemA[address,4] = PCStoreValue();
4222 if (BitIsSet (registers, 15))
4223 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004224 RegisterInfo pc_reg;
4225 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Tice1511f502011-02-15 00:19:42 +00004226 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004227 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004228 if (!success)
4229 return false;
4230
Caroline Tice8d681f52011-03-17 23:50:16 +00004231 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004232 return false;
4233 }
4234
4235 // if wback then R[n] = R[n] - 4*BitCount(registers);
4236 if (wback)
4237 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004238 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004239 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4240 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004241 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004242 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4243 return false;
4244 }
4245 }
4246 return true;
4247}
4248
Caroline Ticeaf556562011-02-15 18:42:15 +00004249// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4250// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4251// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004252bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004253EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004254{
4255#if 0
4256 if ConditionPassed() then
4257 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4258 address = R[n] - 4*BitCount(registers);
4259
4260 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004261 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004262 if i == n && wback && i != LowestSetBit(registers) then
4263 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4264 else
4265 MemA[address,4] = R[i];
4266 address = address + 4;
4267
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004268 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004269 MemA[address,4] = PCStoreValue();
4270
4271 if wback then R[n] = R[n] - 4*BitCount(registers);
4272#endif
4273
4274
4275 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004276
Greg Clayton7bc39082011-03-24 23:53:38 +00004277 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004278 {
4279 uint32_t n;
4280 uint32_t registers = 0;
4281 bool wback;
4282 const uint32_t addr_byte_size = GetAddressByteSize();
4283
4284 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4285 switch (encoding)
4286 {
4287 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004288 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004289 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4290 {
4291 // See PUSH
4292 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004293 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004294 n = Bits32 (opcode, 19, 16);
4295 registers = Bits32 (opcode, 15, 0);
4296 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4297 wback = BitIsSet (opcode, 21);
4298 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4299 if ((n == 15) || BitCount (registers) < 2)
4300 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004301 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004302 if (wback && BitIsSet (registers, n))
4303 return false;
4304 break;
4305
4306 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00004307 // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004308 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4309 {
4310 // See Push
4311 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004312 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004313 n = Bits32 (opcode, 19, 16);
4314 registers = Bits32 (opcode, 15, 0);
4315 wback = BitIsSet (opcode, 21);
4316 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4317 if ((n == 15) || BitCount (registers) < 1)
4318 return false;
4319 break;
4320
4321 default:
4322 return false;
4323 }
4324
4325 // address = R[n] - 4*BitCount(registers);
4326
4327 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004328 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004329 if (!success)
4330 return false;
4331
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004332 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004333
4334 EmulateInstruction::Context context;
4335 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004336 RegisterInfo base_reg;
4337 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004338
4339 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004340 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004341 for (int i = 0; i < 14; ++i)
4342 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004343 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004344 if (BitIsSet (registers, i))
4345 {
4346 if (i < lowest_set_bit)
4347 lowest_set_bit = i;
4348 // if i == n && wback && i != LowestSetBit(registers) then
4349 if ((i == n) && wback && (i != lowest_set_bit))
4350 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4351 WriteBits32UnknownToMemory (address + offset);
4352 else
4353 {
4354 // MemA[address,4] = R[i];
4355 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4356 if (!success)
4357 return false;
4358
Greg Claytonc07d4512011-04-26 23:48:45 +00004359 RegisterInfo data_reg;
4360 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004361 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004362 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004363 return false;
4364 }
4365
4366 // address = address + 4;
4367 offset += addr_byte_size;
4368 }
4369 }
4370
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004371 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004372 // MemA[address,4] = PCStoreValue();
4373 if (BitIsSet (registers, 15))
4374 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004375 RegisterInfo pc_reg;
4376 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004377 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004378 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004379 if (!success)
4380 return false;
4381
Caroline Tice8d681f52011-03-17 23:50:16 +00004382 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004383 return false;
4384 }
4385
4386 // if wback then R[n] = R[n] - 4*BitCount(registers);
4387 if (wback)
4388 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004389 offset = (addr_byte_size * BitCount (registers)) * -1;
4390 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4391 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004392 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004393 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4394 return false;
4395 }
4396 }
4397 return true;
4398}
4399
4400// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4401// from a base register. The consecutive memory locations start just above this address, and the address of the last
4402// of those locations can optionally be written back to the base register.
4403bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004404EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004405{
4406#if 0
4407 if ConditionPassed() then
4408 EncodingSpecificOperations();
4409 address = R[n] + 4;
4410
4411 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004412 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004413 if i == n && wback && i != LowestSetBit(registers) then
4414 MemA[address,4] = bits(32) UNKNOWN;
4415 else
4416 MemA[address,4] = R[i];
4417 address = address + 4;
4418
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004419 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004420 MemA[address,4] = PCStoreValue();
4421
4422 if wback then R[n] = R[n] + 4*BitCount(registers);
4423#endif
4424
4425 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004426
Greg Clayton7bc39082011-03-24 23:53:38 +00004427 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004428 {
4429 uint32_t n;
4430 uint32_t registers = 0;
4431 bool wback;
4432 const uint32_t addr_byte_size = GetAddressByteSize();
4433
4434 // EncodingSpecificOperations();
4435 switch (encoding)
4436 {
4437 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004438 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004439 n = Bits32 (opcode, 19, 16);
4440 registers = Bits32 (opcode, 15, 0);
4441 wback = BitIsSet (opcode, 21);
4442
4443 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4444 if ((n == 15) && (BitCount (registers) < 1))
4445 return false;
4446 break;
4447 default:
4448 return false;
4449 }
4450 // address = R[n] + 4;
4451
4452 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004453 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004454 if (!success)
4455 return false;
4456
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004457 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004458
4459 EmulateInstruction::Context context;
4460 context.type = EmulateInstruction::eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004461 RegisterInfo base_reg;
4462 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004463
4464 uint32_t lowest_set_bit = 14;
4465 // for i = 0 to 14
4466 for (int i = 0; i < 14; ++i)
4467 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004468 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004469 if (BitIsSet (registers, i))
4470 {
4471 if (i < lowest_set_bit)
4472 lowest_set_bit = i;
4473 // if i == n && wback && i != LowestSetBit(registers) then
4474 if ((i == n) && wback && (i != lowest_set_bit))
4475 // MemA[address,4] = bits(32) UNKNOWN;
4476 WriteBits32UnknownToMemory (address + offset);
4477 // else
4478 else
4479 {
4480 // MemA[address,4] = R[i];
4481 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4482 if (!success)
4483 return false;
4484
Greg Claytonc07d4512011-04-26 23:48:45 +00004485 RegisterInfo data_reg;
4486 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004487 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004488 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004489 return false;
4490 }
4491
4492 // address = address + 4;
4493 offset += addr_byte_size;
4494 }
4495 }
4496
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004497 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004498 // MemA[address,4] = PCStoreValue();
4499 if (BitIsSet (registers, 15))
4500 {
Greg Claytonc07d4512011-04-26 23:48:45 +00004501 RegisterInfo pc_reg;
4502 GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
Caroline Ticeaf556562011-02-15 18:42:15 +00004503 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004504 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004505 if (!success)
4506 return false;
4507
Caroline Tice8d681f52011-03-17 23:50:16 +00004508 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004509 return false;
4510 }
4511
4512 // if wback then R[n] = R[n] + 4*BitCount(registers);
4513 if (wback)
4514 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004515 offset = addr_byte_size * BitCount (registers);
4516 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4517 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004518 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004519 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4520 return false;
4521 }
4522 }
4523 return true;
4524}
Caroline Tice7fac8572011-02-15 22:53:54 +00004525
4526// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4527// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4528bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004529EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004530{
4531#if 0
4532 if ConditionPassed() then
4533 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4534 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4535 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004536 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004537 MemU[address,4] = R[t];
4538 else // Can only occur before ARMv7
4539 MemU[address,4] = bits(32) UNKNOWN;
4540 if wback then R[n] = offset_addr;
4541#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004542
Caroline Tice7fac8572011-02-15 22:53:54 +00004543 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004544
Greg Clayton7bc39082011-03-24 23:53:38 +00004545 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004546 {
4547 const uint32_t addr_byte_size = GetAddressByteSize();
4548
4549 uint32_t t;
4550 uint32_t n;
4551 uint32_t imm32;
4552 bool index;
4553 bool add;
4554 bool wback;
4555 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4556 switch (encoding)
4557 {
4558 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004559 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004560 t = Bits32 (opcode, 2, 0);
4561 n = Bits32 (opcode, 5, 3);
4562 imm32 = Bits32 (opcode, 10, 6) << 2;
4563
4564 // index = TRUE; add = TRUE; wback = FALSE;
4565 index = true;
4566 add = false;
4567 wback = false;
4568 break;
4569
4570 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004571 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004572 t = Bits32 (opcode, 10, 8);
4573 n = 13;
4574 imm32 = Bits32 (opcode, 7, 0) << 2;
4575
4576 // index = TRUE; add = TRUE; wback = FALSE;
4577 index = true;
4578 add = true;
4579 wback = false;
4580 break;
4581
4582 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004583 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004584 if (Bits32 (opcode, 19, 16) == 15)
4585 return false;
4586
4587 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4588 t = Bits32 (opcode, 15, 12);
4589 n = Bits32 (opcode, 19, 16);
4590 imm32 = Bits32 (opcode, 11, 0);
4591
4592 // index = TRUE; add = TRUE; wback = FALSE;
4593 index = true;
4594 add = true;
4595 wback = false;
4596
4597 // if t == 15 then UNPREDICTABLE;
4598 if (t == 15)
4599 return false;
4600 break;
4601
4602 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004603 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4604 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4605 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004606 if ((Bits32 (opcode, 19, 16) == 15)
4607 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4608 return false;
4609
4610 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4611 t = Bits32 (opcode, 15, 12);
4612 n = Bits32 (opcode, 19, 16);
4613 imm32 = Bits32 (opcode, 7, 0);
4614
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004615 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004616 index = BitIsSet (opcode, 10);
4617 add = BitIsSet (opcode, 9);
4618 wback = BitIsSet (opcode, 8);
4619
4620 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4621 if ((t == 15) || (wback && (n == t)))
4622 return false;
4623 break;
4624
4625 default:
4626 return false;
4627 }
4628
4629 addr_t offset_addr;
4630 addr_t address;
4631
4632 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004633 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004634 if (!success)
4635 return false;
4636
4637 if (add)
4638 offset_addr = base_address + imm32;
4639 else
4640 offset_addr = base_address - imm32;
4641
4642 // address = if index then offset_addr else R[n];
4643 if (index)
4644 address = offset_addr;
4645 else
4646 address = base_address;
4647
4648 EmulateInstruction::Context context;
4649 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00004650 RegisterInfo base_reg;
4651 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004652
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004653 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004654 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4655 {
4656 // MemU[address,4] = R[t];
4657 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4658 if (!success)
4659 return false;
4660
Greg Claytonc07d4512011-04-26 23:48:45 +00004661 RegisterInfo data_reg;
4662 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice7fac8572011-02-15 22:53:54 +00004663 int32_t offset = address - base_address;
4664 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004665 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004666 return false;
4667 }
4668 else
4669 {
4670 // MemU[address,4] = bits(32) UNKNOWN;
4671 WriteBits32UnknownToMemory (address);
4672 }
4673
4674 // if wback then R[n] = offset_addr;
4675 if (wback)
4676 {
4677 context.type = eContextRegisterLoad;
4678 context.SetAddress (offset_addr);
4679 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4680 return false;
4681 }
4682 }
4683 return true;
4684}
Caroline Ticeaf556562011-02-15 18:42:15 +00004685
Caroline Tice3fd63e92011-02-16 00:33:43 +00004686// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4687// word from a register to memory. The offset register value can optionally be shifted.
4688bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004689EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004690{
4691#if 0
4692 if ConditionPassed() then
4693 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4694 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4695 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4696 address = if index then offset_addr else R[n];
4697 if t == 15 then // Only possible for encoding A1
4698 data = PCStoreValue();
4699 else
4700 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004701 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004702 MemU[address,4] = data;
4703 else // Can only occur before ARMv7
4704 MemU[address,4] = bits(32) UNKNOWN;
4705 if wback then R[n] = offset_addr;
4706#endif
4707
4708 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004709
Greg Clayton7bc39082011-03-24 23:53:38 +00004710 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004711 {
4712 const uint32_t addr_byte_size = GetAddressByteSize();
4713
4714 uint32_t t;
4715 uint32_t n;
4716 uint32_t m;
4717 ARM_ShifterType shift_t;
4718 uint32_t shift_n;
4719 bool index;
4720 bool add;
4721 bool wback;
4722
4723 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4724 switch (encoding)
4725 {
4726 case eEncodingT1:
4727 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4728 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4729 t = Bits32 (opcode, 2, 0);
4730 n = Bits32 (opcode, 5, 3);
4731 m = Bits32 (opcode, 8, 6);
4732
4733 // index = TRUE; add = TRUE; wback = FALSE;
4734 index = true;
4735 add = true;
4736 wback = false;
4737
4738 // (shift_t, shift_n) = (SRType_LSL, 0);
4739 shift_t = SRType_LSL;
4740 shift_n = 0;
4741 break;
4742
4743 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004744 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004745 if (Bits32 (opcode, 19, 16) == 15)
4746 return false;
4747
4748 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4749 t = Bits32 (opcode, 15, 12);
4750 n = Bits32 (opcode, 19, 16);
4751 m = Bits32 (opcode, 3, 0);
4752
4753 // index = TRUE; add = TRUE; wback = FALSE;
4754 index = true;
4755 add = true;
4756 wback = false;
4757
4758 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4759 shift_t = SRType_LSL;
4760 shift_n = Bits32 (opcode, 5, 4);
4761
4762 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4763 if ((t == 15) || (BadReg (m)))
4764 return false;
4765 break;
4766
4767 case eEncodingA1:
4768 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004769 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004770 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4771 t = Bits32 (opcode, 15, 12);
4772 n = Bits32 (opcode, 19, 16);
4773 m = Bits32 (opcode, 3, 0);
4774
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004775 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004776 index = BitIsSet (opcode, 24);
4777 add = BitIsSet (opcode, 23);
4778 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4779
4780 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4781 uint32_t typ = Bits32 (opcode, 6, 5);
4782 uint32_t imm5 = Bits32 (opcode, 11, 7);
4783 shift_n = DecodeImmShift(typ, imm5, shift_t);
4784
4785 // if m == 15 then UNPREDICTABLE;
4786 if (m == 15)
4787 return false;
4788
4789 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4790 if (wback && ((n == 15) || (n == t)))
4791 return false;
4792
4793 break;
4794 }
4795 default:
4796 return false;
4797 }
4798
4799 addr_t offset_addr;
4800 addr_t address;
4801 int32_t offset = 0;
4802
4803 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4804 if (!success)
4805 return false;
4806
4807 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4808 if (!success)
4809 return false;
4810
4811 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00004812 offset = Shift (Rm_data, shift_t, shift_n, APSR_C, &success);
4813 if (!success)
4814 return false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004815
4816 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4817 if (add)
4818 offset_addr = base_address + offset;
4819 else
4820 offset_addr = base_address - offset;
4821
4822 // address = if index then offset_addr else R[n];
4823 if (index)
4824 address = offset_addr;
4825 else
4826 address = base_address;
4827
4828 uint32_t data;
4829 // if t == 15 then // Only possible for encoding A1
4830 if (t == 15)
4831 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004832 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004833 else
4834 // data = R[t];
4835 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4836
4837 if (!success)
4838 return false;
4839
4840 EmulateInstruction::Context context;
4841 context.type = eContextRegisterStore;
4842
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004843 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004844 if (UnalignedSupport ()
4845 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4846 || CurrentInstrSet() == eModeARM)
4847 {
4848 // MemU[address,4] = data;
4849
Greg Claytonc07d4512011-04-26 23:48:45 +00004850 RegisterInfo base_reg;
4851 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004852
Greg Claytonc07d4512011-04-26 23:48:45 +00004853 RegisterInfo data_reg;
4854 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004855
4856 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004857 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004858 return false;
4859
4860 }
4861 else
4862 // MemU[address,4] = bits(32) UNKNOWN;
4863 WriteBits32UnknownToMemory (address);
4864
4865 // if wback then R[n] = offset_addr;
4866 if (wback)
4867 {
4868 context.type = eContextRegisterLoad;
4869 context.SetAddress (offset_addr);
4870 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4871 return false;
4872 }
4873
4874 }
4875 return true;
4876}
Caroline Tice73a29de2011-02-16 20:22:22 +00004877
4878bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004879EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004880{
4881#if 0
4882 if ConditionPassed() then
4883 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4884 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4885 address = if index then offset_addr else R[n];
4886 MemU[address,1] = R[t]<7:0>;
4887 if wback then R[n] = offset_addr;
4888#endif
4889
4890
4891 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004892
Greg Clayton7bc39082011-03-24 23:53:38 +00004893 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004894 {
4895 uint32_t t;
4896 uint32_t n;
4897 uint32_t imm32;
4898 bool index;
4899 bool add;
4900 bool wback;
4901 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4902 switch (encoding)
4903 {
4904 case eEncodingT1:
4905 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4906 t = Bits32 (opcode, 2, 0);
4907 n = Bits32 (opcode, 5, 3);
4908 imm32 = Bits32 (opcode, 10, 6);
4909
4910 // index = TRUE; add = TRUE; wback = FALSE;
4911 index = true;
4912 add = true;
4913 wback = false;
4914 break;
4915
4916 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004917 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004918 if (Bits32 (opcode, 19, 16) == 15)
4919 return false;
4920
4921 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4922 t = Bits32 (opcode, 15, 12);
4923 n = Bits32 (opcode, 19, 16);
4924 imm32 = Bits32 (opcode, 11, 0);
4925
4926 // index = TRUE; add = TRUE; wback = FALSE;
4927 index = true;
4928 add = true;
4929 wback = false;
4930
4931 // if BadReg(t) then UNPREDICTABLE;
4932 if (BadReg (t))
4933 return false;
4934 break;
4935
4936 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004937 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4938 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004939 if (Bits32 (opcode, 19, 16) == 15)
4940 return false;
4941
4942 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4943 t = Bits32 (opcode, 15, 12);
4944 n = Bits32 (opcode, 19, 16);
4945 imm32 = Bits32 (opcode, 7, 0);
4946
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004947 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004948 index = BitIsSet (opcode, 10);
4949 add = BitIsSet (opcode, 9);
4950 wback = BitIsSet (opcode, 8);
4951
4952 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4953 if ((BadReg (t)) || (wback && (n == t)))
4954 return false;
4955 break;
4956
4957 default:
4958 return false;
4959 }
4960
4961 addr_t offset_addr;
4962 addr_t address;
4963 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4964 if (!success)
4965 return false;
4966
4967 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4968 if (add)
4969 offset_addr = base_address + imm32;
4970 else
4971 offset_addr = base_address - imm32;
4972
4973 // address = if index then offset_addr else R[n];
4974 if (index)
4975 address = offset_addr;
4976 else
4977 address = base_address;
4978
Caroline Ticecc96eb52011-02-17 19:20:40 +00004979 // MemU[address,1] = R[t]<7:0>
Greg Claytonc07d4512011-04-26 23:48:45 +00004980 RegisterInfo base_reg;
4981 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004982
Greg Claytonc07d4512011-04-26 23:48:45 +00004983 RegisterInfo data_reg;
4984 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice73a29de2011-02-16 20:22:22 +00004985
4986 EmulateInstruction::Context context;
4987 context.type = eContextRegisterStore;
4988 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4989
4990 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4991 if (!success)
4992 return false;
4993
4994 data = Bits32 (data, 7, 0);
4995
Caroline Ticecc96eb52011-02-17 19:20:40 +00004996 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004997 return false;
4998
4999 // if wback then R[n] = offset_addr;
5000 if (wback)
5001 {
5002 context.type = eContextRegisterLoad;
5003 context.SetAddress (offset_addr);
5004 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5005 return false;
5006 }
5007
5008 }
5009
5010 return true;
5011}
Caroline Tice8ce836d2011-03-16 22:46:55 +00005012
5013// STRH (register) calculates an address from a base register value and an offset register value, and stores a
5014// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
5015bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005016EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00005017{
5018#if 0
5019 if ConditionPassed() then
5020 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5021 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5022 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5023 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005024 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005025 MemU[address,2] = R[t]<15:0>;
5026 else // Can only occur before ARMv7
5027 MemU[address,2] = bits(16) UNKNOWN;
5028 if wback then R[n] = offset_addr;
5029#endif
5030
5031 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005032
Greg Clayton7bc39082011-03-24 23:53:38 +00005033 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00005034 {
5035 uint32_t t;
5036 uint32_t n;
5037 uint32_t m;
5038 bool index;
5039 bool add;
5040 bool wback;
5041 ARM_ShifterType shift_t;
5042 uint32_t shift_n;
5043
5044 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5045 switch (encoding)
5046 {
5047 case eEncodingT1:
5048 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5049 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5050 t = Bits32 (opcode, 2, 0);
5051 n = Bits32 (opcode, 5, 3);
5052 m = Bits32 (opcode, 8, 6);
5053
5054 // index = TRUE; add = TRUE; wback = FALSE;
5055 index = true;
5056 add = true;
5057 wback = false;
5058
5059 // (shift_t, shift_n) = (SRType_LSL, 0);
5060 shift_t = SRType_LSL;
5061 shift_n = 0;
5062
5063 break;
5064
5065 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005066 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005067 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5068 t = Bits32 (opcode, 15, 12);
5069 n = Bits32 (opcode, 19, 16);
5070 m = Bits32 (opcode, 3, 0);
5071 if (n == 15)
5072 return false;
5073
5074 // index = TRUE; add = TRUE; wback = FALSE;
5075 index = true;
5076 add = true;
5077 wback = false;
5078
5079 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5080 shift_t = SRType_LSL;
5081 shift_n = Bits32 (opcode, 5, 4);
5082
5083 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5084 if (BadReg (t) || BadReg (m))
5085 return false;
5086
5087 break;
5088
5089 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005090 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005091 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5092 t = Bits32 (opcode, 15, 12);
5093 n = Bits32 (opcode, 19, 16);
5094 m = Bits32 (opcode, 3, 0);
5095
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005096 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00005097 index = BitIsSet (opcode, 24);
5098 add = BitIsSet (opcode, 23);
5099 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5100
5101 // (shift_t, shift_n) = (SRType_LSL, 0);
5102 shift_t = SRType_LSL;
5103 shift_n = 0;
5104
5105 // if t == 15 || m == 15 then UNPREDICTABLE;
5106 if ((t == 15) || (m == 15))
5107 return false;
5108
5109 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5110 if (wback && ((n == 15) || (n == t)))
5111 return false;
5112
5113 break;
5114
5115 default:
5116 return false;
5117 }
5118
5119 uint32_t Rm = ReadCoreReg (m, &success);
5120 if (!success)
5121 return false;
5122
5123 uint32_t Rn = ReadCoreReg (n, &success);
5124 if (!success)
5125 return false;
5126
5127 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00005128 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
5129 if (!success)
5130 return false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00005131
5132 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5133 addr_t offset_addr;
5134 if (add)
5135 offset_addr = Rn + offset;
5136 else
5137 offset_addr = Rn - offset;
5138
5139 // address = if index then offset_addr else R[n];
5140 addr_t address;
5141 if (index)
5142 address = offset_addr;
5143 else
5144 address = Rn;
5145
5146 EmulateInstruction::Context context;
5147 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005148 RegisterInfo base_reg;
5149 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5150 RegisterInfo offset_reg;
5151 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005152
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005153 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00005154 if (UnalignedSupport() || BitIsClear (address, 0))
5155 {
5156 // MemU[address,2] = R[t]<15:0>;
5157 uint32_t Rt = ReadCoreReg (t, &success);
5158 if (!success)
5159 return false;
5160
5161 EmulateInstruction::Context context;
5162 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +00005163 RegisterInfo base_reg;
5164 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
5165 RegisterInfo offset_reg;
5166 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
5167 RegisterInfo data_reg;
5168 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice8ce836d2011-03-16 22:46:55 +00005169 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5170
5171 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5172 return false;
5173 }
5174 else // Can only occur before ARMv7
5175 {
5176 // MemU[address,2] = bits(16) UNKNOWN;
5177 }
5178
5179 // if wback then R[n] = offset_addr;
5180 if (wback)
5181 {
5182 context.type = eContextAdjustBaseRegister;
5183 context.SetAddress (offset_addr);
5184 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5185 return false;
5186 }
5187 }
5188
5189 return true;
5190}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005191
Johnny Chen157b9592011-02-18 21:13:05 +00005192// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5193// and writes the result to the destination register. It can optionally update the condition flags
5194// based on the result.
5195bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005196EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005197{
5198#if 0
5199 // ARM pseudo code...
5200 if ConditionPassed() then
5201 EncodingSpecificOperations();
5202 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5203 if d == 15 then // Can only occur for ARM encoding
5204 ALUWritePC(result); // setflags is always FALSE here
5205 else
5206 R[d] = result;
5207 if setflags then
5208 APSR.N = result<31>;
5209 APSR.Z = IsZeroBit(result);
5210 APSR.C = carry;
5211 APSR.V = overflow;
5212#endif
5213
5214 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005215
Greg Clayton7bc39082011-03-24 23:53:38 +00005216 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005217 {
5218 uint32_t Rd, Rn;
5219 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5220 bool setflags;
5221 switch (encoding)
5222 {
5223 case eEncodingT1:
5224 Rd = Bits32(opcode, 11, 8);
5225 Rn = Bits32(opcode, 19, 16);
5226 setflags = BitIsSet(opcode, 20);
5227 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5228 if (BadReg(Rd) || BadReg(Rn))
5229 return false;
5230 break;
5231 case eEncodingA1:
5232 Rd = Bits32(opcode, 15, 12);
5233 Rn = Bits32(opcode, 19, 16);
5234 setflags = BitIsSet(opcode, 20);
5235 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00005236
Johnny Chen157b9592011-02-18 21:13:05 +00005237 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005238 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005239 break;
5240 default:
5241 return false;
5242 }
5243
5244 // Read the first operand.
5245 int32_t val1 = ReadCoreReg(Rn, &success);
5246 if (!success)
5247 return false;
5248
5249 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5250
5251 EmulateInstruction::Context context;
5252 context.type = EmulateInstruction::eContextImmediate;
5253 context.SetNoArgs ();
5254
5255 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5256 return false;
5257 }
5258 return true;
5259}
5260
5261// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5262// register value, and writes the result to the destination register. It can optionally update the
5263// condition flags based on the result.
5264bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005265EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005266{
5267#if 0
5268 // ARM pseudo code...
5269 if ConditionPassed() then
5270 EncodingSpecificOperations();
5271 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5272 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5273 if d == 15 then // Can only occur for ARM encoding
5274 ALUWritePC(result); // setflags is always FALSE here
5275 else
5276 R[d] = result;
5277 if setflags then
5278 APSR.N = result<31>;
5279 APSR.Z = IsZeroBit(result);
5280 APSR.C = carry;
5281 APSR.V = overflow;
5282#endif
5283
5284 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005285
Greg Clayton7bc39082011-03-24 23:53:38 +00005286 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005287 {
5288 uint32_t Rd, Rn, Rm;
5289 ARM_ShifterType shift_t;
5290 uint32_t shift_n; // the shift applied to the value read from Rm
5291 bool setflags;
5292 switch (encoding)
5293 {
5294 case eEncodingT1:
5295 Rd = Rn = Bits32(opcode, 2, 0);
5296 Rm = Bits32(opcode, 5, 3);
5297 setflags = !InITBlock();
5298 shift_t = SRType_LSL;
5299 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005300 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005301 case eEncodingT2:
5302 Rd = Bits32(opcode, 11, 8);
5303 Rn = Bits32(opcode, 19, 16);
5304 Rm = Bits32(opcode, 3, 0);
5305 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005306 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005307 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5308 return false;
5309 break;
5310 case eEncodingA1:
5311 Rd = Bits32(opcode, 15, 12);
5312 Rn = Bits32(opcode, 19, 16);
5313 Rm = Bits32(opcode, 3, 0);
5314 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005315 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005316
Johnny Chen157b9592011-02-18 21:13:05 +00005317 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005318 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen157b9592011-02-18 21:13:05 +00005319 break;
5320 default:
5321 return false;
5322 }
5323
5324 // Read the first operand.
5325 int32_t val1 = ReadCoreReg(Rn, &success);
5326 if (!success)
5327 return false;
5328
5329 // Read the second operand.
5330 int32_t val2 = ReadCoreReg(Rm, &success);
5331 if (!success)
5332 return false;
5333
Johnny Chena4438a72011-06-02 22:50:51 +00005334 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5335 if (!success)
5336 return false;
Johnny Chen157b9592011-02-18 21:13:05 +00005337 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5338
5339 EmulateInstruction::Context context;
5340 context.type = EmulateInstruction::eContextImmediate;
5341 context.SetNoArgs ();
5342
5343 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5344 return false;
5345 }
5346 return true;
5347}
5348
Johnny Chena695f952011-02-23 21:24:25 +00005349// This instruction adds an immediate value to the PC value to form a PC-relative address,
5350// and writes the result to the destination register.
5351bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005352EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005353{
5354#if 0
5355 // ARM pseudo code...
5356 if ConditionPassed() then
5357 EncodingSpecificOperations();
5358 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5359 if d == 15 then // Can only occur for ARM encodings
5360 ALUWritePC(result);
5361 else
5362 R[d] = result;
5363#endif
5364
5365 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005366
Greg Clayton7bc39082011-03-24 23:53:38 +00005367 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005368 {
5369 uint32_t Rd;
5370 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5371 bool add;
5372 switch (encoding)
5373 {
5374 case eEncodingT1:
5375 Rd = Bits32(opcode, 10, 8);
5376 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5377 break;
5378 case eEncodingT2:
5379 case eEncodingT3:
5380 Rd = Bits32(opcode, 11, 8);
5381 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5382 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5383 if (BadReg(Rd))
5384 return false;
5385 break;
5386 case eEncodingA1:
5387 case eEncodingA2:
5388 Rd = Bits32(opcode, 15, 12);
5389 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5390 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5391 break;
5392 default:
5393 return false;
5394 }
5395
5396 // Read the PC value.
5397 uint32_t pc = ReadCoreReg(PC_REG, &success);
5398 if (!success)
5399 return false;
5400
5401 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5402
5403 EmulateInstruction::Context context;
5404 context.type = EmulateInstruction::eContextImmediate;
5405 context.SetNoArgs ();
5406
5407 if (!WriteCoreReg(context, result, Rd))
5408 return false;
5409 }
5410 return true;
5411}
5412
Johnny Chene97c0d52011-02-18 19:32:20 +00005413// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5414// to the destination register. It can optionally update the condition flags based on the result.
5415bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005416EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005417{
5418#if 0
5419 // ARM pseudo code...
5420 if ConditionPassed() then
5421 EncodingSpecificOperations();
5422 result = R[n] AND imm32;
5423 if d == 15 then // Can only occur for ARM encoding
5424 ALUWritePC(result); // setflags is always FALSE here
5425 else
5426 R[d] = result;
5427 if setflags then
5428 APSR.N = result<31>;
5429 APSR.Z = IsZeroBit(result);
5430 APSR.C = carry;
5431 // APSR.V unchanged
5432#endif
5433
5434 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005435
Greg Clayton7bc39082011-03-24 23:53:38 +00005436 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005437 {
5438 uint32_t Rd, Rn;
5439 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5440 bool setflags;
5441 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5442 switch (encoding)
5443 {
5444 case eEncodingT1:
5445 Rd = Bits32(opcode, 11, 8);
5446 Rn = Bits32(opcode, 19, 16);
5447 setflags = BitIsSet(opcode, 20);
5448 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005449 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005450 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005451 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005452 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5453 return false;
5454 break;
5455 case eEncodingA1:
5456 Rd = Bits32(opcode, 15, 12);
5457 Rn = Bits32(opcode, 19, 16);
5458 setflags = BitIsSet(opcode, 20);
5459 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005460
Johnny Chene97c0d52011-02-18 19:32:20 +00005461 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005462 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005463 break;
5464 default:
5465 return false;
5466 }
5467
Johnny Chene97c0d52011-02-18 19:32:20 +00005468 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005469 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005470 if (!success)
5471 return false;
5472
5473 uint32_t result = val1 & imm32;
5474
5475 EmulateInstruction::Context context;
5476 context.type = EmulateInstruction::eContextImmediate;
5477 context.SetNoArgs ();
5478
5479 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5480 return false;
5481 }
5482 return true;
5483}
5484
5485// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5486// and writes the result to the destination register. It can optionally update the condition flags
5487// based on the result.
5488bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005489EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005490{
5491#if 0
5492 // ARM pseudo code...
5493 if ConditionPassed() then
5494 EncodingSpecificOperations();
5495 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5496 result = R[n] AND shifted;
5497 if d == 15 then // Can only occur for ARM encoding
5498 ALUWritePC(result); // setflags is always FALSE here
5499 else
5500 R[d] = result;
5501 if setflags then
5502 APSR.N = result<31>;
5503 APSR.Z = IsZeroBit(result);
5504 APSR.C = carry;
5505 // APSR.V unchanged
5506#endif
5507
5508 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005509
Greg Clayton7bc39082011-03-24 23:53:38 +00005510 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005511 {
5512 uint32_t Rd, Rn, Rm;
5513 ARM_ShifterType shift_t;
5514 uint32_t shift_n; // the shift applied to the value read from Rm
5515 bool setflags;
5516 uint32_t carry;
5517 switch (encoding)
5518 {
5519 case eEncodingT1:
5520 Rd = Rn = Bits32(opcode, 2, 0);
5521 Rm = Bits32(opcode, 5, 3);
5522 setflags = !InITBlock();
5523 shift_t = SRType_LSL;
5524 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005525 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005526 case eEncodingT2:
5527 Rd = Bits32(opcode, 11, 8);
5528 Rn = Bits32(opcode, 19, 16);
5529 Rm = Bits32(opcode, 3, 0);
5530 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005531 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005532 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005533 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005534 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005535 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5536 return false;
5537 break;
5538 case eEncodingA1:
5539 Rd = Bits32(opcode, 15, 12);
5540 Rn = Bits32(opcode, 19, 16);
5541 Rm = Bits32(opcode, 3, 0);
5542 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005543 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005544
Johnny Chene97c0d52011-02-18 19:32:20 +00005545 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005546 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chene97c0d52011-02-18 19:32:20 +00005547 break;
5548 default:
5549 return false;
5550 }
5551
Johnny Chene97c0d52011-02-18 19:32:20 +00005552 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005553 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005554 if (!success)
5555 return false;
5556
5557 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005558 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005559 if (!success)
5560 return false;
5561
Johnny Chena4438a72011-06-02 22:50:51 +00005562 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5563 if (!success)
5564 return false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005565 uint32_t result = val1 & shifted;
5566
5567 EmulateInstruction::Context context;
5568 context.type = EmulateInstruction::eContextImmediate;
5569 context.SetNoArgs ();
5570
5571 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5572 return false;
5573 }
5574 return true;
5575}
5576
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005577// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5578// immediate value, and writes the result to the destination register. It can optionally update the
5579// condition flags based on the result.
5580bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005581EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005582{
5583#if 0
5584 // ARM pseudo code...
5585 if ConditionPassed() then
5586 EncodingSpecificOperations();
5587 result = R[n] AND NOT(imm32);
5588 if d == 15 then // Can only occur for ARM encoding
5589 ALUWritePC(result); // setflags is always FALSE here
5590 else
5591 R[d] = result;
5592 if setflags then
5593 APSR.N = result<31>;
5594 APSR.Z = IsZeroBit(result);
5595 APSR.C = carry;
5596 // APSR.V unchanged
5597#endif
5598
5599 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005600
Greg Clayton7bc39082011-03-24 23:53:38 +00005601 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005602 {
5603 uint32_t Rd, Rn;
5604 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5605 bool setflags;
5606 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5607 switch (encoding)
5608 {
5609 case eEncodingT1:
5610 Rd = Bits32(opcode, 11, 8);
5611 Rn = Bits32(opcode, 19, 16);
5612 setflags = BitIsSet(opcode, 20);
5613 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5614 if (BadReg(Rd) || BadReg(Rn))
5615 return false;
5616 break;
5617 case eEncodingA1:
5618 Rd = Bits32(opcode, 15, 12);
5619 Rn = Bits32(opcode, 19, 16);
5620 setflags = BitIsSet(opcode, 20);
5621 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00005622
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005623 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005624 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005625 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005626 break;
5627 default:
5628 return false;
5629 }
5630
5631 // Read the first operand.
5632 uint32_t val1 = ReadCoreReg(Rn, &success);
5633 if (!success)
5634 return false;
5635
5636 uint32_t result = val1 & ~imm32;
5637
5638 EmulateInstruction::Context context;
5639 context.type = EmulateInstruction::eContextImmediate;
5640 context.SetNoArgs ();
5641
5642 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5643 return false;
5644 }
5645 return true;
5646}
5647
5648// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5649// optionally-shifted register value, and writes the result to the destination register.
5650// It can optionally update the condition flags based on the result.
5651bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005652EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005653{
5654#if 0
5655 // ARM pseudo code...
5656 if ConditionPassed() then
5657 EncodingSpecificOperations();
5658 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5659 result = R[n] AND NOT(shifted);
5660 if d == 15 then // Can only occur for ARM encoding
5661 ALUWritePC(result); // setflags is always FALSE here
5662 else
5663 R[d] = result;
5664 if setflags then
5665 APSR.N = result<31>;
5666 APSR.Z = IsZeroBit(result);
5667 APSR.C = carry;
5668 // APSR.V unchanged
5669#endif
5670
5671 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005672
Greg Clayton7bc39082011-03-24 23:53:38 +00005673 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005674 {
5675 uint32_t Rd, Rn, Rm;
5676 ARM_ShifterType shift_t;
5677 uint32_t shift_n; // the shift applied to the value read from Rm
5678 bool setflags;
5679 uint32_t carry;
5680 switch (encoding)
5681 {
5682 case eEncodingT1:
5683 Rd = Rn = Bits32(opcode, 2, 0);
5684 Rm = Bits32(opcode, 5, 3);
5685 setflags = !InITBlock();
5686 shift_t = SRType_LSL;
5687 shift_n = 0;
5688 break;
5689 case eEncodingT2:
5690 Rd = Bits32(opcode, 11, 8);
5691 Rn = Bits32(opcode, 19, 16);
5692 Rm = Bits32(opcode, 3, 0);
5693 setflags = BitIsSet(opcode, 20);
5694 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5695 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5696 return false;
5697 break;
5698 case eEncodingA1:
5699 Rd = Bits32(opcode, 15, 12);
5700 Rn = Bits32(opcode, 19, 16);
5701 Rm = Bits32(opcode, 3, 0);
5702 setflags = BitIsSet(opcode, 20);
5703 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00005704
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005705 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005706 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00005707 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005708 break;
5709 default:
5710 return false;
5711 }
5712
5713 // Read the first operand.
5714 uint32_t val1 = ReadCoreReg(Rn, &success);
5715 if (!success)
5716 return false;
5717
5718 // Read the second operand.
5719 uint32_t val2 = ReadCoreReg(Rm, &success);
5720 if (!success)
5721 return false;
5722
Johnny Chena4438a72011-06-02 22:50:51 +00005723 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
5724 if (!success)
5725 return false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005726 uint32_t result = val1 & ~shifted;
5727
5728 EmulateInstruction::Context context;
5729 context.type = EmulateInstruction::eContextImmediate;
5730 context.SetNoArgs ();
5731
5732 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5733 return false;
5734 }
5735 return true;
5736}
5737
Caroline Tice4d729c52011-02-18 00:55:53 +00005738// 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 +00005739// 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 +00005740bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005741EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005742{
5743#if 0
5744 if ConditionPassed() then
5745 EncodingSpecificOperations();
5746 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5747 address = if index then offset_addr else R[n];
5748 data = MemU[address,4];
5749 if wback then R[n] = offset_addr;
5750 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005751 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5752 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005753 R[t] = data;
5754 else // Can only apply before ARMv7
5755 R[t] = ROR(data, 8*UInt(address<1:0>));
5756#endif
5757
5758 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005759
Greg Clayton7bc39082011-03-24 23:53:38 +00005760 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005761 {
5762 const uint32_t addr_byte_size = GetAddressByteSize();
5763
5764 uint32_t t;
5765 uint32_t n;
5766 uint32_t imm32;
5767 bool index;
5768 bool add;
5769 bool wback;
5770
5771 switch (encoding)
5772 {
5773 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005774 // if Rn == '1111' then SEE LDR (literal);
5775 // if P == '0' && W == '1' then SEE LDRT;
5776 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005777 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5778 t = Bits32 (opcode, 15, 12);
5779 n = Bits32 (opcode, 19, 16);
5780 imm32 = Bits32 (opcode, 11, 0);
5781
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005782 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5783 index = BitIsSet (opcode, 24);
5784 add = BitIsSet (opcode, 23);
5785 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005786
5787 // if wback && n == t then UNPREDICTABLE;
5788 if (wback && (n == t))
5789 return false;
5790
5791 break;
5792
5793 default:
5794 return false;
5795 }
5796
5797 addr_t address;
5798 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005799 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005800 if (!success)
5801 return false;
5802
5803 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5804 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005805 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005806 else
5807 offset_addr = base_address - imm32;
5808
5809 // address = if index then offset_addr else R[n];
5810 if (index)
5811 address = offset_addr;
5812 else
5813 address = base_address;
5814
5815 // data = MemU[address,4];
5816
Greg Claytonc07d4512011-04-26 23:48:45 +00005817 RegisterInfo base_reg;
5818 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4d729c52011-02-18 00:55:53 +00005819
5820 EmulateInstruction::Context context;
5821 context.type = eContextRegisterLoad;
5822 context.SetRegisterPlusOffset (base_reg, address - base_address);
5823
5824 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5825 if (!success)
5826 return false;
5827
5828 // if wback then R[n] = offset_addr;
5829 if (wback)
5830 {
5831 context.type = eContextAdjustBaseRegister;
5832 context.SetAddress (offset_addr);
5833 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5834 return false;
5835 }
5836
5837 // if t == 15 then
5838 if (t == 15)
5839 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005840 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005841 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5842 {
5843 // LoadWritePC (data);
5844 context.type = eContextRegisterLoad;
5845 context.SetRegisterPlusOffset (base_reg, address - base_address);
5846 LoadWritePC (context, data);
5847 }
5848 else
5849 return false;
5850 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005851 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005852 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5853 {
5854 // R[t] = data;
5855 context.type = eContextRegisterLoad;
5856 context.SetRegisterPlusOffset (base_reg, address - base_address);
5857 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5858 return false;
5859 }
5860 // else // Can only apply before ARMv7
5861 else
5862 {
5863 // R[t] = ROR(data, 8*UInt(address<1:0>));
Johnny Chena4438a72011-06-02 22:50:51 +00005864 data = ROR (data, Bits32 (address, 1, 0), &success);
5865 if (!success)
5866 return false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005867 context.type = eContextRegisterLoad;
5868 context.SetImmediate (data);
5869 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5870 return false;
5871 }
5872
5873 }
5874 return true;
5875}
5876
Caroline Ticefe479112011-02-18 18:52:37 +00005877// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5878// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5879bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005880EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005881{
5882#if 0
5883 if ConditionPassed() then
5884 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5885 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5886 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5887 address = if index then offset_addr else R[n];
5888 data = MemU[address,4];
5889 if wback then R[n] = offset_addr;
5890 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005891 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5892 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005893 R[t] = data;
5894 else // Can only apply before ARMv7
5895 if CurrentInstrSet() == InstrSet_ARM then
5896 R[t] = ROR(data, 8*UInt(address<1:0>));
5897 else
5898 R[t] = bits(32) UNKNOWN;
5899#endif
5900
5901 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005902
Greg Clayton7bc39082011-03-24 23:53:38 +00005903 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005904 {
5905 const uint32_t addr_byte_size = GetAddressByteSize();
5906
5907 uint32_t t;
5908 uint32_t n;
5909 uint32_t m;
5910 bool index;
5911 bool add;
5912 bool wback;
5913 ARM_ShifterType shift_t;
5914 uint32_t shift_n;
5915
5916 switch (encoding)
5917 {
5918 case eEncodingT1:
5919 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5920 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5921 t = Bits32 (opcode, 2, 0);
5922 n = Bits32 (opcode, 5, 3);
5923 m = Bits32 (opcode, 8, 6);
5924
5925 // index = TRUE; add = TRUE; wback = FALSE;
5926 index = true;
5927 add = true;
5928 wback = false;
5929
5930 // (shift_t, shift_n) = (SRType_LSL, 0);
5931 shift_t = SRType_LSL;
5932 shift_n = 0;
5933
5934 break;
5935
5936 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005937 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005938 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5939 t = Bits32 (opcode, 15, 12);
5940 n = Bits32 (opcode, 19, 16);
5941 m = Bits32 (opcode, 3, 0);
5942
5943 // index = TRUE; add = TRUE; wback = FALSE;
5944 index = true;
5945 add = true;
5946 wback = false;
5947
5948 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5949 shift_t = SRType_LSL;
5950 shift_n = Bits32 (opcode, 5, 4);
5951
5952 // if BadReg(m) then UNPREDICTABLE;
5953 if (BadReg (m))
5954 return false;
5955
5956 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5957 if ((t == 15) && InITBlock() && !LastInITBlock())
5958 return false;
5959
5960 break;
5961
5962 case eEncodingA1:
5963 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005964 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005965 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5966 t = Bits32 (opcode, 15, 12);
5967 n = Bits32 (opcode, 19, 16);
5968 m = Bits32 (opcode, 3, 0);
5969
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005970 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005971 index = BitIsSet (opcode, 24);
5972 add = BitIsSet (opcode, 23);
5973 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5974
5975 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5976 uint32_t type = Bits32 (opcode, 6, 5);
5977 uint32_t imm5 = Bits32 (opcode, 11, 7);
5978 shift_n = DecodeImmShift (type, imm5, shift_t);
5979
5980 // if m == 15 then UNPREDICTABLE;
5981 if (m == 15)
5982 return false;
5983
5984 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5985 if (wback && ((n == 15) || (n == t)))
5986 return false;
5987 }
5988 break;
5989
5990
5991 default:
5992 return false;
5993 }
5994
5995 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5996 if (!success)
5997 return false;
5998
5999 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6000 if (!success)
6001 return false;
6002
6003 addr_t offset_addr;
6004 addr_t address;
6005
6006 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Johnny Chena4438a72011-06-02 22:50:51 +00006007 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C), &success);
6008 if (!success)
6009 return false;
Caroline Ticefe479112011-02-18 18:52:37 +00006010
6011 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6012 if (add)
6013 offset_addr = Rn + offset;
6014 else
6015 offset_addr = Rn - offset;
6016
6017 // address = if index then offset_addr else R[n];
6018 if (index)
6019 address = offset_addr;
6020 else
6021 address = Rn;
6022
6023 // data = MemU[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +00006024 RegisterInfo base_reg;
6025 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticefe479112011-02-18 18:52:37 +00006026
6027 EmulateInstruction::Context context;
6028 context.type = eContextRegisterLoad;
6029 context.SetRegisterPlusOffset (base_reg, address - Rn);
6030
6031 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
6032 if (!success)
6033 return false;
6034
6035 // if wback then R[n] = offset_addr;
6036 if (wback)
6037 {
6038 context.type = eContextAdjustBaseRegister;
6039 context.SetAddress (offset_addr);
6040 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6041 return false;
6042 }
6043
6044 // if t == 15 then
6045 if (t == 15)
6046 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006047 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00006048 if (BitIsClear (address, 1) && BitIsClear (address, 0))
6049 {
6050 context.type = eContextRegisterLoad;
6051 context.SetRegisterPlusOffset (base_reg, address - Rn);
6052 LoadWritePC (context, data);
6053 }
6054 else
6055 return false;
6056 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006057 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00006058 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
6059 {
6060 // R[t] = data;
6061 context.type = eContextRegisterLoad;
6062 context.SetRegisterPlusOffset (base_reg, address - Rn);
6063 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6064 return false;
6065 }
6066 else // Can only apply before ARMv7
6067 {
6068 // if CurrentInstrSet() == InstrSet_ARM then
6069 if (CurrentInstrSet () == eModeARM)
6070 {
6071 // R[t] = ROR(data, 8*UInt(address<1:0>));
Johnny Chena4438a72011-06-02 22:50:51 +00006072 data = ROR (data, Bits32 (address, 1, 0), &success);
6073 if (!success)
6074 return false;
Caroline Ticefe479112011-02-18 18:52:37 +00006075 context.type = eContextRegisterLoad;
6076 context.SetImmediate (data);
6077 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6078 return false;
6079 }
6080 else
6081 {
6082 // R[t] = bits(32) UNKNOWN;
6083 WriteBits32Unknown (t);
6084 }
6085 }
6086 }
6087 return true;
6088}
Caroline Tice21b604b2011-02-18 21:06:04 +00006089
6090// LDRB (immediate, Thumb)
6091bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006092EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00006093{
6094#if 0
6095 if ConditionPassed() then
6096 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6097 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6098 address = if index then offset_addr else R[n];
6099 R[t] = ZeroExtend(MemU[address,1], 32);
6100 if wback then R[n] = offset_addr;
6101#endif
6102
6103 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00006104
Greg Clayton7bc39082011-03-24 23:53:38 +00006105 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00006106 {
6107 uint32_t t;
6108 uint32_t n;
6109 uint32_t imm32;
6110 bool index;
6111 bool add;
6112 bool wback;
6113
6114 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6115 switch (encoding)
6116 {
6117 case eEncodingT1:
6118 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6119 t = Bits32 (opcode, 2, 0);
6120 n = Bits32 (opcode, 5, 3);
6121 imm32 = Bits32 (opcode, 10, 6);
6122
6123 // index = TRUE; add = TRUE; wback = FALSE;
6124 index = true;
6125 add = true;
6126 wback= false;
6127
6128 break;
6129
6130 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006131 // if Rt == '1111' then SEE PLD;
6132 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00006133 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6134 t = Bits32 (opcode, 15, 12);
6135 n = Bits32 (opcode, 19, 16);
6136 imm32 = Bits32 (opcode, 11, 0);
6137
6138 // index = TRUE; add = TRUE; wback = FALSE;
6139 index = true;
6140 add = true;
6141 wback = false;
6142
6143 // if t == 13 then UNPREDICTABLE;
6144 if (t == 13)
6145 return false;
6146
6147 break;
6148
6149 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006150 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6151 // if Rn == '1111' then SEE LDRB (literal);
6152 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6153 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00006154 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6155 return false;
6156
6157 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6158 t = Bits32 (opcode, 15, 12);
6159 n = Bits32 (opcode, 19, 16);
6160 imm32 = Bits32 (opcode, 7, 0);
6161
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006162 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00006163 index = BitIsSet (opcode, 10);
6164 add = BitIsSet (opcode, 9);
6165 wback = BitIsSet (opcode, 8);
6166
6167 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6168 if (BadReg (t) || (wback && (n == t)))
6169 return false;
6170
6171 break;
6172
6173 default:
6174 return false;
6175 }
6176
6177 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6178 if (!success)
6179 return false;
6180
6181 addr_t address;
6182 addr_t offset_addr;
6183
6184 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6185 if (add)
6186 offset_addr = Rn + imm32;
6187 else
6188 offset_addr = Rn - imm32;
6189
6190 // address = if index then offset_addr else R[n];
6191 if (index)
6192 address = offset_addr;
6193 else
6194 address = Rn;
6195
6196 // R[t] = ZeroExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006197 RegisterInfo base_reg;
6198 RegisterInfo data_reg;
6199 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6200 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice21b604b2011-02-18 21:06:04 +00006201
6202 EmulateInstruction::Context context;
6203 context.type = eContextRegisterLoad;
6204 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6205
6206 uint64_t data = MemURead (context, address, 1, 0, &success);
6207 if (!success)
6208 return false;
6209
6210 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6211 return false;
6212
6213 // if wback then R[n] = offset_addr;
6214 if (wback)
6215 {
6216 context.type = eContextAdjustBaseRegister;
6217 context.SetAddress (offset_addr);
6218 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6219 return false;
6220 }
6221 }
6222 return true;
6223}
Caroline Ticef55261f2011-02-18 22:24:22 +00006224
6225// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6226// zero-extends it to form a 32-bit word and writes it to a register.
6227bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006228EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006229{
6230#if 0
6231 if ConditionPassed() then
6232 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6233 base = Align(PC,4);
6234 address = if add then (base + imm32) else (base - imm32);
6235 R[t] = ZeroExtend(MemU[address,1], 32);
6236#endif
6237
6238 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006239
Greg Clayton7bc39082011-03-24 23:53:38 +00006240 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006241 {
6242 uint32_t t;
6243 uint32_t imm32;
6244 bool add;
6245 switch (encoding)
6246 {
6247 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006248 // if Rt == '1111' then SEE PLD;
6249 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006250 t = Bits32 (opcode, 15, 12);
6251 imm32 = Bits32 (opcode, 11, 0);
6252 add = BitIsSet (opcode, 23);
6253
6254 // if t == 13 then UNPREDICTABLE;
6255 if (t == 13)
6256 return false;
6257
6258 break;
6259
6260 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006261 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006262 t = Bits32 (opcode, 15, 12);
6263 imm32 = Bits32 (opcode, 11, 0);
6264 add = BitIsSet (opcode, 23);
6265
6266 // if t == 15 then UNPREDICTABLE;
6267 if (t == 15)
6268 return false;
6269 break;
6270
6271 default:
6272 return false;
6273 }
6274
6275 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006276 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006277 if (!success)
6278 return false;
6279
6280 uint32_t base = AlignPC (pc_val);
6281
6282 addr_t address;
6283 // address = if add then (base + imm32) else (base - imm32);
6284 if (add)
6285 address = base + imm32;
6286 else
6287 address = base - imm32;
6288
6289 // R[t] = ZeroExtend(MemU[address,1], 32);
6290 EmulateInstruction::Context context;
6291 context.type = eContextRelativeBranchImmediate;
6292 context.SetImmediate (address - base);
6293
6294 uint64_t data = MemURead (context, address, 1, 0, &success);
6295 if (!success)
6296 return false;
6297
6298 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6299 return false;
6300 }
6301 return true;
6302}
Caroline Tice30fec122011-02-18 23:52:21 +00006303
6304// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6305// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6306// optionally be shifted.
6307bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006308EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006309{
6310#if 0
6311 if ConditionPassed() then
6312 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6313 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6314 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6315 address = if index then offset_addr else R[n];
6316 R[t] = ZeroExtend(MemU[address,1],32);
6317 if wback then R[n] = offset_addr;
6318#endif
6319
6320 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006321
Greg Clayton7bc39082011-03-24 23:53:38 +00006322 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006323 {
6324 uint32_t t;
6325 uint32_t n;
6326 uint32_t m;
6327 bool index;
6328 bool add;
6329 bool wback;
6330 ARM_ShifterType shift_t;
6331 uint32_t shift_n;
6332
6333 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6334 switch (encoding)
6335 {
6336 case eEncodingT1:
6337 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6338 t = Bits32 (opcode, 2, 0);
6339 n = Bits32 (opcode, 5, 3);
6340 m = Bits32 (opcode, 8, 6);
6341
6342 // index = TRUE; add = TRUE; wback = FALSE;
6343 index = true;
6344 add = true;
6345 wback = false;
6346
6347 // (shift_t, shift_n) = (SRType_LSL, 0);
6348 shift_t = SRType_LSL;
6349 shift_n = 0;
6350 break;
6351
6352 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006353 // if Rt == '1111' then SEE PLD;
6354 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006355 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6356 t = Bits32 (opcode, 15, 12);
6357 n = Bits32 (opcode, 19, 16);
6358 m = Bits32 (opcode, 3, 0);
6359
6360 // index = TRUE; add = TRUE; wback = FALSE;
6361 index = true;
6362 add = true;
6363 wback = false;
6364
6365 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6366 shift_t = SRType_LSL;
6367 shift_n = Bits32 (opcode, 5, 4);
6368
6369 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6370 if ((t == 13) || BadReg (m))
6371 return false;
6372 break;
6373
6374 case eEncodingA1:
6375 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006376 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006377 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6378 t = Bits32 (opcode, 15, 12);
6379 n = Bits32 (opcode, 19, 16);
6380 m = Bits32 (opcode, 3, 0);
6381
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006382 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006383 index = BitIsSet (opcode, 24);
6384 add = BitIsSet (opcode, 23);
6385 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6386
6387 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6388 uint32_t type = Bits32 (opcode, 6, 5);
6389 uint32_t imm5 = Bits32 (opcode, 11, 7);
6390 shift_n = DecodeImmShift (type, imm5, shift_t);
6391
6392 // if t == 15 || m == 15 then UNPREDICTABLE;
6393 if ((t == 15) || (m == 15))
6394 return false;
6395
6396 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6397 if (wback && ((n == 15) || (n == t)))
6398 return false;
6399 }
6400 break;
6401
6402 default:
6403 return false;
6404 }
6405
6406 addr_t offset_addr;
6407 addr_t address;
6408
6409 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6410 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6411 if (!success)
6412 return false;
6413
Johnny Chena4438a72011-06-02 22:50:51 +00006414 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6415 if (!success)
6416 return false;
Caroline Tice30fec122011-02-18 23:52:21 +00006417
6418 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6419 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6420 if (!success)
6421 return false;
6422
6423 if (add)
6424 offset_addr = Rn + offset;
6425 else
6426 offset_addr = Rn - offset;
6427
6428 // address = if index then offset_addr else R[n];
6429 if (index)
6430 address = offset_addr;
6431 else
6432 address = Rn;
6433
6434 // R[t] = ZeroExtend(MemU[address,1],32);
Greg Claytonc07d4512011-04-26 23:48:45 +00006435 RegisterInfo base_reg;
6436 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice30fec122011-02-18 23:52:21 +00006437
6438 EmulateInstruction::Context context;
6439 context.type = eContextRegisterLoad;
6440 context.SetRegisterPlusOffset (base_reg, address - Rn);
6441
6442 uint64_t data = MemURead (context, address, 1, 0, &success);
6443 if (!success)
6444 return false;
6445
6446 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6447 return false;
6448
6449 // if wback then R[n] = offset_addr;
6450 if (wback)
6451 {
6452 context.type = eContextAdjustBaseRegister;
6453 context.SetAddress (offset_addr);
6454 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6455 return false;
6456 }
6457 }
6458 return true;
6459}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006460
6461// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6462// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6463// post-indexed, or pre-indexed addressing.
6464bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006465EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006466{
6467#if 0
6468 if ConditionPassed() then
6469 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6470 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6471 address = if index then offset_addr else R[n];
6472 data = MemU[address,2];
6473 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006474 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006475 R[t] = ZeroExtend(data, 32);
6476 else // Can only apply before ARMv7
6477 R[t] = bits(32) UNKNOWN;
6478#endif
6479
6480
6481 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006482
Greg Clayton7bc39082011-03-24 23:53:38 +00006483 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006484 {
6485 uint32_t t;
6486 uint32_t n;
6487 uint32_t imm32;
6488 bool index;
6489 bool add;
6490 bool wback;
6491
6492 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6493 switch (encoding)
6494 {
6495 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006496 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006497 t = Bits32 (opcode, 2, 0);
6498 n = Bits32 (opcode, 5, 3);
6499 imm32 = Bits32 (opcode, 10, 6) << 1;
6500
6501 // index = TRUE; add = TRUE; wback = FALSE;
6502 index = true;
6503 add = true;
6504 wback = false;
6505
6506 break;
6507
6508 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006509 // if Rt == '1111' then SEE "Unallocated memory hints";
6510 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006511 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6512 t = Bits32 (opcode, 15, 12);
6513 n = Bits32 (opcode, 19, 16);
6514 imm32 = Bits32 (opcode, 11, 0);
6515
6516 // index = TRUE; add = TRUE; wback = FALSE;
6517 index = true;
6518 add = true;
6519 wback = false;
6520
6521 // if t == 13 then UNPREDICTABLE;
6522 if (t == 13)
6523 return false;
6524 break;
6525
6526 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006527 // if Rn == '1111' then SEE LDRH (literal);
6528 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6529 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6530 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006531 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6532 return false;
6533
6534 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6535 t = Bits32 (opcode, 15, 12);
6536 n = Bits32 (opcode, 19, 16);
6537 imm32 = Bits32 (opcode, 7, 0);
6538
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006539 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006540 index = BitIsSet (opcode, 10);
6541 add = BitIsSet (opcode, 9);
6542 wback = BitIsSet (opcode, 8);
6543
6544 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6545 if (BadReg (t) || (wback && (n == t)))
6546 return false;
6547 break;
6548
6549 default:
6550 return false;
6551 }
6552
6553 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6554 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6555 if (!success)
6556 return false;
6557
6558 addr_t offset_addr;
6559 addr_t address;
6560
6561 if (add)
6562 offset_addr = Rn + imm32;
6563 else
6564 offset_addr = Rn - imm32;
6565
6566 // address = if index then offset_addr else R[n];
6567 if (index)
6568 address = offset_addr;
6569 else
6570 address = Rn;
6571
6572 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006573 RegisterInfo base_reg;
6574 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006575
6576 EmulateInstruction::Context context;
6577 context.type = eContextRegisterLoad;
6578 context.SetRegisterPlusOffset (base_reg, address - Rn);
6579
6580 uint64_t data = MemURead (context, address, 2, 0, &success);
6581 if (!success)
6582 return false;
6583
6584 // if wback then R[n] = offset_addr;
6585 if (wback)
6586 {
6587 context.type = eContextAdjustBaseRegister;
6588 context.SetAddress (offset_addr);
6589 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6590 return false;
6591 }
6592
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006593 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006594 if (UnalignedSupport () || BitIsClear (address, 0))
6595 {
6596 // R[t] = ZeroExtend(data, 32);
6597 context.type = eContextRegisterLoad;
6598 context.SetRegisterPlusOffset (base_reg, address - Rn);
6599 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6600 return false;
6601 }
6602 else // Can only apply before ARMv7
6603 {
6604 // R[t] = bits(32) UNKNOWN;
6605 WriteBits32Unknown (t);
6606 }
6607 }
6608 return true;
6609}
Caroline Ticefe479112011-02-18 18:52:37 +00006610
Caroline Tice952b5382011-02-28 23:15:24 +00006611// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6612// zero-extends it to form a 32-bit word, and writes it to a register.
6613bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006614EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006615{
6616#if 0
6617 if ConditionPassed() then
6618 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6619 base = Align(PC,4);
6620 address = if add then (base + imm32) else (base - imm32);
6621 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006622 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006623 R[t] = ZeroExtend(data, 32);
6624 else // Can only apply before ARMv7
6625 R[t] = bits(32) UNKNOWN;
6626#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006627
Caroline Tice952b5382011-02-28 23:15:24 +00006628 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006629
Greg Clayton7bc39082011-03-24 23:53:38 +00006630 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006631 {
6632 uint32_t t;
6633 uint32_t imm32;
6634 bool add;
6635
6636 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6637 switch (encoding)
6638 {
6639 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006640 // if Rt == '1111' then SEE "Unallocated memory hints";
6641 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006642 t = Bits32 (opcode, 15, 12);
6643 imm32 = Bits32 (opcode, 11, 0);
6644 add = BitIsSet (opcode, 23);
6645
6646 // if t == 13 then UNPREDICTABLE;
6647 if (t == 13)
6648 return false;
6649
6650 break;
6651
6652 case eEncodingA1:
6653 {
6654 uint32_t imm4H = Bits32 (opcode, 11, 8);
6655 uint32_t imm4L = Bits32 (opcode, 3, 0);
6656
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006657 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006658 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006659 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006660 add = BitIsSet (opcode, 23);
6661
6662 // if t == 15 then UNPREDICTABLE;
6663 if (t == 15)
6664 return false;
6665 break;
6666 }
6667
6668 default:
6669 return false;
6670 }
6671
6672 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006673 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006674 if (!success)
6675 return false;
6676
6677 addr_t base = AlignPC (pc_value);
6678 addr_t address;
6679
6680 // address = if add then (base + imm32) else (base - imm32);
6681 if (add)
6682 address = base + imm32;
6683 else
6684 address = base - imm32;
6685
6686 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006687 RegisterInfo base_reg;
6688 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice952b5382011-02-28 23:15:24 +00006689
6690 EmulateInstruction::Context context;
6691 context.type = eContextRegisterLoad;
6692 context.SetRegisterPlusOffset (base_reg, address - base);
6693
6694 uint64_t data = MemURead (context, address, 2, 0, &success);
6695 if (!success)
6696 return false;
6697
6698
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006699 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006700 if (UnalignedSupport () || BitIsClear (address, 0))
6701 {
6702 // R[t] = ZeroExtend(data, 32);
6703 context.type = eContextRegisterLoad;
6704 context.SetRegisterPlusOffset (base_reg, address - base);
6705 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6706 return false;
6707
6708 }
6709 else // Can only apply before ARMv7
6710 {
6711 // R[t] = bits(32) UNKNOWN;
6712 WriteBits32Unknown (t);
6713 }
6714 }
6715 return true;
6716}
6717
Caroline Tice0e6bc952011-03-01 18:00:42 +00006718// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6719// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6720// be shifted left by 0, 1, 2, or 3 bits.
6721bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006722EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006723{
6724#if 0
6725 if ConditionPassed() then
6726 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6727 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6728 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6729 address = if index then offset_addr else R[n];
6730 data = MemU[address,2];
6731 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006732 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006733 R[t] = ZeroExtend(data, 32);
6734 else // Can only apply before ARMv7
6735 R[t] = bits(32) UNKNOWN;
6736#endif
6737
6738 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006739
Greg Clayton7bc39082011-03-24 23:53:38 +00006740 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006741 {
6742 uint32_t t;
6743 uint32_t n;
6744 uint32_t m;
6745 bool index;
6746 bool add;
6747 bool wback;
6748 ARM_ShifterType shift_t;
6749 uint32_t shift_n;
6750
6751 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6752 switch (encoding)
6753 {
6754 case eEncodingT1:
6755 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6756 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6757 t = Bits32 (opcode, 2, 0);
6758 n = Bits32 (opcode, 5, 3);
6759 m = Bits32 (opcode, 8, 6);
6760
6761 // index = TRUE; add = TRUE; wback = FALSE;
6762 index = true;
6763 add = true;
6764 wback = false;
6765
6766 // (shift_t, shift_n) = (SRType_LSL, 0);
6767 shift_t = SRType_LSL;
6768 shift_n = 0;
6769
6770 break;
6771
6772 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006773 // if Rn == '1111' then SEE LDRH (literal);
6774 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006775 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6776 t = Bits32 (opcode, 15, 12);
6777 n = Bits32 (opcode, 19, 16);
6778 m = Bits32 (opcode, 3, 0);
6779
6780 // index = TRUE; add = TRUE; wback = FALSE;
6781 index = true;
6782 add = true;
6783 wback = false;
6784
6785 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6786 shift_t = SRType_LSL;
6787 shift_n = Bits32 (opcode, 5, 4);
6788
6789 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6790 if ((t == 13) || BadReg (m))
6791 return false;
6792 break;
6793
6794 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006795 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006796 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6797 t = Bits32 (opcode, 15, 12);
6798 n = Bits32 (opcode, 19, 16);
6799 m = Bits32 (opcode, 3, 0);
6800
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006801 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006802 index = BitIsSet (opcode, 24);
6803 add = BitIsSet (opcode, 23);
6804 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6805
6806 // (shift_t, shift_n) = (SRType_LSL, 0);
6807 shift_t = SRType_LSL;
6808 shift_n = 0;
6809
6810 // if t == 15 || m == 15 then UNPREDICTABLE;
6811 if ((t == 15) || (m == 15))
6812 return false;
6813
6814 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6815 if (wback && ((n == 15) || (n == t)))
6816 return false;
6817
6818 break;
6819
6820 default:
6821 return false;
6822 }
6823
6824 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6825
6826 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6827 if (!success)
6828 return false;
6829
Johnny Chena4438a72011-06-02 22:50:51 +00006830 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
6831 if (!success)
6832 return false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006833
6834 addr_t offset_addr;
6835 addr_t address;
6836
6837 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6838 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6839 if (!success)
6840 return false;
6841
6842 if (add)
6843 offset_addr = Rn + offset;
6844 else
6845 offset_addr = Rn - offset;
6846
6847 // address = if index then offset_addr else R[n];
6848 if (index)
6849 address = offset_addr;
6850 else
6851 address = Rn;
6852
6853 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00006854 RegisterInfo base_reg;
6855 RegisterInfo offset_reg;
6856 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
6857 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice0e6bc952011-03-01 18:00:42 +00006858
6859 EmulateInstruction::Context context;
6860 context.type = eContextRegisterLoad;
6861 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6862 uint64_t data = MemURead (context, address, 2, 0, &success);
6863 if (!success)
6864 return false;
6865
6866 // if wback then R[n] = offset_addr;
6867 if (wback)
6868 {
6869 context.type = eContextAdjustBaseRegister;
6870 context.SetAddress (offset_addr);
6871 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6872 return false;
6873 }
6874
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006875 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006876 if (UnalignedSupport() || BitIsClear (address, 0))
6877 {
6878 // R[t] = ZeroExtend(data, 32);
6879 context.type = eContextRegisterLoad;
6880 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6881 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6882 return false;
6883 }
6884 else // Can only apply before ARMv7
6885 {
6886 // R[t] = bits(32) UNKNOWN;
6887 WriteBits32Unknown (t);
6888 }
6889 }
6890 return true;
6891}
6892
Caroline Ticea5e28af2011-03-01 21:53:03 +00006893// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6894// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6895// or pre-indexed addressing.
6896bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006897EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006898{
6899#if 0
6900 if ConditionPassed() then
6901 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6902 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6903 address = if index then offset_addr else R[n];
6904 R[t] = SignExtend(MemU[address,1], 32);
6905 if wback then R[n] = offset_addr;
6906#endif
6907
6908 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006909
Greg Clayton7bc39082011-03-24 23:53:38 +00006910 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006911 {
6912 uint32_t t;
6913 uint32_t n;
6914 uint32_t imm32;
6915 bool index;
6916 bool add;
6917 bool wback;
6918
6919 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6920 switch (encoding)
6921 {
6922 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006923 // if Rt == '1111' then SEE PLI;
6924 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006925 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6926 t = Bits32 (opcode, 15, 12);
6927 n = Bits32 (opcode, 19, 16);
6928 imm32 = Bits32 (opcode, 11, 0);
6929
6930 // index = TRUE; add = TRUE; wback = FALSE;
6931 index = true;
6932 add = true;
6933 wback = false;
6934
6935 // if t == 13 then UNPREDICTABLE;
6936 if (t == 13)
6937 return false;
6938
6939 break;
6940
6941 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006942 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6943 // if Rn == '1111' then SEE LDRSB (literal);
6944 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6945 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006946 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6947 return false;
6948
6949 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6950 t = Bits32 (opcode, 15, 12);
6951 n = Bits32 (opcode, 19, 16);
6952 imm32 = Bits32 (opcode, 7, 0);
6953
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006954 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006955 index = BitIsSet (opcode, 10);
6956 add = BitIsSet (opcode, 9);
6957 wback = BitIsSet (opcode, 8);
6958
6959 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006960 if (((t == 13) || ((t == 15)
6961 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6962 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006963 return false;
6964
6965 break;
6966
6967 case eEncodingA1:
6968 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006969 // if Rn == '1111' then SEE LDRSB (literal);
6970 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006971 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6972 t = Bits32 (opcode, 15, 12);
6973 n = Bits32 (opcode, 19, 16);
6974
6975 uint32_t imm4H = Bits32 (opcode, 11, 8);
6976 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006977 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006978
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006979 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006980 index = BitIsSet (opcode, 24);
6981 add = BitIsSet (opcode, 23);
6982 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6983
6984 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6985 if ((t == 15) || (wback && (n == t)))
6986 return false;
6987
6988 break;
6989 }
6990
6991 default:
6992 return false;
6993 }
6994
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006995 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006996 if (!success)
6997 return false;
6998
6999 addr_t offset_addr;
7000 addr_t address;
7001
7002 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7003 if (add)
7004 offset_addr = Rn + imm32;
7005 else
7006 offset_addr = Rn - imm32;
7007
7008 // address = if index then offset_addr else R[n];
7009 if (index)
7010 address = offset_addr;
7011 else
7012 address = Rn;
7013
7014 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007015 RegisterInfo base_reg;
7016 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticea5e28af2011-03-01 21:53:03 +00007017
7018 EmulateInstruction::Context context;
7019 context.type = eContextRegisterLoad;
7020 context.SetRegisterPlusOffset (base_reg, address - Rn);
7021
7022 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7023 if (!success)
7024 return false;
7025
7026 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7027 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7028 return false;
7029
7030 // if wback then R[n] = offset_addr;
7031 if (wback)
7032 {
7033 context.type = eContextAdjustBaseRegister;
7034 context.SetAddress (offset_addr);
7035 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7036 return false;
7037 }
7038 }
7039
7040 return true;
7041}
Caroline Tice0e6bc952011-03-01 18:00:42 +00007042
Caroline Tice5f593912011-03-01 22:25:17 +00007043// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
7044// sign-extends it to form a 32-bit word, and writes tit to a register.
7045bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007046EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00007047{
7048#if 0
7049 if ConditionPassed() then
7050 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7051 base = Align(PC,4);
7052 address = if add then (base + imm32) else (base - imm32);
7053 R[t] = SignExtend(MemU[address,1], 32);
7054#endif
7055
7056 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00007057
Greg Clayton7bc39082011-03-24 23:53:38 +00007058 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00007059 {
7060 uint32_t t;
7061 uint32_t imm32;
7062 bool add;
7063
7064 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7065 switch (encoding)
7066 {
7067 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007068 // if Rt == '1111' then SEE PLI;
7069 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007070 t = Bits32 (opcode, 15, 12);
7071 imm32 = Bits32 (opcode, 11, 0);
7072 add = BitIsSet (opcode, 23);
7073
7074 // if t == 13 then UNPREDICTABLE;
7075 if (t == 13)
7076 return false;
7077
7078 break;
7079
7080 case eEncodingA1:
7081 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007082 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00007083 t = Bits32 (opcode, 15, 12);
7084 uint32_t imm4H = Bits32 (opcode, 11, 8);
7085 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007086 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00007087 add = BitIsSet (opcode, 23);
7088
7089 // if t == 15 then UNPREDICTABLE;
7090 if (t == 15)
7091 return false;
7092
7093 break;
7094 }
7095
7096 default:
7097 return false;
7098 }
7099
7100 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007101 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00007102 if (!success)
7103 return false;
7104 uint64_t base = AlignPC (pc_value);
7105
7106 // address = if add then (base + imm32) else (base - imm32);
7107 addr_t address;
7108 if (add)
7109 address = base + imm32;
7110 else
7111 address = base - imm32;
7112
7113 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007114 RegisterInfo base_reg;
7115 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Tice5f593912011-03-01 22:25:17 +00007116
7117 EmulateInstruction::Context context;
7118 context.type = eContextRegisterLoad;
7119 context.SetRegisterPlusOffset (base_reg, address - base);
7120
7121 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7122 if (!success)
7123 return false;
7124
7125 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7126 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7127 return false;
7128 }
7129 return true;
7130}
7131
Caroline Tice672f3112011-03-01 23:55:59 +00007132// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7133// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7134// shifted left by 0, 1, 2, or 3 bits.
7135bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007136EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00007137{
7138#if 0
7139 if ConditionPassed() then
7140 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7141 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7142 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7143 address = if index then offset_addr else R[n];
7144 R[t] = SignExtend(MemU[address,1], 32);
7145 if wback then R[n] = offset_addr;
7146#endif
7147
7148 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00007149
Greg Clayton7bc39082011-03-24 23:53:38 +00007150 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00007151 {
7152 uint32_t t;
7153 uint32_t n;
7154 uint32_t m;
7155 bool index;
7156 bool add;
7157 bool wback;
7158 ARM_ShifterType shift_t;
7159 uint32_t shift_n;
7160
7161 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7162 switch (encoding)
7163 {
7164 case eEncodingT1:
7165 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7166 t = Bits32 (opcode, 2, 0);
7167 n = Bits32 (opcode, 5, 3);
7168 m = Bits32 (opcode, 8, 6);
7169
7170 // index = TRUE; add = TRUE; wback = FALSE;
7171 index = true;
7172 add = true;
7173 wback = false;
7174
7175 // (shift_t, shift_n) = (SRType_LSL, 0);
7176 shift_t = SRType_LSL;
7177 shift_n = 0;
7178
7179 break;
7180
7181 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007182 // if Rt == '1111' then SEE PLI;
7183 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00007184 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7185 t = Bits32 (opcode, 15, 12);
7186 n = Bits32 (opcode, 19, 16);
7187 m = Bits32 (opcode, 3, 0);
7188
7189 // index = TRUE; add = TRUE; wback = FALSE;
7190 index = true;
7191 add = true;
7192 wback = false;
7193
7194 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7195 shift_t = SRType_LSL;
7196 shift_n = Bits32 (opcode, 5, 4);
7197
7198 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7199 if ((t == 13) || BadReg (m))
7200 return false;
7201 break;
7202
7203 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007204 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007205 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7206 t = Bits32 (opcode, 15, 12);
7207 n = Bits32 (opcode, 19, 16);
7208 m = Bits32 (opcode, 3, 0);
7209
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007210 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007211 index = BitIsSet (opcode, 24);
7212 add = BitIsSet (opcode, 23);
7213 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7214
7215 // (shift_t, shift_n) = (SRType_LSL, 0);
7216 shift_t = SRType_LSL;
7217 shift_n = 0;
7218
7219 // if t == 15 || m == 15 then UNPREDICTABLE;
7220 if ((t == 15) || (m == 15))
7221 return false;
7222
7223 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7224 if (wback && ((n == 15) || (n == t)))
7225 return false;
7226 break;
7227
7228 default:
7229 return false;
7230 }
7231
7232 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7233 if (!success)
7234 return false;
7235
7236 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00007237 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7238 if (!success)
7239 return false;
Caroline Tice672f3112011-03-01 23:55:59 +00007240
7241 addr_t offset_addr;
7242 addr_t address;
7243
7244 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7245 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7246 if (!success)
7247 return false;
7248
7249 if (add)
7250 offset_addr = Rn + offset;
7251 else
7252 offset_addr = Rn - offset;
7253
7254 // address = if index then offset_addr else R[n];
7255 if (index)
7256 address = offset_addr;
7257 else
7258 address = Rn;
7259
7260 // R[t] = SignExtend(MemU[address,1], 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007261 RegisterInfo base_reg;
7262 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
7263 RegisterInfo offset_reg;
7264 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice672f3112011-03-01 23:55:59 +00007265
7266 EmulateInstruction::Context context;
7267 context.type = eContextRegisterLoad;
7268 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7269
7270 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7271 if (!success)
7272 return false;
7273
7274 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7275 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7276 return false;
7277
7278 // if wback then R[n] = offset_addr;
7279 if (wback)
7280 {
7281 context.type = eContextAdjustBaseRegister;
7282 context.SetAddress (offset_addr);
7283 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7284 return false;
7285 }
7286 }
7287 return true;
7288}
7289
Caroline Tice78fb5632011-03-02 00:39:42 +00007290// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7291// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7292// pre-indexed addressing.
7293bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007294EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007295{
7296#if 0
7297 if ConditionPassed() then
7298 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7299 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7300 address = if index then offset_addr else R[n];
7301 data = MemU[address,2];
7302 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007303 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007304 R[t] = SignExtend(data, 32);
7305 else // Can only apply before ARMv7
7306 R[t] = bits(32) UNKNOWN;
7307#endif
7308
7309 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007310
Greg Clayton7bc39082011-03-24 23:53:38 +00007311 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007312 {
7313 uint32_t t;
7314 uint32_t n;
7315 uint32_t imm32;
7316 bool index;
7317 bool add;
7318 bool wback;
7319
7320 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7321 switch (encoding)
7322 {
7323 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007324 // if Rn == '1111' then SEE LDRSH (literal);
7325 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007326 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7327 t = Bits32 (opcode, 15, 12);
7328 n = Bits32 (opcode, 19, 16);
7329 imm32 = Bits32 (opcode, 11, 0);
7330
7331 // index = TRUE; add = TRUE; wback = FALSE;
7332 index = true;
7333 add = true;
7334 wback = false;
7335
7336 // if t == 13 then UNPREDICTABLE;
7337 if (t == 13)
7338 return false;
7339
7340 break;
7341
7342 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007343 // if Rn == '1111' then SEE LDRSH (literal);
7344 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7345 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7346 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007347 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7348 return false;
7349
7350 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7351 t = Bits32 (opcode, 15, 12);
7352 n = Bits32 (opcode, 19, 16);
7353 imm32 = Bits32 (opcode, 7, 0);
7354
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007355 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007356 index = BitIsSet (opcode, 10);
7357 add = BitIsSet (opcode, 9);
7358 wback = BitIsSet (opcode, 8);
7359
7360 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7361 if (BadReg (t) || (wback && (n == t)))
7362 return false;
7363
7364 break;
7365
7366 case eEncodingA1:
7367 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007368 // if Rn == '1111' then SEE LDRSH (literal);
7369 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007370 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7371 t = Bits32 (opcode, 15, 12);
7372 n = Bits32 (opcode, 19, 16);
7373 uint32_t imm4H = Bits32 (opcode, 11,8);
7374 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007375 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007376
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007377 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007378 index = BitIsSet (opcode, 24);
7379 add = BitIsSet (opcode, 23);
7380 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7381
7382 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7383 if ((t == 15) || (wback && (n == t)))
7384 return false;
7385
7386 break;
7387 }
7388
7389 default:
7390 return false;
7391 }
7392
7393 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7394 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7395 if (!success)
7396 return false;
7397
7398 addr_t offset_addr;
7399 if (add)
7400 offset_addr = Rn + imm32;
7401 else
7402 offset_addr = Rn - imm32;
7403
7404 // address = if index then offset_addr else R[n];
7405 addr_t address;
7406 if (index)
7407 address = offset_addr;
7408 else
7409 address = Rn;
7410
7411 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007412 RegisterInfo base_reg;
7413 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice78fb5632011-03-02 00:39:42 +00007414
7415 EmulateInstruction::Context context;
7416 context.type = eContextRegisterLoad;
7417 context.SetRegisterPlusOffset (base_reg, address - Rn);
7418
7419 uint64_t data = MemURead (context, address, 2, 0, &success);
7420 if (!success)
7421 return false;
7422
7423 // if wback then R[n] = offset_addr;
7424 if (wback)
7425 {
7426 context.type = eContextAdjustBaseRegister;
7427 context.SetAddress (offset_addr);
7428 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7429 return false;
7430 }
7431
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007432 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007433 if (UnalignedSupport() || BitIsClear (address, 0))
7434 {
7435 // R[t] = SignExtend(data, 32);
7436 int64_t signed_data = llvm::SignExtend64<16>(data);
7437 context.type = eContextRegisterLoad;
7438 context.SetRegisterPlusOffset (base_reg, address - Rn);
7439 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7440 return false;
7441 }
7442 else // Can only apply before ARMv7
7443 {
7444 // R[t] = bits(32) UNKNOWN;
7445 WriteBits32Unknown (t);
7446 }
7447 }
7448 return true;
7449}
7450
Caroline Ticed2fac092011-03-02 19:45:34 +00007451// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7452// sign-extends it to from a 32-bit word, and writes it to a register.
7453bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007454EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007455{
7456#if 0
7457 if ConditionPassed() then
7458 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7459 base = Align(PC,4);
7460 address = if add then (base + imm32) else (base - imm32);
7461 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007462 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007463 R[t] = SignExtend(data, 32);
7464 else // Can only apply before ARMv7
7465 R[t] = bits(32) UNKNOWN;
7466#endif
7467
7468 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007469
Greg Clayton7bc39082011-03-24 23:53:38 +00007470 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007471 {
7472 uint32_t t;
7473 uint32_t imm32;
7474 bool add;
7475
7476 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7477 switch (encoding)
7478 {
7479 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007480 // if Rt == '1111' then SEE "Unallocated memory hints";
7481 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007482 t = Bits32 (opcode, 15, 12);
7483 imm32 = Bits32 (opcode, 11, 0);
7484 add = BitIsSet (opcode, 23);
7485
7486 // if t == 13 then UNPREDICTABLE;
7487 if (t == 13)
7488 return false;
7489
7490 break;
7491
7492 case eEncodingA1:
7493 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007494 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007495 t = Bits32 (opcode, 15, 12);
7496 uint32_t imm4H = Bits32 (opcode, 11, 8);
7497 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007498 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007499 add = BitIsSet (opcode, 23);
7500
7501 // if t == 15 then UNPREDICTABLE;
7502 if (t == 15)
7503 return false;
7504
7505 break;
7506 }
7507 default:
7508 return false;
7509 }
7510
7511 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007512 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007513 if (!success)
7514 return false;
7515
7516 uint64_t base = AlignPC (pc_value);
7517
7518 addr_t address;
7519 // address = if add then (base + imm32) else (base - imm32);
7520 if (add)
7521 address = base + imm32;
7522 else
7523 address = base - imm32;
7524
7525 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007526 RegisterInfo base_reg;
7527 GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
Caroline Ticed2fac092011-03-02 19:45:34 +00007528
7529 EmulateInstruction::Context context;
7530 context.type = eContextRegisterLoad;
7531 context.SetRegisterPlusOffset (base_reg, imm32);
7532
7533 uint64_t data = MemURead (context, address, 2, 0, &success);
7534 if (!success)
7535 return false;
7536
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007537 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007538 if (UnalignedSupport() || BitIsClear (address, 0))
7539 {
7540 // R[t] = SignExtend(data, 32);
7541 int64_t signed_data = llvm::SignExtend64<16>(data);
7542 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7543 return false;
7544 }
7545 else // Can only apply before ARMv7
7546 {
7547 // R[t] = bits(32) UNKNOWN;
7548 WriteBits32Unknown (t);
7549 }
7550 }
7551 return true;
7552}
7553
Caroline Tice291a3e92011-03-02 21:13:44 +00007554// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7555// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7556// shifted left by 0, 1, 2, or 3 bits.
7557bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007558EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007559{
7560#if 0
7561 if ConditionPassed() then
7562 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7563 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7564 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7565 address = if index then offset_addr else R[n];
7566 data = MemU[address,2];
7567 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007568 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007569 R[t] = SignExtend(data, 32);
7570 else // Can only apply before ARMv7
7571 R[t] = bits(32) UNKNOWN;
7572#endif
7573
7574 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007575
Greg Clayton7bc39082011-03-24 23:53:38 +00007576 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007577 {
7578 uint32_t t;
7579 uint32_t n;
7580 uint32_t m;
7581 bool index;
7582 bool add;
7583 bool wback;
7584 ARM_ShifterType shift_t;
7585 uint32_t shift_n;
7586
7587 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7588 switch (encoding)
7589 {
7590 case eEncodingT1:
7591 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7592 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7593 t = Bits32 (opcode, 2, 0);
7594 n = Bits32 (opcode, 5, 3);
7595 m = Bits32 (opcode, 8, 6);
7596
7597 // index = TRUE; add = TRUE; wback = FALSE;
7598 index = true;
7599 add = true;
7600 wback = false;
7601
7602 // (shift_t, shift_n) = (SRType_LSL, 0);
7603 shift_t = SRType_LSL;
7604 shift_n = 0;
7605
7606 break;
7607
7608 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007609 // if Rn == '1111' then SEE LDRSH (literal);
7610 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007611 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7612 t = Bits32 (opcode, 15, 12);
7613 n = Bits32 (opcode, 19, 16);
7614 m = Bits32 (opcode, 3, 0);
7615
7616 // index = TRUE; add = TRUE; wback = FALSE;
7617 index = true;
7618 add = true;
7619 wback = false;
7620
7621 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7622 shift_t = SRType_LSL;
7623 shift_n = Bits32 (opcode, 5, 4);
7624
7625 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7626 if ((t == 13) || BadReg (m))
7627 return false;
7628
7629 break;
7630
7631 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007632 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007633 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7634 t = Bits32 (opcode, 15, 12);
7635 n = Bits32 (opcode, 19, 16);
7636 m = Bits32 (opcode, 3, 0);
7637
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007638 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007639 index = BitIsSet (opcode, 24);
7640 add = BitIsSet (opcode, 23);
7641 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7642
7643 // (shift_t, shift_n) = (SRType_LSL, 0);
7644 shift_t = SRType_LSL;
7645 shift_n = 0;
7646
7647 // if t == 15 || m == 15 then UNPREDICTABLE;
7648 if ((t == 15) || (m == 15))
7649 return false;
7650
7651 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7652 if (wback && ((n == 15) || (n == t)))
7653 return false;
7654
7655 break;
7656
7657 default:
7658 break;
7659 }
7660
7661 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7662 if (!success)
7663 return false;
7664
7665 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7666 if (!success)
7667 return false;
7668
7669 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chena4438a72011-06-02 22:50:51 +00007670 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
7671 if (!success)
7672 return false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007673
7674 addr_t offset_addr;
7675 addr_t address;
7676
7677 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7678 if (add)
7679 offset_addr = Rn + offset;
7680 else
7681 offset_addr = Rn - offset;
7682
7683 // address = if index then offset_addr else R[n];
7684 if (index)
7685 address = offset_addr;
7686 else
7687 address = Rn;
7688
7689 // data = MemU[address,2];
Greg Claytonc07d4512011-04-26 23:48:45 +00007690 RegisterInfo base_reg;
7691 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007692
Greg Claytonc07d4512011-04-26 23:48:45 +00007693 RegisterInfo offset_reg;
7694 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Tice291a3e92011-03-02 21:13:44 +00007695
7696 EmulateInstruction::Context context;
7697 context.type = eContextRegisterLoad;
7698 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7699
7700 uint64_t data = MemURead (context, address, 2, 0, &success);
7701 if (!success)
7702 return false;
7703
7704 // if wback then R[n] = offset_addr;
7705 if (wback)
7706 {
7707 context.type = eContextAdjustBaseRegister;
7708 context.SetAddress (offset_addr);
7709 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7710 return false;
7711 }
7712
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007713 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007714 if (UnalignedSupport() || BitIsClear (address, 0))
7715 {
7716 // R[t] = SignExtend(data, 32);
7717 context.type = eContextRegisterLoad;
7718 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7719
7720 int64_t signed_data = llvm::SignExtend64<16>(data);
7721 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7722 return false;
7723 }
7724 else // Can only apply before ARMv7
7725 {
7726 // R[t] = bits(32) UNKNOWN;
7727 WriteBits32Unknown (t);
7728 }
7729 }
7730 return true;
7731}
Caroline Tice6bf65162011-03-03 17:42:58 +00007732
7733// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7734// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7735bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007736EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007737{
7738#if 0
7739 if ConditionPassed() then
7740 EncodingSpecificOperations();
7741 rotated = ROR(R[m], rotation);
7742 R[d] = SignExtend(rotated<7:0>, 32);
7743#endif
7744
7745 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007746
Greg Clayton7bc39082011-03-24 23:53:38 +00007747 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007748 {
7749 uint32_t d;
7750 uint32_t m;
7751 uint32_t rotation;
7752
7753 // EncodingSpecificOperations();
7754 switch (encoding)
7755 {
7756 case eEncodingT1:
7757 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7758 d = Bits32 (opcode, 2, 0);
7759 m = Bits32 (opcode, 5, 3);
7760 rotation = 0;
7761
7762 break;
7763
7764 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007765 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007766 d = Bits32 (opcode, 11, 8);
7767 m = Bits32 (opcode, 3, 0);
7768 rotation = Bits32 (opcode, 5, 4) << 3;
7769
7770 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7771 if (BadReg (d) || BadReg (m))
7772 return false;
7773
7774 break;
7775
7776 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007777 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007778 d = Bits32 (opcode, 15, 12);
7779 m = Bits32 (opcode, 3, 0);
7780 rotation = Bits32 (opcode, 11, 10) << 3;
7781
7782 // if d == 15 || m == 15 then UNPREDICTABLE;
7783 if ((d == 15) || (m == 15))
7784 return false;
7785
7786 break;
7787
7788 default:
7789 return false;
7790 }
7791
Caroline Tice868198b2011-03-03 18:04:49 +00007792 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7793 if (!success)
7794 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007795
7796 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007797 uint64_t rotated = ROR (Rm, rotation, &success);
7798 if (!success)
7799 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007800
7801 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007802 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007803
Greg Claytonc07d4512011-04-26 23:48:45 +00007804 RegisterInfo source_reg;
7805 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice6bf65162011-03-03 17:42:58 +00007806
7807 EmulateInstruction::Context context;
7808 context.type = eContextRegisterLoad;
7809 context.SetRegister (source_reg);
7810
Caroline Tice8ce96d92011-03-03 18:27:17 +00007811 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007812 return false;
7813 }
7814 return true;
7815}
Caroline Tice291a3e92011-03-02 21:13:44 +00007816
Caroline Tice868198b2011-03-03 18:04:49 +00007817// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7818// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7819bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007820EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007821{
7822#if 0
7823 if ConditionPassed() then
7824 EncodingSpecificOperations();
7825 rotated = ROR(R[m], rotation);
7826 R[d] = SignExtend(rotated<15:0>, 32);
7827#endif
7828
7829 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007830
Greg Clayton7bc39082011-03-24 23:53:38 +00007831 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007832 {
7833 uint32_t d;
7834 uint32_t m;
7835 uint32_t rotation;
7836
7837 // EncodingSpecificOperations();
7838 switch (encoding)
7839 {
7840 case eEncodingT1:
7841 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7842 d = Bits32 (opcode, 2, 0);
7843 m = Bits32 (opcode, 5, 3);
7844 rotation = 0;
7845
7846 break;
7847
7848 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007849 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007850 d = Bits32 (opcode, 11, 8);
7851 m = Bits32 (opcode, 3, 0);
7852 rotation = Bits32 (opcode, 5, 4) << 3;
7853
7854 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7855 if (BadReg (d) || BadReg (m))
7856 return false;
7857
7858 break;
7859
7860 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007861 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007862 d = Bits32 (opcode, 15, 12);
7863 m = Bits32 (opcode, 3, 0);
7864 rotation = Bits32 (opcode, 11, 10) << 3;
7865
7866 // if d == 15 || m == 15 then UNPREDICTABLE;
7867 if ((d == 15) || (m == 15))
7868 return false;
7869
7870 break;
7871
7872 default:
7873 return false;
7874 }
7875
7876 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7877 if (!success)
7878 return false;
7879
7880 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007881 uint64_t rotated = ROR (Rm, rotation, &success);
7882 if (!success)
7883 return false;
Caroline Tice868198b2011-03-03 18:04:49 +00007884
7885 // R[d] = SignExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007886 RegisterInfo source_reg;
7887 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice868198b2011-03-03 18:04:49 +00007888
7889 EmulateInstruction::Context context;
7890 context.type = eContextRegisterLoad;
7891 context.SetRegister (source_reg);
7892
Caroline Tice8ce96d92011-03-03 18:27:17 +00007893 int64_t data = llvm::SignExtend64<16> (rotated);
7894 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007895 return false;
7896 }
7897
7898 return true;
7899}
7900
Caroline Tice8ce96d92011-03-03 18:27:17 +00007901// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7902// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7903bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007904EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007905{
7906#if 0
7907 if ConditionPassed() then
7908 EncodingSpecificOperations();
7909 rotated = ROR(R[m], rotation);
7910 R[d] = ZeroExtend(rotated<7:0>, 32);
7911#endif
7912
7913 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007914
Greg Clayton7bc39082011-03-24 23:53:38 +00007915 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007916 {
7917 uint32_t d;
7918 uint32_t m;
7919 uint32_t rotation;
7920
7921 // EncodingSpecificOperations();
7922 switch (encoding)
7923 {
7924 case eEncodingT1:
7925 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7926 d = Bits32 (opcode, 2, 0);
7927 m = Bits32 (opcode, 5, 3);
7928 rotation = 0;
7929
7930 break;
7931
7932 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007933 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007934 d = Bits32 (opcode, 11, 8);
7935 m = Bits32 (opcode, 3, 0);
7936 rotation = Bits32 (opcode, 5, 4) << 3;
7937
7938 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7939 if (BadReg (d) || BadReg (m))
7940 return false;
7941
7942 break;
7943
7944 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007945 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007946 d = Bits32 (opcode, 15, 12);
7947 m = Bits32 (opcode, 3, 0);
7948 rotation = Bits32 (opcode, 11, 10) << 3;
7949
7950 // if d == 15 || m == 15 then UNPREDICTABLE;
7951 if ((d == 15) || (m == 15))
7952 return false;
7953
7954 break;
7955
7956 default:
7957 return false;
7958 }
7959
7960 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7961 if (!success)
7962 return false;
7963
7964 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00007965 uint64_t rotated = ROR (Rm, rotation, &success);
7966 if (!success)
7967 return false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007968
7969 // R[d] = ZeroExtend(rotated<7:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00007970 RegisterInfo source_reg;
7971 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007972
7973 EmulateInstruction::Context context;
7974 context.type = eContextRegisterLoad;
7975 context.SetRegister (source_reg);
7976
7977 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7978 return false;
7979 }
7980 return true;
7981}
7982
Caroline Tice11555f22011-03-03 18:48:58 +00007983// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7984// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7985bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007986EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007987{
7988#if 0
7989 if ConditionPassed() then
7990 EncodingSpecificOperations();
7991 rotated = ROR(R[m], rotation);
7992 R[d] = ZeroExtend(rotated<15:0>, 32);
7993#endif
7994
7995 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007996
Greg Clayton7bc39082011-03-24 23:53:38 +00007997 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007998 {
7999 uint32_t d;
8000 uint32_t m;
8001 uint32_t rotation;
8002
8003 switch (encoding)
8004 {
8005 case eEncodingT1:
8006 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8007 d = Bits32 (opcode, 2, 0);
8008 m = Bits32 (opcode, 5, 3);
8009 rotation = 0;
8010
8011 break;
8012
8013 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008014 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00008015 d = Bits32 (opcode, 11, 8);
8016 m = Bits32 (opcode, 3, 0);
8017 rotation = Bits32 (opcode, 5, 4) << 3;
8018
8019 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8020 if (BadReg (d) || BadReg (m))
8021 return false;
8022
8023 break;
8024
8025 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008026 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00008027 d = Bits32 (opcode, 15, 12);
8028 m = Bits32 (opcode, 3, 0);
8029 rotation = Bits32 (opcode, 11, 10) << 3;
8030
8031 // if d == 15 || m == 15 then UNPREDICTABLE;
8032 if ((d == 15) || (m == 15))
8033 return false;
8034
8035 break;
8036
8037 default:
8038 return false;
8039 }
8040
8041 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8042 if (!success)
8043 return false;
8044
8045 // rotated = ROR(R[m], rotation);
Johnny Chena4438a72011-06-02 22:50:51 +00008046 uint64_t rotated = ROR (Rm, rotation, &success);
8047 if (!success)
8048 return false;
Caroline Tice11555f22011-03-03 18:48:58 +00008049
8050 // R[d] = ZeroExtend(rotated<15:0>, 32);
Greg Claytonc07d4512011-04-26 23:48:45 +00008051 RegisterInfo source_reg;
8052 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
Caroline Tice11555f22011-03-03 18:48:58 +00008053
8054 EmulateInstruction::Context context;
8055 context.type = eContextRegisterLoad;
8056 context.SetRegister (source_reg);
8057
8058 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
8059 return false;
8060 }
8061 return true;
8062}
Caroline Ticeb27771d2011-03-03 22:37:46 +00008063
8064// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
8065// word respectively.
8066bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008067EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00008068{
8069#if 0
8070 if ConditionPassed() then
8071 EncodingSpecificOperations();
8072 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8073 UNPREDICTABLE;
8074 else
8075 address = if increment then R[n] else R[n]-8;
8076 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008077 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008078 BranchWritePC(MemA[address,4]);
8079 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8080#endif
8081
8082 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008083
Greg Clayton7bc39082011-03-24 23:53:38 +00008084 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00008085 {
8086 uint32_t n;
8087 bool wback;
8088 bool increment;
8089 bool wordhigher;
8090
8091 // EncodingSpecificOperations();
8092 switch (encoding)
8093 {
8094 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008095 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008096 n = Bits32 (opcode, 19, 16);
8097 wback = BitIsSet (opcode, 21);
8098 increment = false;
8099 wordhigher = false;
8100
8101 // if n == 15 then UNPREDICTABLE;
8102 if (n == 15)
8103 return false;
8104
8105 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8106 if (InITBlock() && !LastInITBlock())
8107 return false;
8108
8109 break;
8110
8111 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008112 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00008113 n = Bits32 (opcode, 19, 16);
8114 wback = BitIsSet (opcode, 21);
8115 increment = true;
8116 wordhigher = false;
8117
8118 // if n == 15 then UNPREDICTABLE;
8119 if (n == 15)
8120 return false;
8121
8122 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8123 if (InITBlock() && !LastInITBlock())
8124 return false;
8125
8126 break;
8127
8128 case eEncodingA1:
8129 // n = UInt(Rn);
8130 n = Bits32 (opcode, 19, 16);
8131
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008132 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008133 wback = BitIsSet (opcode, 21);
8134 increment = BitIsSet (opcode, 23);
8135 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8136
8137 // if n == 15 then UNPREDICTABLE;
8138 if (n == 15)
8139 return false;
8140
8141 break;
8142
8143 default:
8144 return false;
8145 }
8146
8147 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8148 if (!CurrentModeIsPrivileged ())
8149 // UNPREDICTABLE;
8150 return false;
8151 else
8152 {
8153 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8154 if (!success)
8155 return false;
8156
8157 addr_t address;
8158 // address = if increment then R[n] else R[n]-8;
8159 if (increment)
8160 address = Rn;
8161 else
8162 address = Rn - 8;
8163
8164 // if wordhigher then address = address+4;
8165 if (wordhigher)
8166 address = address + 4;
8167
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008168 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Greg Claytonc07d4512011-04-26 23:48:45 +00008169 RegisterInfo base_reg;
8170 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb27771d2011-03-03 22:37:46 +00008171
8172 EmulateInstruction::Context context;
8173 context.type = eContextReturnFromException;
8174 context.SetRegisterPlusOffset (base_reg, address - Rn);
8175
8176 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8177 if (!success)
8178 return false;
8179
8180 CPSRWriteByInstr (data, 15, true);
8181
8182 // BranchWritePC(MemA[address,4]);
8183 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8184 if (!success)
8185 return false;
8186
8187 BranchWritePC (context, data2);
8188
8189 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8190 if (wback)
8191 {
8192 context.type = eContextAdjustBaseRegister;
8193 if (increment)
8194 {
8195 context.SetOffset (8);
8196 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8197 return false;
8198 }
8199 else
8200 {
8201 context.SetOffset (-8);
8202 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8203 return false;
8204 }
8205 } // if wback
8206 }
8207 } // if ConditionPassed()
8208 return true;
8209}
Caroline Tice11555f22011-03-03 18:48:58 +00008210
Johnny Chen2115b412011-02-21 23:42:44 +00008211// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8212// and writes the result to the destination register. It can optionally update the condition flags based on
8213// the result.
8214bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008215EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008216{
8217#if 0
8218 // ARM pseudo code...
8219 if ConditionPassed() then
8220 EncodingSpecificOperations();
8221 result = R[n] EOR imm32;
8222 if d == 15 then // Can only occur for ARM encoding
8223 ALUWritePC(result); // setflags is always FALSE here
8224 else
8225 R[d] = result;
8226 if setflags then
8227 APSR.N = result<31>;
8228 APSR.Z = IsZeroBit(result);
8229 APSR.C = carry;
8230 // APSR.V unchanged
8231#endif
8232
8233 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008234
Greg Clayton7bc39082011-03-24 23:53:38 +00008235 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008236 {
8237 uint32_t Rd, Rn;
8238 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8239 bool setflags;
8240 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8241 switch (encoding)
8242 {
8243 case eEncodingT1:
8244 Rd = Bits32(opcode, 11, 8);
8245 Rn = Bits32(opcode, 19, 16);
8246 setflags = BitIsSet(opcode, 20);
8247 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8248 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8249 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008250 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008251 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8252 return false;
8253 break;
8254 case eEncodingA1:
8255 Rd = Bits32(opcode, 15, 12);
8256 Rn = Bits32(opcode, 19, 16);
8257 setflags = BitIsSet(opcode, 20);
8258 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008259
Johnny Chen2115b412011-02-21 23:42:44 +00008260 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008261 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008262 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008263 break;
8264 default:
8265 return false;
8266 }
8267
8268 // Read the first operand.
8269 uint32_t val1 = ReadCoreReg(Rn, &success);
8270 if (!success)
8271 return false;
8272
8273 uint32_t result = val1 ^ imm32;
8274
8275 EmulateInstruction::Context context;
8276 context.type = EmulateInstruction::eContextImmediate;
8277 context.SetNoArgs ();
8278
8279 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8280 return false;
8281 }
8282 return true;
8283}
8284
8285// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8286// optionally-shifted register value, and writes the result to the destination register.
8287// It can optionally update the condition flags based on the result.
8288bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008289EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008290{
8291#if 0
8292 // ARM pseudo code...
8293 if ConditionPassed() then
8294 EncodingSpecificOperations();
8295 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8296 result = R[n] EOR shifted;
8297 if d == 15 then // Can only occur for ARM encoding
8298 ALUWritePC(result); // setflags is always FALSE here
8299 else
8300 R[d] = result;
8301 if setflags then
8302 APSR.N = result<31>;
8303 APSR.Z = IsZeroBit(result);
8304 APSR.C = carry;
8305 // APSR.V unchanged
8306#endif
8307
8308 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008309
Greg Clayton7bc39082011-03-24 23:53:38 +00008310 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008311 {
8312 uint32_t Rd, Rn, Rm;
8313 ARM_ShifterType shift_t;
8314 uint32_t shift_n; // the shift applied to the value read from Rm
8315 bool setflags;
8316 uint32_t carry;
8317 switch (encoding)
8318 {
8319 case eEncodingT1:
8320 Rd = Rn = Bits32(opcode, 2, 0);
8321 Rm = Bits32(opcode, 5, 3);
8322 setflags = !InITBlock();
8323 shift_t = SRType_LSL;
8324 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008325 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008326 case eEncodingT2:
8327 Rd = Bits32(opcode, 11, 8);
8328 Rn = Bits32(opcode, 19, 16);
8329 Rm = Bits32(opcode, 3, 0);
8330 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008331 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8332 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008333 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008334 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008335 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8336 return false;
8337 break;
8338 case eEncodingA1:
8339 Rd = Bits32(opcode, 15, 12);
8340 Rn = Bits32(opcode, 19, 16);
8341 Rm = Bits32(opcode, 3, 0);
8342 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008343 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008344
Johnny Chen2115b412011-02-21 23:42:44 +00008345 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen2115b412011-02-21 23:42:44 +00008346 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008347 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen2115b412011-02-21 23:42:44 +00008348 break;
8349 default:
8350 return false;
8351 }
8352
8353 // Read the first operand.
8354 uint32_t val1 = ReadCoreReg(Rn, &success);
8355 if (!success)
8356 return false;
8357
8358 // Read the second operand.
8359 uint32_t val2 = ReadCoreReg(Rm, &success);
8360 if (!success)
8361 return false;
8362
Johnny Chena4438a72011-06-02 22:50:51 +00008363 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8364 if (!success)
8365 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00008366 uint32_t result = val1 ^ shifted;
8367
8368 EmulateInstruction::Context context;
8369 context.type = EmulateInstruction::eContextImmediate;
8370 context.SetNoArgs ();
8371
8372 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8373 return false;
8374 }
8375 return true;
8376}
8377
Johnny Chen7c5234d2011-02-18 23:41:11 +00008378// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8379// writes the result to the destination register. It can optionally update the condition flags based
8380// on the result.
8381bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008382EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008383{
8384#if 0
8385 // ARM pseudo code...
8386 if ConditionPassed() then
8387 EncodingSpecificOperations();
8388 result = R[n] OR imm32;
8389 if d == 15 then // Can only occur for ARM encoding
8390 ALUWritePC(result); // setflags is always FALSE here
8391 else
8392 R[d] = result;
8393 if setflags then
8394 APSR.N = result<31>;
8395 APSR.Z = IsZeroBit(result);
8396 APSR.C = carry;
8397 // APSR.V unchanged
8398#endif
8399
8400 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008401
Greg Clayton7bc39082011-03-24 23:53:38 +00008402 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008403 {
8404 uint32_t Rd, Rn;
8405 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8406 bool setflags;
8407 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8408 switch (encoding)
8409 {
8410 case eEncodingT1:
8411 Rd = Bits32(opcode, 11, 8);
8412 Rn = Bits32(opcode, 19, 16);
8413 setflags = BitIsSet(opcode, 20);
8414 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008415 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008416 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008417 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008418 if (BadReg(Rd) || Rn == 13)
8419 return false;
8420 break;
8421 case eEncodingA1:
8422 Rd = Bits32(opcode, 15, 12);
8423 Rn = Bits32(opcode, 19, 16);
8424 setflags = BitIsSet(opcode, 20);
8425 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Tice1f954f52011-04-11 15:51:10 +00008426
Johnny Chen7c5234d2011-02-18 23:41:11 +00008427 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008428 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008429 break;
8430 default:
8431 return false;
8432 }
8433
8434 // Read the first operand.
8435 uint32_t val1 = ReadCoreReg(Rn, &success);
8436 if (!success)
8437 return false;
8438
8439 uint32_t result = val1 | imm32;
8440
8441 EmulateInstruction::Context context;
8442 context.type = EmulateInstruction::eContextImmediate;
8443 context.SetNoArgs ();
8444
8445 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8446 return false;
8447 }
8448 return true;
8449}
8450
8451// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8452// value, and writes the result to the destination register. It can optionally update the condition flags based
8453// on the result.
8454bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008455EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008456{
8457#if 0
8458 // ARM pseudo code...
8459 if ConditionPassed() then
8460 EncodingSpecificOperations();
8461 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8462 result = R[n] OR shifted;
8463 if d == 15 then // Can only occur for ARM encoding
8464 ALUWritePC(result); // setflags is always FALSE here
8465 else
8466 R[d] = result;
8467 if setflags then
8468 APSR.N = result<31>;
8469 APSR.Z = IsZeroBit(result);
8470 APSR.C = carry;
8471 // APSR.V unchanged
8472#endif
8473
8474 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008475
Greg Clayton7bc39082011-03-24 23:53:38 +00008476 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008477 {
8478 uint32_t Rd, Rn, Rm;
8479 ARM_ShifterType shift_t;
8480 uint32_t shift_n; // the shift applied to the value read from Rm
8481 bool setflags;
8482 uint32_t carry;
8483 switch (encoding)
8484 {
8485 case eEncodingT1:
8486 Rd = Rn = Bits32(opcode, 2, 0);
8487 Rm = Bits32(opcode, 5, 3);
8488 setflags = !InITBlock();
8489 shift_t = SRType_LSL;
8490 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008491 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008492 case eEncodingT2:
8493 Rd = Bits32(opcode, 11, 8);
8494 Rn = Bits32(opcode, 19, 16);
8495 Rm = Bits32(opcode, 3, 0);
8496 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008497 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8498 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008499 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008500 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008501 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8502 return false;
8503 break;
8504 case eEncodingA1:
8505 Rd = Bits32(opcode, 15, 12);
8506 Rn = Bits32(opcode, 19, 16);
8507 Rm = Bits32(opcode, 3, 0);
8508 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008509 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008510
Johnny Chen7c5234d2011-02-18 23:41:11 +00008511 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008512 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008513 break;
8514 default:
8515 return false;
8516 }
8517
8518 // Read the first operand.
8519 uint32_t val1 = ReadCoreReg(Rn, &success);
8520 if (!success)
8521 return false;
8522
8523 // Read the second operand.
8524 uint32_t val2 = ReadCoreReg(Rm, &success);
8525 if (!success)
8526 return false;
8527
Johnny Chena4438a72011-06-02 22:50:51 +00008528 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8529 if (!success)
8530 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00008531 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008532
8533 EmulateInstruction::Context context;
8534 context.type = EmulateInstruction::eContextImmediate;
8535 context.SetNoArgs ();
8536
8537 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8538 return false;
8539 }
8540 return true;
8541}
8542
Johnny Chened32e7c2011-02-22 23:42:58 +00008543// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8544// the destination register. It can optionally update the condition flags based on the result.
8545bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008546EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008547{
8548#if 0
8549 // ARM pseudo code...
8550 if ConditionPassed() then
8551 EncodingSpecificOperations();
8552 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8553 if d == 15 then // Can only occur for ARM encoding
8554 ALUWritePC(result); // setflags is always FALSE here
8555 else
8556 R[d] = result;
8557 if setflags then
8558 APSR.N = result<31>;
8559 APSR.Z = IsZeroBit(result);
8560 APSR.C = carry;
8561 APSR.V = overflow;
8562#endif
8563
8564 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008565
8566 uint32_t Rd; // the destination register
8567 uint32_t Rn; // the first operand
8568 bool setflags;
8569 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8570 switch (encoding) {
8571 case eEncodingT1:
8572 Rd = Bits32(opcode, 2, 0);
8573 Rn = Bits32(opcode, 5, 3);
8574 setflags = !InITBlock();
8575 imm32 = 0;
8576 break;
8577 case eEncodingT2:
8578 Rd = Bits32(opcode, 11, 8);
8579 Rn = Bits32(opcode, 19, 16);
8580 setflags = BitIsSet(opcode, 20);
8581 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8582 if (BadReg(Rd) || BadReg(Rn))
8583 return false;
8584 break;
8585 case eEncodingA1:
8586 Rd = Bits32(opcode, 15, 12);
8587 Rn = Bits32(opcode, 19, 16);
8588 setflags = BitIsSet(opcode, 20);
8589 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008590
Johnny Chened32e7c2011-02-22 23:42:58 +00008591 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008592 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008593 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008594 break;
8595 default:
8596 return false;
8597 }
8598 // Read the register value from the operand register Rn.
8599 uint32_t reg_val = ReadCoreReg(Rn, &success);
8600 if (!success)
8601 return false;
8602
8603 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8604
8605 EmulateInstruction::Context context;
8606 context.type = EmulateInstruction::eContextImmediate;
8607 context.SetNoArgs ();
8608
8609 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8610 return false;
8611
8612 return true;
8613}
8614
8615// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8616// result to the destination register. It can optionally update the condition flags based on the result.
8617bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008618EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008619{
8620#if 0
8621 // ARM pseudo code...
8622 if ConditionPassed() then
8623 EncodingSpecificOperations();
8624 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8625 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8626 if d == 15 then // Can only occur for ARM encoding
8627 ALUWritePC(result); // setflags is always FALSE here
8628 else
8629 R[d] = result;
8630 if setflags then
8631 APSR.N = result<31>;
8632 APSR.Z = IsZeroBit(result);
8633 APSR.C = carry;
8634 APSR.V = overflow;
8635#endif
8636
8637 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008638
8639 uint32_t Rd; // the destination register
8640 uint32_t Rn; // the first operand
8641 uint32_t Rm; // the second operand
8642 bool setflags;
8643 ARM_ShifterType shift_t;
8644 uint32_t shift_n; // the shift applied to the value read from Rm
8645 switch (encoding) {
8646 case eEncodingT1:
8647 Rd = Bits32(opcode, 11, 8);
8648 Rn = Bits32(opcode, 19, 16);
8649 Rm = Bits32(opcode, 3, 0);
8650 setflags = BitIsSet(opcode, 20);
8651 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8652 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8653 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8654 return false;
8655 break;
8656 case eEncodingA1:
8657 Rd = Bits32(opcode, 15, 12);
8658 Rn = Bits32(opcode, 19, 16);
8659 Rm = Bits32(opcode, 3, 0);
8660 setflags = BitIsSet(opcode, 20);
8661 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008662
Johnny Chened32e7c2011-02-22 23:42:58 +00008663 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chened32e7c2011-02-22 23:42:58 +00008664 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008665 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chened32e7c2011-02-22 23:42:58 +00008666 break;
8667 default:
8668 return false;
8669 }
8670 // Read the register value from register Rn.
8671 uint32_t val1 = ReadCoreReg(Rn, &success);
8672 if (!success)
8673 return false;
8674
8675 // Read the register value from register Rm.
8676 uint32_t val2 = ReadCoreReg(Rm, &success);
8677 if (!success)
8678 return false;
8679
Johnny Chena4438a72011-06-02 22:50:51 +00008680 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8681 if (!success)
8682 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008683 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8684
8685 EmulateInstruction::Context context;
8686 context.type = EmulateInstruction::eContextImmediate;
8687 context.SetNoArgs();
8688 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8689 return false;
8690
8691 return true;
8692}
8693
Johnny Chen90e607b2011-02-23 00:07:09 +00008694// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8695// an immediate value, and writes the result to the destination register. It can optionally update the condition
8696// flags based on the result.
8697bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008698EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008699{
8700#if 0
8701 // ARM pseudo code...
8702 if ConditionPassed() then
8703 EncodingSpecificOperations();
8704 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8705 if d == 15 then
8706 ALUWritePC(result); // setflags is always FALSE here
8707 else
8708 R[d] = result;
8709 if setflags then
8710 APSR.N = result<31>;
8711 APSR.Z = IsZeroBit(result);
8712 APSR.C = carry;
8713 APSR.V = overflow;
8714#endif
8715
8716 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008717
8718 uint32_t Rd; // the destination register
8719 uint32_t Rn; // the first operand
8720 bool setflags;
8721 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8722 switch (encoding) {
8723 case eEncodingA1:
8724 Rd = Bits32(opcode, 15, 12);
8725 Rn = Bits32(opcode, 19, 16);
8726 setflags = BitIsSet(opcode, 20);
8727 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008728
Johnny Chen90e607b2011-02-23 00:07:09 +00008729 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008730 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008731 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008732 break;
8733 default:
8734 return false;
8735 }
8736 // Read the register value from the operand register Rn.
8737 uint32_t reg_val = ReadCoreReg(Rn, &success);
8738 if (!success)
8739 return false;
8740
8741 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8742
8743 EmulateInstruction::Context context;
8744 context.type = EmulateInstruction::eContextImmediate;
8745 context.SetNoArgs ();
8746
8747 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8748 return false;
8749
8750 return true;
8751}
8752
8753// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8754// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8755// condition flags based on the result.
8756bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008757EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008758{
8759#if 0
8760 // ARM pseudo code...
8761 if ConditionPassed() then
8762 EncodingSpecificOperations();
8763 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8764 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8765 if d == 15 then
8766 ALUWritePC(result); // setflags is always FALSE here
8767 else
8768 R[d] = result;
8769 if setflags then
8770 APSR.N = result<31>;
8771 APSR.Z = IsZeroBit(result);
8772 APSR.C = carry;
8773 APSR.V = overflow;
8774#endif
8775
8776 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008777
8778 uint32_t Rd; // the destination register
8779 uint32_t Rn; // the first operand
8780 uint32_t Rm; // the second operand
8781 bool setflags;
8782 ARM_ShifterType shift_t;
8783 uint32_t shift_n; // the shift applied to the value read from Rm
8784 switch (encoding) {
8785 case eEncodingA1:
8786 Rd = Bits32(opcode, 15, 12);
8787 Rn = Bits32(opcode, 19, 16);
8788 Rm = Bits32(opcode, 3, 0);
8789 setflags = BitIsSet(opcode, 20);
8790 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008791
Johnny Chen90e607b2011-02-23 00:07:09 +00008792 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen90e607b2011-02-23 00:07:09 +00008793 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008794 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen90e607b2011-02-23 00:07:09 +00008795 break;
8796 default:
8797 return false;
8798 }
8799 // Read the register value from register Rn.
8800 uint32_t val1 = ReadCoreReg(Rn, &success);
8801 if (!success)
8802 return false;
8803
8804 // Read the register value from register Rm.
8805 uint32_t val2 = ReadCoreReg(Rm, &success);
8806 if (!success)
8807 return false;
8808
Johnny Chena4438a72011-06-02 22:50:51 +00008809 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8810 if (!success)
8811 return false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008812 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8813
8814 EmulateInstruction::Context context;
8815 context.type = EmulateInstruction::eContextImmediate;
8816 context.SetNoArgs();
8817 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8818 return false;
8819
8820 return true;
8821}
8822
Johnny Chen9b381772011-02-23 01:01:21 +00008823// Subtract with Carry (immediate) subtracts an immediate value and the value of
8824// NOT (Carry flag) from a register value, and writes the result to the destination register.
8825// It can optionally update the condition flags based on the result.
8826bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008827EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008828{
8829#if 0
8830 // ARM pseudo code...
8831 if ConditionPassed() then
8832 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008833 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008834 if d == 15 then // Can only occur for ARM encoding
8835 ALUWritePC(result); // setflags is always FALSE here
8836 else
8837 R[d] = result;
8838 if setflags then
8839 APSR.N = result<31>;
8840 APSR.Z = IsZeroBit(result);
8841 APSR.C = carry;
8842 APSR.V = overflow;
8843#endif
8844
8845 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008846
8847 uint32_t Rd; // the destination register
8848 uint32_t Rn; // the first operand
8849 bool setflags;
8850 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8851 switch (encoding) {
8852 case eEncodingT1:
8853 Rd = Bits32(opcode, 11, 8);
8854 Rn = Bits32(opcode, 19, 16);
8855 setflags = BitIsSet(opcode, 20);
8856 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8857 if (BadReg(Rd) || BadReg(Rn))
8858 return false;
8859 break;
8860 case eEncodingA1:
8861 Rd = Bits32(opcode, 15, 12);
8862 Rn = Bits32(opcode, 19, 16);
8863 setflags = BitIsSet(opcode, 20);
8864 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Caroline Tice1f954f52011-04-11 15:51:10 +00008865
Johnny Chen9b381772011-02-23 01:01:21 +00008866 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008867 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008868 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008869 break;
8870 default:
8871 return false;
8872 }
8873 // Read the register value from the operand register Rn.
8874 uint32_t reg_val = ReadCoreReg(Rn, &success);
8875 if (!success)
8876 return false;
8877
8878 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8879
8880 EmulateInstruction::Context context;
8881 context.type = EmulateInstruction::eContextImmediate;
8882 context.SetNoArgs ();
8883
8884 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8885 return false;
8886
8887 return true;
8888}
8889
8890// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8891// NOT (Carry flag) from a register value, and writes the result to the destination register.
8892// It can optionally update the condition flags based on the result.
8893bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008894EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008895{
8896#if 0
8897 // ARM pseudo code...
8898 if ConditionPassed() then
8899 EncodingSpecificOperations();
8900 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8901 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8902 if d == 15 then // Can only occur for ARM encoding
8903 ALUWritePC(result); // setflags is always FALSE here
8904 else
8905 R[d] = result;
8906 if setflags then
8907 APSR.N = result<31>;
8908 APSR.Z = IsZeroBit(result);
8909 APSR.C = carry;
8910 APSR.V = overflow;
8911#endif
8912
8913 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008914
8915 uint32_t Rd; // the destination register
8916 uint32_t Rn; // the first operand
8917 uint32_t Rm; // the second operand
8918 bool setflags;
8919 ARM_ShifterType shift_t;
8920 uint32_t shift_n; // the shift applied to the value read from Rm
8921 switch (encoding) {
8922 case eEncodingT1:
8923 Rd = Rn = Bits32(opcode, 2, 0);
8924 Rm = Bits32(opcode, 5, 3);
8925 setflags = !InITBlock();
8926 shift_t = SRType_LSL;
8927 shift_n = 0;
8928 break;
8929 case eEncodingT2:
8930 Rd = Bits32(opcode, 11, 8);
8931 Rn = Bits32(opcode, 19, 16);
8932 Rm = Bits32(opcode, 3, 0);
8933 setflags = BitIsSet(opcode, 20);
8934 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8935 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8936 return false;
8937 break;
8938 case eEncodingA1:
8939 Rd = Bits32(opcode, 15, 12);
8940 Rn = Bits32(opcode, 19, 16);
8941 Rm = Bits32(opcode, 3, 0);
8942 setflags = BitIsSet(opcode, 20);
8943 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Tice1f954f52011-04-11 15:51:10 +00008944
Johnny Chen9b381772011-02-23 01:01:21 +00008945 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen9b381772011-02-23 01:01:21 +00008946 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00008947 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen9b381772011-02-23 01:01:21 +00008948 break;
8949 default:
8950 return false;
8951 }
8952 // Read the register value from register Rn.
8953 uint32_t val1 = ReadCoreReg(Rn, &success);
8954 if (!success)
8955 return false;
8956
8957 // Read the register value from register Rm.
8958 uint32_t val2 = ReadCoreReg(Rm, &success);
8959 if (!success)
8960 return false;
8961
Johnny Chena4438a72011-06-02 22:50:51 +00008962 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
8963 if (!success)
8964 return false;
Johnny Chen9b381772011-02-23 01:01:21 +00008965 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8966
8967 EmulateInstruction::Context context;
8968 context.type = EmulateInstruction::eContextImmediate;
8969 context.SetNoArgs();
8970 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8971 return false;
8972
8973 return true;
8974}
8975
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008976// This instruction subtracts an immediate value from a register value, and writes the result
8977// to the destination register. It can optionally update the condition flags based on the result.
8978bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008979EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008980{
8981#if 0
8982 // ARM pseudo code...
8983 if ConditionPassed() then
8984 EncodingSpecificOperations();
8985 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8986 R[d] = result;
8987 if setflags then
8988 APSR.N = result<31>;
8989 APSR.Z = IsZeroBit(result);
8990 APSR.C = carry;
8991 APSR.V = overflow;
8992#endif
8993
8994 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008995
8996 uint32_t Rd; // the destination register
8997 uint32_t Rn; // the first operand
8998 bool setflags;
8999 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9000 switch (encoding) {
9001 case eEncodingT1:
9002 Rd = Bits32(opcode, 2, 0);
9003 Rn = Bits32(opcode, 5, 3);
9004 setflags = !InITBlock();
9005 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9006 break;
9007 case eEncodingT2:
9008 Rd = Rn = Bits32(opcode, 10, 8);
9009 setflags = !InITBlock();
9010 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9011 break;
9012 case eEncodingT3:
9013 Rd = Bits32(opcode, 11, 8);
9014 Rn = Bits32(opcode, 19, 16);
9015 setflags = BitIsSet(opcode, 20);
9016 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9017
9018 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9019 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00009020 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009021
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009022 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009023 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009024 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009025
9026 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9027 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9028 return false;
9029 break;
9030 case eEncodingT4:
9031 Rd = Bits32(opcode, 11, 8);
9032 Rn = Bits32(opcode, 19, 16);
9033 setflags = BitIsSet(opcode, 20);
9034 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9035
9036 // if Rn == '1111' then SEE ADR;
9037 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00009038 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009039
9040 // if Rn == '1101' then SEE SUB (SP minus immediate);
9041 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009042 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009043
9044 if (BadReg(Rd))
9045 return false;
9046 break;
9047 default:
9048 return false;
9049 }
9050 // Read the register value from the operand register Rn.
9051 uint32_t reg_val = ReadCoreReg(Rn, &success);
9052 if (!success)
9053 return false;
9054
9055 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9056
9057 EmulateInstruction::Context context;
9058 context.type = EmulateInstruction::eContextImmediate;
9059 context.SetNoArgs ();
9060
9061 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9062 return false;
9063
9064 return true;
9065}
9066
9067// This instruction subtracts an immediate value from a register value, and writes the result
9068// to the destination register. It can optionally update the condition flags based on the result.
9069bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009070EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009071{
9072#if 0
9073 // ARM pseudo code...
9074 if ConditionPassed() then
9075 EncodingSpecificOperations();
9076 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9077 if d == 15 then
9078 ALUWritePC(result); // setflags is always FALSE here
9079 else
9080 R[d] = result;
9081 if setflags then
9082 APSR.N = result<31>;
9083 APSR.Z = IsZeroBit(result);
9084 APSR.C = carry;
9085 APSR.V = overflow;
9086#endif
9087
9088 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009089
9090 uint32_t Rd; // the destination register
9091 uint32_t Rn; // the first operand
9092 bool setflags;
9093 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9094 switch (encoding) {
9095 case eEncodingA1:
9096 Rd = Bits32(opcode, 15, 12);
9097 Rn = Bits32(opcode, 19, 16);
9098 setflags = BitIsSet(opcode, 20);
9099 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9100
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009101 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009102 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00009103 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009104
Caroline Ticebb48f0b2011-03-28 16:10:45 +00009105 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009106 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00009107 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009108
9109 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009110 if (Rd == 15 && setflags)
Caroline Tice1f954f52011-04-11 15:51:10 +00009111 return EmulateSUBSPcLrEtc (opcode, encoding);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009112 break;
9113 default:
9114 return false;
9115 }
9116 // Read the register value from the operand register Rn.
9117 uint32_t reg_val = ReadCoreReg(Rn, &success);
9118 if (!success)
9119 return false;
9120
9121 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9122
9123 EmulateInstruction::Context context;
9124 context.type = EmulateInstruction::eContextImmediate;
9125 context.SetNoArgs ();
9126
9127 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9128 return false;
9129
9130 return true;
9131}
9132
Johnny Chen2115b412011-02-21 23:42:44 +00009133// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9134// immediate value. It updates the condition flags based on the result, and discards the result.
9135bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009136EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009137{
9138#if 0
9139 // ARM pseudo code...
9140 if ConditionPassed() then
9141 EncodingSpecificOperations();
9142 result = R[n] EOR imm32;
9143 APSR.N = result<31>;
9144 APSR.Z = IsZeroBit(result);
9145 APSR.C = carry;
9146 // APSR.V unchanged
9147#endif
9148
9149 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009150
Greg Clayton7bc39082011-03-24 23:53:38 +00009151 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009152 {
9153 uint32_t Rn;
9154 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9155 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9156 switch (encoding)
9157 {
9158 case eEncodingT1:
9159 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009160 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009161 if (BadReg(Rn))
9162 return false;
9163 break;
9164 case eEncodingA1:
9165 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00009166 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00009167 break;
9168 default:
9169 return false;
9170 }
9171
9172 // Read the first operand.
9173 uint32_t val1 = ReadCoreReg(Rn, &success);
9174 if (!success)
9175 return false;
9176
9177 uint32_t result = val1 ^ imm32;
9178
9179 EmulateInstruction::Context context;
9180 context.type = EmulateInstruction::eContextImmediate;
9181 context.SetNoArgs ();
9182
9183 if (!WriteFlags(context, result, carry))
9184 return false;
9185 }
9186 return true;
9187}
9188
9189// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9190// optionally-shifted register value. It updates the condition flags based on the result, and discards
9191// the result.
9192bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009193EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00009194{
9195#if 0
9196 // ARM pseudo code...
9197 if ConditionPassed() then
9198 EncodingSpecificOperations();
9199 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9200 result = R[n] EOR shifted;
9201 APSR.N = result<31>;
9202 APSR.Z = IsZeroBit(result);
9203 APSR.C = carry;
9204 // APSR.V unchanged
9205#endif
9206
9207 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009208
Greg Clayton7bc39082011-03-24 23:53:38 +00009209 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009210 {
9211 uint32_t Rn, Rm;
9212 ARM_ShifterType shift_t;
9213 uint32_t shift_n; // the shift applied to the value read from Rm
9214 uint32_t carry;
9215 switch (encoding)
9216 {
9217 case eEncodingT1:
9218 Rn = Bits32(opcode, 19, 16);
9219 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009220 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009221 if (BadReg(Rn) || BadReg(Rm))
9222 return false;
9223 break;
9224 case eEncodingA1:
9225 Rn = Bits32(opcode, 19, 16);
9226 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009227 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009228 break;
9229 default:
9230 return false;
9231 }
9232
9233 // Read the first operand.
9234 uint32_t val1 = ReadCoreReg(Rn, &success);
9235 if (!success)
9236 return false;
9237
9238 // Read the second operand.
9239 uint32_t val2 = ReadCoreReg(Rm, &success);
9240 if (!success)
9241 return false;
9242
Johnny Chena4438a72011-06-02 22:50:51 +00009243 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9244 if (!success)
9245 return false;
Johnny Chen2115b412011-02-21 23:42:44 +00009246 uint32_t result = val1 ^ shifted;
9247
9248 EmulateInstruction::Context context;
9249 context.type = EmulateInstruction::eContextImmediate;
9250 context.SetNoArgs ();
9251
9252 if (!WriteFlags(context, result, carry))
9253 return false;
9254 }
9255 return true;
9256}
9257
Johnny Chende3cce32011-02-21 21:24:49 +00009258// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9259// It updates the condition flags based on the result, and discards the result.
9260bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009261EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009262{
9263#if 0
9264 // ARM pseudo code...
9265 if ConditionPassed() then
9266 EncodingSpecificOperations();
9267 result = R[n] AND imm32;
9268 APSR.N = result<31>;
9269 APSR.Z = IsZeroBit(result);
9270 APSR.C = carry;
9271 // APSR.V unchanged
9272#endif
9273
9274 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009275
Greg Clayton7bc39082011-03-24 23:53:38 +00009276 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009277 {
9278 uint32_t Rn;
9279 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9280 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9281 switch (encoding)
9282 {
9283 case eEncodingT1:
9284 Rn = Bits32(opcode, 19, 16);
9285 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9286 if (BadReg(Rn))
9287 return false;
9288 break;
9289 case eEncodingA1:
9290 Rn = Bits32(opcode, 19, 16);
9291 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9292 break;
9293 default:
9294 return false;
9295 }
9296
9297 // Read the first operand.
9298 uint32_t val1 = ReadCoreReg(Rn, &success);
9299 if (!success)
9300 return false;
9301
9302 uint32_t result = val1 & imm32;
9303
9304 EmulateInstruction::Context context;
9305 context.type = EmulateInstruction::eContextImmediate;
9306 context.SetNoArgs ();
9307
9308 if (!WriteFlags(context, result, carry))
9309 return false;
9310 }
9311 return true;
9312}
9313
9314// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9315// It updates the condition flags based on the result, and discards the result.
9316bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009317EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009318{
9319#if 0
9320 // ARM pseudo code...
9321 if ConditionPassed() then
9322 EncodingSpecificOperations();
9323 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9324 result = R[n] AND shifted;
9325 APSR.N = result<31>;
9326 APSR.Z = IsZeroBit(result);
9327 APSR.C = carry;
9328 // APSR.V unchanged
9329#endif
9330
9331 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009332
Greg Clayton7bc39082011-03-24 23:53:38 +00009333 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009334 {
9335 uint32_t Rn, Rm;
9336 ARM_ShifterType shift_t;
9337 uint32_t shift_n; // the shift applied to the value read from Rm
9338 uint32_t carry;
9339 switch (encoding)
9340 {
9341 case eEncodingT1:
9342 Rn = Bits32(opcode, 2, 0);
9343 Rm = Bits32(opcode, 5, 3);
9344 shift_t = SRType_LSL;
9345 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009346 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009347 case eEncodingT2:
9348 Rn = Bits32(opcode, 19, 16);
9349 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009350 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009351 if (BadReg(Rn) || BadReg(Rm))
9352 return false;
9353 break;
9354 case eEncodingA1:
9355 Rn = Bits32(opcode, 19, 16);
9356 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009357 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009358 break;
9359 default:
9360 return false;
9361 }
9362
9363 // Read the first operand.
9364 uint32_t val1 = ReadCoreReg(Rn, &success);
9365 if (!success)
9366 return false;
9367
9368 // Read the second operand.
9369 uint32_t val2 = ReadCoreReg(Rm, &success);
9370 if (!success)
9371 return false;
9372
Johnny Chena4438a72011-06-02 22:50:51 +00009373 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9374 if (!success)
9375 return false;
Johnny Chende3cce32011-02-21 21:24:49 +00009376 uint32_t result = val1 & shifted;
9377
9378 EmulateInstruction::Context context;
9379 context.type = EmulateInstruction::eContextImmediate;
9380 context.SetNoArgs ();
9381
9382 if (!WriteFlags(context, result, carry))
9383 return false;
9384 }
9385 return true;
9386}
Caroline Ticed05b4902011-03-29 21:24:06 +00009387
9388// A8.6.216 SUB (SP minus register)
9389bool
9390EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9391{
9392#if 0
9393 if ConditionPassed() then
9394 EncodingSpecificOperations();
9395 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009396 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009397 if d == 15 then // Can only occur for ARM encoding
9398 ALUWritePC(result); // setflags is always FALSE here
9399 else
9400 R[d] = result;
9401 if setflags then
9402 APSR.N = result<31>;
9403 APSR.Z = IsZeroBit(result);
9404 APSR.C = carry;
9405 APSR.V = overflow;
9406#endif
9407
9408 bool success = false;
9409
9410 if (ConditionPassed(opcode))
9411 {
9412 uint32_t d;
9413 uint32_t m;
9414 bool setflags;
9415 ARM_ShifterType shift_t;
9416 uint32_t shift_n;
9417
9418 switch (encoding)
9419 {
9420 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009421 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009422 d = Bits32 (opcode, 11, 8);
9423 m = Bits32 (opcode, 3, 0);
9424 setflags = BitIsSet (opcode, 20);
9425
9426 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9427 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9428
9429 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9430 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9431 return false;
9432
9433 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9434 if ((d == 15) || BadReg (m))
9435 return false;
9436 break;
9437
9438 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009439 // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009440 d = Bits32 (opcode, 15, 12);
9441 m = Bits32 (opcode, 3, 0);
9442 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009443
Greg Clayton061b79d2011-05-09 20:18:18 +00009444 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009445 if (d == 15 && setflags)
9446 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Ticed05b4902011-03-29 21:24:06 +00009447
9448 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9449 shift_n = DecodeImmShiftARM (opcode, shift_t);
9450 break;
9451
9452 default:
9453 return false;
9454 }
9455
9456 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9457 uint32_t Rm = ReadCoreReg (m, &success);
9458 if (!success)
9459 return false;
9460
Johnny Chena4438a72011-06-02 22:50:51 +00009461 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9462 if (!success)
9463 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009464
Greg Clayton061b79d2011-05-09 20:18:18 +00009465 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
Caroline Ticed05b4902011-03-29 21:24:06 +00009466 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9467 if (!success)
9468 return false;
9469
9470 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9471
9472 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009473 context.type = eContextArithmetic;
9474 RegisterInfo sp_reg;
9475 GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
9476 RegisterInfo dwarf_reg;
9477 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +00009478 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9479
Caroline Ticeef440002011-03-30 05:40:56 +00009480 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009481 return false;
9482 }
9483 return true;
9484}
9485
9486
9487// A8.6.7 ADD (register-shifted register)
9488bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009489EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009490{
9491#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009492 if ConditionPassed() then
9493 EncodingSpecificOperations();
9494 shift_n = UInt(R[s]<7:0>);
9495 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009496 (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009497 R[d] = result;
9498 if setflags then
9499 APSR.N = result<31>;
9500 APSR.Z = IsZeroBit(result);
9501 APSR.C = carry;
9502 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009503#endif
9504
Caroline Ticec08ed382011-03-29 23:03:16 +00009505 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009506
9507 if (ConditionPassed(opcode))
9508 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009509 uint32_t d;
9510 uint32_t n;
9511 uint32_t m;
9512 uint32_t s;
9513 bool setflags;
9514 ARM_ShifterType shift_t;
9515
Caroline Ticed05b4902011-03-29 21:24:06 +00009516 switch (encoding)
9517 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009518 case eEncodingA1:
9519 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9520 d = Bits32 (opcode, 15, 12);
9521 n = Bits32 (opcode, 19, 16);
9522 m = Bits32 (opcode, 3, 0);
9523 s = Bits32 (opcode, 11, 8);
9524
Greg Clayton061b79d2011-05-09 20:18:18 +00009525 // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
Caroline Ticec08ed382011-03-29 23:03:16 +00009526 setflags = BitIsSet (opcode, 20);
9527 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9528
9529 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9530 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9531 return false;
9532 break;
9533
9534 default:
9535 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009536 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009537
9538 // shift_n = UInt(R[s]<7:0>);
9539 uint32_t Rs = ReadCoreReg (s, &success);
9540 if (!success)
9541 return false;
9542
9543 uint32_t shift_n = Bits32 (Rs, 7, 0);
9544
9545 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9546 uint32_t Rm = ReadCoreReg (m, &success);
9547 if (!success)
9548 return false;
9549
Johnny Chena4438a72011-06-02 22:50:51 +00009550 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9551 if (!success)
9552 return false;
9553
Greg Clayton061b79d2011-05-09 20:18:18 +00009554 // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
Caroline Ticec08ed382011-03-29 23:03:16 +00009555 uint32_t Rn = ReadCoreReg (n, &success);
9556 if (!success)
9557 return false;
9558
9559 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9560
9561 // R[d] = result;
9562 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009563 context.type = eContextArithmetic;
9564 RegisterInfo reg_n;
9565 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9566 RegisterInfo reg_m;
9567 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009568
9569 context.SetRegisterRegisterOperands (reg_n, reg_m);
9570
9571 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9572 return false;
9573
9574 // if setflags then
9575 // APSR.N = result<31>;
9576 // APSR.Z = IsZeroBit(result);
9577 // APSR.C = carry;
9578 // APSR.V = overflow;
9579 if (setflags)
9580 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009581 }
9582 return true;
9583}
9584
9585// A8.6.213 SUB (register)
9586bool
9587EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9588{
9589#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009590 if ConditionPassed() then
9591 EncodingSpecificOperations();
9592 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Greg Clayton061b79d2011-05-09 20:18:18 +00009593 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009594 if d == 15 then // Can only occur for ARM encoding
9595 ALUWritePC(result); // setflags is always FALSE here
9596 else
9597 R[d] = result;
9598 if setflags then
9599 APSR.N = result<31>;
9600 APSR.Z = IsZeroBit(result);
9601 APSR.C = carry;
9602 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009603#endif
9604
Caroline Tice4cccd532011-03-29 23:44:20 +00009605 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009606
9607 if (ConditionPassed(opcode))
9608 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009609 uint32_t d;
9610 uint32_t n;
9611 uint32_t m;
9612 bool setflags;
9613 ARM_ShifterType shift_t;
9614 uint32_t shift_n;
9615
Caroline Ticed05b4902011-03-29 21:24:06 +00009616 switch (encoding)
9617 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009618 case eEncodingT1:
9619 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9620 d = Bits32 (opcode, 2, 0);
9621 n = Bits32 (opcode, 5, 3);
9622 m = Bits32 (opcode, 8, 6);
9623 setflags = !InITBlock();
9624
9625 // (shift_t, shift_n) = (SRType_LSL, 0);
9626 shift_t = SRType_LSL;
9627 shift_n = 0;
9628
9629 break;
9630
9631 case eEncodingT2:
Greg Clayton061b79d2011-05-09 20:18:18 +00009632 // if Rd == Ô1111Õ && S == Ô1Õ then SEE CMP (register);
9633 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9634 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009635 d = Bits32 (opcode, 11, 8);
9636 n = Bits32 (opcode, 19, 16);
9637 m = Bits32 (opcode, 3, 0);
9638 setflags = BitIsSet (opcode, 20);
9639
9640 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9641 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9642
9643 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9644 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9645 return false;
9646
9647 break;
9648
9649 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009650 // if Rn == Ô1101Õ then SEE SUB (SP minus register);
9651 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009652 d = Bits32 (opcode, 15, 12);
9653 n = Bits32 (opcode, 19, 16);
9654 m = Bits32 (opcode, 3, 0);
9655 setflags = BitIsSet (opcode, 20);
Caroline Tice1f954f52011-04-11 15:51:10 +00009656
Greg Clayton061b79d2011-05-09 20:18:18 +00009657 // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
Caroline Tice1f954f52011-04-11 15:51:10 +00009658 if ((d == 15) && setflags)
9659 EmulateSUBSPcLrEtc (opcode, encoding);
Caroline Tice4cccd532011-03-29 23:44:20 +00009660
9661 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9662 shift_n = DecodeImmShiftARM (opcode, shift_t);
9663
9664 break;
9665
9666 default:
9667 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009668 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009669
9670 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9671 uint32_t Rm = ReadCoreReg (m, &success);
9672 if (!success)
9673 return false;
9674
Johnny Chena4438a72011-06-02 22:50:51 +00009675 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
9676 if (!success)
9677 return false;
Caroline Tice4cccd532011-03-29 23:44:20 +00009678
Greg Clayton061b79d2011-05-09 20:18:18 +00009679 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
Caroline Tice4cccd532011-03-29 23:44:20 +00009680 uint32_t Rn = ReadCoreReg (n, &success);
9681 if (!success)
9682 return false;
9683
9684 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9685
9686 // if d == 15 then // Can only occur for ARM encoding
9687 // ALUWritePC(result); // setflags is always FALSE here
9688 // else
9689 // R[d] = result;
9690 // if setflags then
9691 // APSR.N = result<31>;
9692 // APSR.Z = IsZeroBit(result);
9693 // APSR.C = carry;
9694 // APSR.V = overflow;
9695
9696 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +00009697 context.type = eContextArithmetic;
9698 RegisterInfo reg_n;
9699 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
9700 RegisterInfo reg_m;
9701 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009702 context.SetRegisterRegisterOperands (reg_n, reg_m);
9703
Caroline Ticeef440002011-03-30 05:40:56 +00009704 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009705 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009706 }
9707 return true;
9708}
Caroline Tice4cccd532011-03-29 23:44:20 +00009709
Caroline Ticed05b4902011-03-29 21:24:06 +00009710// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009711// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9712// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009713bool
9714EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9715{
9716#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009717 if ConditionPassed() then
9718 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9719 address = R[n] + imm32;
9720 if ExclusiveMonitorsPass(address,4) then
9721 MemA[address,4] = R[t];
9722 R[d] = 0;
9723 else
9724 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009725#endif
9726
Caroline Tice5168b6c2011-03-30 05:15:46 +00009727 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009728
9729 if (ConditionPassed(opcode))
9730 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009731 uint32_t d;
9732 uint32_t t;
9733 uint32_t n;
9734 uint32_t imm32;
9735 const uint32_t addr_byte_size = GetAddressByteSize();
9736
Caroline Ticed05b4902011-03-29 21:24:06 +00009737 switch (encoding)
9738 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009739 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009740 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009741 d = Bits32 (opcode, 11, 8);
9742 t = Bits32 (opcode, 15, 12);
9743 n = Bits32 (opcode, 19, 16);
9744 imm32 = Bits32 (opcode, 7, 0) << 2;
9745
9746 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9747 if (BadReg (d) || BadReg (t) || (n == 15))
9748 return false;
9749
9750 // if d == n || d == t then UNPREDICTABLE;
9751 if ((d == n) || (d == t))
9752 return false;
9753
9754 break;
9755
9756 case eEncodingA1:
9757 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9758 d = Bits32 (opcode, 15, 12);
9759 t = Bits32 (opcode, 3, 0);
9760 n = Bits32 (opcode, 19, 16);
9761 imm32 = 0;
9762
9763 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9764 if ((d == 15) || (t == 15) || (n == 15))
9765 return false;
9766
9767 // if d == n || d == t then UNPREDICTABLE;
9768 if ((d == n) || (d == t))
9769 return false;
9770
9771 break;
9772
9773 default:
9774 return false;
9775 }
9776
9777 // address = R[n] + imm32;
9778 uint32_t Rn = ReadCoreReg (n, &success);
9779 if (!success)
9780 return false;
9781
9782 addr_t address = Rn + imm32;
9783
Greg Claytonc07d4512011-04-26 23:48:45 +00009784 RegisterInfo base_reg;
9785 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9786 RegisterInfo data_reg;
9787 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice5168b6c2011-03-30 05:15:46 +00009788 EmulateInstruction::Context context;
9789 context.type = eContextRegisterStore;
9790 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9791
9792 // if ExclusiveMonitorsPass(address,4) then
9793 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9794 // always return true.
9795 if (true)
9796 {
9797 // MemA[address,4] = R[t];
9798 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9799 if (!success)
9800 return false;
9801
9802 if (!MemAWrite (context, address, Rt, addr_byte_size))
9803 return false;
9804
9805 // R[d] = 0;
9806 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9807 return false;
9808 }
9809 else
9810 {
9811 // R[d] = 1;
9812 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9813 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009814 }
9815 }
9816 return true;
9817}
9818
9819// A8.6.197 STRB (immediate, ARM)
9820bool
9821EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9822{
9823#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009824 if ConditionPassed() then
9825 EncodingSpecificOperations();
9826 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9827 address = if index then offset_addr else R[n];
9828 MemU[address,1] = R[t]<7:0>;
9829 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009830#endif
9831
Caroline Ticeef440002011-03-30 05:40:56 +00009832 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009833
9834 if (ConditionPassed(opcode))
9835 {
Caroline Ticeef440002011-03-30 05:40:56 +00009836 uint32_t t;
9837 uint32_t n;
9838 uint32_t imm32;
9839 bool index;
9840 bool add;
9841 bool wback;
9842
Caroline Ticed05b4902011-03-29 21:24:06 +00009843 switch (encoding)
9844 {
Caroline Ticeef440002011-03-30 05:40:56 +00009845 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009846 // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
Caroline Ticeef440002011-03-30 05:40:56 +00009847 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9848 t = Bits32 (opcode, 15, 12);
9849 n = Bits32 (opcode, 19, 16);
9850 imm32 = Bits32 (opcode, 11, 0);
9851
Greg Clayton061b79d2011-05-09 20:18:18 +00009852 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeef440002011-03-30 05:40:56 +00009853 index = BitIsSet (opcode, 24);
9854 add = BitIsSet (opcode, 23);
9855 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9856
9857 // if t == 15 then UNPREDICTABLE;
9858 if (t == 15)
9859 return false;
9860
9861 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9862 if (wback && ((n == 15) || (n == t)))
9863 return false;
9864
9865 break;
9866
9867 default:
9868 return false;
9869 }
9870
9871 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9872 uint32_t Rn = ReadCoreReg (n, &success);
9873 if (!success)
9874 return false;
9875
9876 addr_t offset_addr;
9877 if (add)
9878 offset_addr = Rn + imm32;
9879 else
9880 offset_addr = Rn - imm32;
9881
9882 // address = if index then offset_addr else R[n];
9883 addr_t address;
9884 if (index)
9885 address = offset_addr;
9886 else
9887 address = Rn;
9888
9889 // MemU[address,1] = R[t]<7:0>;
9890 uint32_t Rt = ReadCoreReg (t, &success);
9891 if (!success)
9892 return false;
9893
Greg Claytonc07d4512011-04-26 23:48:45 +00009894 RegisterInfo base_reg;
9895 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9896 RegisterInfo data_reg;
9897 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticeef440002011-03-30 05:40:56 +00009898 EmulateInstruction::Context context;
9899 context.type = eContextRegisterStore;
9900 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9901
9902 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9903 return false;
9904
9905 // if wback then R[n] = offset_addr;
9906 if (wback)
9907 {
Caroline Tice523c5542011-04-13 00:42:12 +00009908 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
Caroline Ticeef440002011-03-30 05:40:56 +00009909 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009910 }
9911 }
9912 return true;
9913}
9914
9915// A8.6.194 STR (immediate, ARM)
9916bool
9917EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9918{
9919#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009920 if ConditionPassed() then
9921 EncodingSpecificOperations();
9922 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9923 address = if index then offset_addr else R[n];
9924 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9925 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009926#endif
9927
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009928 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009929
9930 if (ConditionPassed(opcode))
9931 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009932 uint32_t t;
9933 uint32_t n;
9934 uint32_t imm32;
9935 bool index;
9936 bool add;
9937 bool wback;
9938
9939 const uint32_t addr_byte_size = GetAddressByteSize();
9940
Caroline Ticed05b4902011-03-29 21:24:06 +00009941 switch (encoding)
9942 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009943 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +00009944 // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
9945 // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009946 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9947 t = Bits32 (opcode, 15, 12);
9948 n = Bits32 (opcode, 19, 16);
9949 imm32 = Bits32 (opcode, 11, 0);
9950
Greg Clayton061b79d2011-05-09 20:18:18 +00009951 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009952 index = BitIsSet (opcode, 24);
9953 add = BitIsSet (opcode, 23);
9954 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9955
9956 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9957 if (wback && ((n == 15) || (n == t)))
9958 return false;
9959
9960 break;
9961
9962 default:
9963 return false;
9964 }
9965
9966 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9967 uint32_t Rn = ReadCoreReg (n, &success);
9968 if (!success)
9969 return false;
9970
9971 addr_t offset_addr;
9972 if (add)
9973 offset_addr = Rn + imm32;
9974 else
9975 offset_addr = Rn - imm32;
9976
9977 // address = if index then offset_addr else R[n];
9978 addr_t address;
9979 if (index)
9980 address = offset_addr;
9981 else
9982 address = Rn;
9983
Greg Claytonc07d4512011-04-26 23:48:45 +00009984 RegisterInfo base_reg;
9985 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
9986 RegisterInfo data_reg;
9987 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009988 EmulateInstruction::Context context;
9989 context.type = eContextRegisterStore;
9990 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9991
9992 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9993 uint32_t Rt = ReadCoreReg (t, &success);
9994 if (!success)
9995 return false;
9996
9997 if (t == 15)
9998 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009999 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +000010000 if (!success)
10001 return false;
10002
10003 if (!MemUWrite (context, address, pc_value, addr_byte_size))
10004 return false;
10005 }
10006 else
10007 {
10008 if (!MemUWrite (context, address, Rt, addr_byte_size))
10009 return false;
10010 }
10011
10012 // if wback then R[n] = offset_addr;
10013 if (wback)
10014 {
10015 context.type = eContextAdjustBaseRegister;
10016 context.SetImmediate (offset_addr);
10017
10018 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10019 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010020 }
10021 }
10022 return true;
10023}
10024
Caroline Ticed05b4902011-03-29 21:24:06 +000010025// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +000010026// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
10027// 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 +000010028bool
10029EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
10030{
10031#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +000010032 if ConditionPassed() then
10033 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10034 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10035 address = if index then offset_addr else R[n];
10036 R[t] = MemA[address,4];
10037 R[t2] = MemA[address+4,4];
10038 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010039#endif
10040
Caroline Tice1697dd72011-03-30 17:11:45 +000010041 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010042
10043 if (ConditionPassed(opcode))
10044 {
Caroline Tice1697dd72011-03-30 17:11:45 +000010045 uint32_t t;
10046 uint32_t t2;
10047 uint32_t n;
10048 uint32_t imm32;
10049 bool index;
10050 bool add;
10051 bool wback;
10052
Caroline Ticed05b4902011-03-29 21:24:06 +000010053 switch (encoding)
10054 {
Caroline Tice1697dd72011-03-30 17:11:45 +000010055 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010056 //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10057 //if Rn == Ô1111Õ then SEE LDRD (literal);
10058 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice1697dd72011-03-30 17:11:45 +000010059 t = Bits32 (opcode, 15, 12);
10060 t2 = Bits32 (opcode, 11, 8);
10061 n = Bits32 (opcode, 19, 16);
10062 imm32 = Bits32 (opcode, 7, 0) << 2;
10063
Greg Clayton061b79d2011-05-09 20:18:18 +000010064 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +000010065 index = BitIsSet (opcode, 24);
10066 add = BitIsSet (opcode, 23);
10067 wback = BitIsSet (opcode, 21);
10068
10069 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10070 if (wback && ((n == t) || (n == t2)))
10071 return false;
10072
10073 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10074 if (BadReg (t) || BadReg (t2) || (t == t2))
10075 return false;
10076
10077 break;
10078
10079 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010080 //if Rn == Ô1111Õ then SEE LDRD (literal);
10081 //if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010082 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10083 t = Bits32 (opcode, 15, 12);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010084 if (BitIsSet (t, 0))
10085 return false;
Caroline Tice1697dd72011-03-30 17:11:45 +000010086 t2 = t + 1;
10087 n = Bits32 (opcode, 19, 16);
10088 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10089
Greg Clayton061b79d2011-05-09 20:18:18 +000010090 //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice1697dd72011-03-30 17:11:45 +000010091 index = BitIsSet (opcode, 24);
10092 add = BitIsSet (opcode, 23);
10093 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10094
Greg Clayton061b79d2011-05-09 20:18:18 +000010095 //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice1697dd72011-03-30 17:11:45 +000010096 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10097 return false;
10098
10099 //if wback && (n == t || n == t2) then UNPREDICTABLE;
10100 if (wback && ((n == t) || (n == t2)))
10101 return false;
10102
10103 //if t2 == 15 then UNPREDICTABLE;
10104 if (t2 == 15)
10105 return false;
10106
10107 break;
10108
10109 default:
10110 return false;
10111 }
10112
10113 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10114 uint32_t Rn = ReadCoreReg (n, &success);
10115 if (!success)
10116 return false;
10117
10118 addr_t offset_addr;
10119 if (add)
10120 offset_addr = Rn + imm32;
10121 else
10122 offset_addr = Rn - imm32;
10123
10124 //address = if index then offset_addr else R[n];
10125 addr_t address;
10126 if (index)
10127 address = offset_addr;
10128 else
10129 address = Rn;
10130
10131 //R[t] = MemA[address,4];
Greg Claytonc07d4512011-04-26 23:48:45 +000010132 RegisterInfo base_reg;
10133 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1697dd72011-03-30 17:11:45 +000010134
10135 EmulateInstruction::Context context;
10136 context.type = eContextRegisterLoad;
10137 context.SetRegisterPlusOffset (base_reg, address - Rn);
10138
10139 const uint32_t addr_byte_size = GetAddressByteSize();
10140 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10141 if (!success)
10142 return false;
10143
10144 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10145 return false;
10146
10147 //R[t2] = MemA[address+4,4];
10148
10149 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10150 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10151 if (!success)
10152 return false;
10153
10154 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10155 return false;
10156
10157 //if wback then R[n] = offset_addr;
10158 if (wback)
10159 {
10160 context.type = eContextAdjustBaseRegister;
10161 context.SetAddress (offset_addr);
10162
10163 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10164 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010165 }
10166 }
10167 return true;
10168}
10169
Caroline Ticed05b4902011-03-29 21:24:06 +000010170// A8.6.68 LDRD (register)
Caroline Ticeeab301f2011-03-30 17:54:52 +000010171// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two
10172// 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 +000010173bool
10174EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10175{
10176#if 0
Caroline Ticeeab301f2011-03-30 17:54:52 +000010177 if ConditionPassed() then
10178 EncodingSpecificOperations();
10179 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10180 address = if index then offset_addr else R[n];
10181 R[t] = MemA[address,4];
10182 R[t2] = MemA[address+4,4];
10183 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010184#endif
10185
Caroline Ticeeab301f2011-03-30 17:54:52 +000010186 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010187
10188 if (ConditionPassed(opcode))
10189 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010190 uint32_t t;
10191 uint32_t t2;
10192 uint32_t n;
10193 uint32_t m;
10194 bool index;
10195 bool add;
10196 bool wback;
10197
Caroline Ticed05b4902011-03-29 21:24:06 +000010198 switch (encoding)
10199 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010200 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010201 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010202 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10203 t = Bits32 (opcode, 15, 12);
10204 if (BitIsSet (t, 0))
10205 return false;
10206 t2 = t + 1;
10207 n = Bits32 (opcode, 19, 16);
10208 m = Bits32 (opcode, 3, 0);
10209
Greg Clayton061b79d2011-05-09 20:18:18 +000010210 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Ticeeab301f2011-03-30 17:54:52 +000010211 index = BitIsSet (opcode, 24);
10212 add = BitIsSet (opcode, 23);
10213 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10214
Greg Clayton061b79d2011-05-09 20:18:18 +000010215 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Ticeeab301f2011-03-30 17:54:52 +000010216 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10217 return false;
10218
10219 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10220 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10221 return false;
10222
10223 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10224 if (wback && ((n == 15) || (n == t) || (n == t2)))
10225 return false;
10226
10227 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10228 if ((ArchVersion() < 6) && wback && (m == n))
10229 return false;
10230 break;
10231
10232 default:
10233 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010234 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010235
Caroline Ticeeab301f2011-03-30 17:54:52 +000010236 uint32_t Rn = ReadCoreReg (n, &success);
10237 if (!success)
10238 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010239 RegisterInfo base_reg;
10240 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010241
Caroline Ticeeab301f2011-03-30 17:54:52 +000010242 uint32_t Rm = ReadCoreReg (m, &success);
10243 if (!success)
10244 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010245 RegisterInfo offset_reg;
10246 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
Caroline Ticed05b4902011-03-29 21:24:06 +000010247
Caroline Ticeeab301f2011-03-30 17:54:52 +000010248 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10249 addr_t offset_addr;
10250 if (add)
10251 offset_addr = Rn + Rm;
10252 else
10253 offset_addr = Rn - Rm;
10254
10255 // address = if index then offset_addr else R[n];
10256 addr_t address;
10257 if (index)
10258 address = offset_addr;
10259 else
10260 address = Rn;
10261
10262 EmulateInstruction::Context context;
10263 context.type = eContextRegisterLoad;
10264 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
10265
10266 // R[t] = MemA[address,4];
10267 const uint32_t addr_byte_size = GetAddressByteSize();
10268 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10269 if (!success)
10270 return false;
10271
10272 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10273 return false;
10274
10275 // R[t2] = MemA[address+4,4];
10276
10277 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10278 if (!success)
10279 return false;
10280
10281 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10282 return false;
10283
10284 // if wback then R[n] = offset_addr;
10285 if (wback)
Caroline Ticed05b4902011-03-29 21:24:06 +000010286 {
Caroline Ticeeab301f2011-03-30 17:54:52 +000010287 context.type = eContextAdjustBaseRegister;
10288 context.SetAddress (offset_addr);
Caroline Ticed05b4902011-03-29 21:24:06 +000010289
Caroline Ticeeab301f2011-03-30 17:54:52 +000010290 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10291 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010292 }
10293 }
10294 return true;
10295}
Caroline Ticed05b4902011-03-29 21:24:06 +000010296
10297// A8.6.200 STRD (immediate)
Caroline Tice74467fe2011-03-30 19:02:56 +000010298// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and
10299// 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 +000010300bool
10301EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10302{
10303#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010304 if ConditionPassed() then
10305 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10306 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10307 address = if index then offset_addr else R[n];
10308 MemA[address,4] = R[t];
10309 MemA[address+4,4] = R[t2];
10310 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010311#endif
10312
Caroline Tice74467fe2011-03-30 19:02:56 +000010313 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010314
Caroline Tice74467fe2011-03-30 19:02:56 +000010315 if (ConditionPassed(opcode))
10316 {
10317 uint32_t t;
10318 uint32_t t2;
10319 uint32_t n;
10320 uint32_t imm32;
10321 bool index;
10322 bool add;
10323 bool wback;
10324
10325 switch (encoding)
10326 {
10327 case eEncodingT1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010328 // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10329 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice74467fe2011-03-30 19:02:56 +000010330 t = Bits32 (opcode, 15, 12);
10331 t2 = Bits32 (opcode, 11, 8);
10332 n = Bits32 (opcode, 19, 16);
10333 imm32 = Bits32 (opcode, 7, 0) << 2;
10334
Greg Clayton061b79d2011-05-09 20:18:18 +000010335 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010336 index = BitIsSet (opcode, 24);
10337 add = BitIsSet (opcode, 23);
10338 wback = BitIsSet (opcode, 21);
10339
10340 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10341 if (wback && ((n == t) || (n == t2)))
10342 return false;
10343
10344 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10345 if ((n == 15) || BadReg (t) || BadReg (t2))
10346 return false;
10347
10348 break;
10349
10350 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010351 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010352 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
10353 t = Bits32 (opcode, 15, 12);
10354 if (BitIsSet (t, 0))
10355 return false;
10356
10357 t2 = t + 1;
10358 n = Bits32 (opcode, 19, 16);
10359 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
10360
Greg Clayton061b79d2011-05-09 20:18:18 +000010361 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010362 index = BitIsSet (opcode, 24);
10363 add = BitIsSet (opcode, 23);
10364 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10365
Greg Clayton061b79d2011-05-09 20:18:18 +000010366 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010367 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10368 return false;
10369
10370 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10371 if (wback && ((n == 15) || (n == t) || (n == t2)))
10372 return false;
10373
10374 // if t2 == 15 then UNPREDICTABLE;
10375 if (t2 == 15)
10376 return false;
10377
10378 break;
10379
10380 default:
10381 return false;
10382 }
10383
Greg Claytonc07d4512011-04-26 23:48:45 +000010384 RegisterInfo base_reg;
10385 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010386
10387 uint32_t Rn = ReadCoreReg (n, &success);
10388 if (!success)
10389 return false;
10390
10391 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10392 addr_t offset_addr;
10393 if (add)
10394 offset_addr = Rn + imm32;
10395 else
10396 offset_addr = Rn - imm32;
10397
10398 //address = if index then offset_addr else R[n];
10399 addr_t address;
10400 if (index)
10401 address = offset_addr;
10402 else
10403 address = Rn;
10404
10405 //MemA[address,4] = R[t];
Greg Claytonc07d4512011-04-26 23:48:45 +000010406 RegisterInfo data_reg;
10407 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010408
10409 uint32_t data = ReadCoreReg (t, &success);
10410 if (!success)
10411 return false;
10412
10413 EmulateInstruction::Context context;
10414 context.type = eContextRegisterStore;
10415 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10416
10417 const uint32_t addr_byte_size = GetAddressByteSize();
10418
10419 if (!MemAWrite (context, address, data, addr_byte_size))
10420 return false;
10421
10422 //MemA[address+4,4] = R[t2];
Greg Claytonc07d4512011-04-26 23:48:45 +000010423 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010424 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10425
10426 data = ReadCoreReg (t2, &success);
10427 if (!success)
10428 return false;
10429
10430 if (!MemAWrite (context, address + 4, data, addr_byte_size))
10431 return false;
10432
10433 //if wback then R[n] = offset_addr;
10434 if (wback)
10435 {
10436 context.type = eContextAdjustBaseRegister;
10437 context.SetAddress (offset_addr);
10438
10439 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10440 return false;
10441 }
10442 }
Caroline Ticed05b4902011-03-29 21:24:06 +000010443 return true;
10444}
10445
10446
10447// A8.6.201 STRD (register)
10448bool
10449EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10450{
10451#if 0
Caroline Tice74467fe2011-03-30 19:02:56 +000010452 if ConditionPassed() then
10453 EncodingSpecificOperations();
10454 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10455 address = if index then offset_addr else R[n];
10456 MemA[address,4] = R[t];
10457 MemA[address+4,4] = R[t2];
10458 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +000010459#endif
10460
Caroline Tice74467fe2011-03-30 19:02:56 +000010461 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010462
Caroline Tice74467fe2011-03-30 19:02:56 +000010463 if (ConditionPassed(opcode))
10464 {
10465 uint32_t t;
10466 uint32_t t2;
10467 uint32_t n;
10468 uint32_t m;
10469 bool index;
10470 bool add;
10471 bool wback;
10472
10473 switch (encoding)
10474 {
10475 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010476 // if Rt<0> == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010477 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10478 t = Bits32 (opcode, 15, 12);
10479 if (BitIsSet (t, 0))
10480 return false;
10481
10482 t2 = t+1;
10483 n = Bits32 (opcode, 19, 16);
10484 m = Bits32 (opcode, 3, 0);
10485
Greg Clayton061b79d2011-05-09 20:18:18 +000010486 // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
Caroline Tice74467fe2011-03-30 19:02:56 +000010487 index = BitIsSet (opcode, 24);
10488 add = BitIsSet (opcode, 23);
10489 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
10490
Greg Clayton061b79d2011-05-09 20:18:18 +000010491 // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
Caroline Tice74467fe2011-03-30 19:02:56 +000010492 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
10493 return false;
10494
10495 // if t2 == 15 || m == 15 then UNPREDICTABLE;
10496 if ((t2 == 15) || (m == 15))
10497 return false;
10498
10499 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10500 if (wback && ((n == 15) || (n == t) || (n == t2)))
10501 return false;
10502
10503 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
Caroline Tice4f605582011-03-31 00:02:51 +000010504 if ((ArchVersion() < 6) && wback && (m == n))
Caroline Tice74467fe2011-03-30 19:02:56 +000010505 return false;
10506
10507 break;
10508
10509 default:
10510 return false;
10511 }
10512
Greg Claytonc07d4512011-04-26 23:48:45 +000010513 RegisterInfo base_reg;
10514 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
10515 RegisterInfo offset_reg;
10516 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
10517 RegisterInfo data_reg;
Caroline Tice74467fe2011-03-30 19:02:56 +000010518
10519 uint32_t Rn = ReadCoreReg (n, &success);
10520 if (!success)
10521 return false;
10522
10523 uint32_t Rm = ReadCoreReg (m, &success);
10524 if (!success)
10525 return false;
10526
10527 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10528 addr_t offset_addr;
10529 if (add)
10530 offset_addr = Rn + Rm;
10531 else
10532 offset_addr = Rn - Rm;
10533
10534 // address = if index then offset_addr else R[n];
10535 addr_t address;
10536 if (index)
10537 address = offset_addr;
10538 else
10539 address = Rn;
10540 // MemA[address,4] = R[t];
10541 uint32_t Rt = ReadCoreReg (t, &success);
10542 if (!success)
10543 return false;
10544
10545 EmulateInstruction::Context context;
10546 context.type = eContextRegisterStore;
Greg Claytonc07d4512011-04-26 23:48:45 +000010547 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010548 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10549
10550 const uint32_t addr_byte_size = GetAddressByteSize();
10551
10552 if (!MemAWrite (context, address, Rt, addr_byte_size))
10553 return false;
10554
10555 // MemA[address+4,4] = R[t2];
10556 uint32_t Rt2 = ReadCoreReg (t2, &success);
10557 if (!success)
10558 return false;
10559
Greg Claytonc07d4512011-04-26 23:48:45 +000010560 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
Caroline Tice74467fe2011-03-30 19:02:56 +000010561
10562 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
10563
10564 if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
10565 return false;
10566
10567 // if wback then R[n] = offset_addr;
10568 if (wback)
10569 {
10570 context.type = eContextAdjustBaseRegister;
10571 context.SetAddress (offset_addr);
10572
10573 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10574 return false;
10575
10576 }
10577 }
Greg Clayton24bc5d92011-03-30 18:16:51 +000010578 return true;
Caroline Ticed05b4902011-03-29 21:24:06 +000010579}
10580
Caroline Tice4f605582011-03-31 00:02:51 +000010581// A8.6.319 VLDM
10582// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from
10583// an ARM core register.
10584bool
10585EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
10586{
10587#if 0
10588 if ConditionPassed() then
10589 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10590 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010591 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010592 for r = 0 to regs-1
10593 if single_regs then
10594 S[d+r] = MemA[address,4]; address = address+4;
10595 else
10596 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10597 // Combine the word-aligned words in the correct order for current endianness.
10598 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10599#endif
10600
10601 bool success = false;
10602
10603 if (ConditionPassed(opcode))
10604 {
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010605 bool single_regs;
10606 bool add;
10607 bool wback;
10608 uint32_t d;
10609 uint32_t n;
10610 uint32_t imm32;
10611 uint32_t regs;
10612
Caroline Tice4f605582011-03-31 00:02:51 +000010613 switch (encoding)
10614 {
10615 case eEncodingT1:
10616 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010617 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10618 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10619 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10620 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010621 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10622 return false;
10623
10624 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010625 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Tice4f605582011-03-31 00:02:51 +000010626 single_regs = false;
10627 add = BitIsSet (opcode, 23);
10628 wback = BitIsSet (opcode, 21);
10629
Greg Clayton061b79d2011-05-09 20:18:18 +000010630 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice4f605582011-03-31 00:02:51 +000010631 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10632 n = Bits32 (opcode, 19, 16);
10633 imm32 = Bits32 (opcode, 7, 0) << 2;
10634
Greg Clayton061b79d2011-05-09 20:18:18 +000010635 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
Caroline Tice4f605582011-03-31 00:02:51 +000010636 regs = Bits32 (opcode, 7, 0) / 2;
10637
10638 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10639 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
10640 return false;
10641
10642 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10643 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10644 return false;
10645
10646 break;
10647
10648 case eEncodingT2:
10649 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010650 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10651 // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
10652 // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
10653 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Tice4f605582011-03-31 00:02:51 +000010654 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10655 return false;
10656
10657 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010658 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Tice4f605582011-03-31 00:02:51 +000010659 single_regs = true;
10660 add = BitIsSet (opcode, 23);
10661 wback = BitIsSet (opcode, 21);
10662 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10663 n = Bits32 (opcode, 19, 16);
10664
Greg Clayton061b79d2011-05-09 20:18:18 +000010665 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Tice4f605582011-03-31 00:02:51 +000010666 imm32 = Bits32 (opcode, 7, 0) << 2;
10667 regs = Bits32 (opcode, 7, 0);
10668
10669 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10670 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10671 return false;
10672
10673 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10674 if ((regs == 0) || ((d + regs) > 32))
10675 return false;
10676 break;
10677
10678 default:
10679 return false;
10680 }
10681
Greg Claytonc07d4512011-04-26 23:48:45 +000010682 RegisterInfo base_reg;
10683 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice4f605582011-03-31 00:02:51 +000010684
10685 uint32_t Rn = ReadCoreReg (n, &success);
10686 if (!success)
10687 return false;
10688
10689 // address = if add then R[n] else R[n]-imm32;
10690 addr_t address;
10691 if (add)
10692 address = Rn;
10693 else
10694 address = Rn - imm32;
10695
Greg Claytonc07d4512011-04-26 23:48:45 +000010696 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Tice4f605582011-03-31 00:02:51 +000010697 EmulateInstruction::Context context;
10698
10699 if (wback)
10700 {
10701 uint32_t value;
10702 if (add)
10703 value = Rn + imm32;
10704 else
10705 value = Rn - imm32;
10706
10707 context.type = eContextAdjustBaseRegister;
10708 context.SetImmediateSigned (value - Rn);
10709 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10710 return false;
10711
10712 }
10713
10714 const uint32_t addr_byte_size = GetAddressByteSize();
10715 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10716
10717 context.type = eContextRegisterLoad;
10718
10719 // for r = 0 to regs-1
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010720 for (uint32_t r = 0; r < regs; ++r)
Caroline Tice4f605582011-03-31 00:02:51 +000010721 {
10722 if (single_regs)
10723 {
10724 // S[d+r] = MemA[address,4]; address = address+4;
10725 context.SetRegisterPlusOffset (base_reg, address - Rn);
10726
10727 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10728 if (!success)
10729 return false;
10730
10731 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10732 return false;
10733
10734 address = address + 4;
10735 }
10736 else
10737 {
10738 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
10739 context.SetRegisterPlusOffset (base_reg, address - Rn);
10740 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
10741 if (!success)
10742 return false;
10743
10744 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10745 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
10746 if (!success)
10747 return false;
10748
10749 address = address + 8;
10750 // // Combine the word-aligned words in the correct order for current endianness.
10751 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
10752 uint64_t data;
Greg Clayton888a7332011-04-26 04:39:08 +000010753 if (GetByteOrder() == eByteOrderBig)
Caroline Tice4f605582011-03-31 00:02:51 +000010754 {
10755 data = word1;
10756 data = (data << 32) | word2;
10757 }
10758 else
10759 {
10760 data = word2;
10761 data = (data << 32) | word1;
10762 }
10763
10764 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
10765 return false;
10766 }
10767 }
10768 }
10769 return true;
10770}
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010771
10772// A8.6.399 VSTM
Caroline Tice917ad352011-03-31 05:05:30 +000010773// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
10774// ARM core register.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010775bool
10776EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
10777{
10778#if 0
10779 if ConditionPassed() then
10780 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10781 address = if add then R[n] else R[n]-imm32;
Greg Claytonc07d4512011-04-26 23:48:45 +000010782 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010783 for r = 0 to regs-1
10784 if single_regs then
10785 MemA[address,4] = S[d+r]; address = address+4;
10786 else
10787 // Store as two word-aligned words in the correct order for current endianness.
10788 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10789 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10790 address = address+8;
10791#endif
10792
10793 bool success = false;
10794
10795 if (ConditionPassed (opcode))
10796 {
10797 bool single_regs;
10798 bool add;
10799 bool wback;
10800 uint32_t d;
10801 uint32_t n;
10802 uint32_t imm32;
10803 uint32_t regs;
10804
10805 switch (encoding)
10806 {
10807 case eEncodingT1:
10808 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000010809 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10810 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10811 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10812 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010813 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10814 return false;
10815
10816 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010817 // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010818 single_regs = false;
10819 add = BitIsSet (opcode, 23);
10820 wback = BitIsSet (opcode, 21);
10821
Greg Clayton061b79d2011-05-09 20:18:18 +000010822 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010823 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
10824 n = Bits32 (opcode, 19, 16);
10825 imm32 = Bits32 (opcode, 7, 0) << 2;
10826
Greg Clayton061b79d2011-05-09 20:18:18 +000010827 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010828 regs = Bits32 (opcode, 7, 0) / 2;
10829
10830 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10831 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
10832 return false;
10833
10834 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
10835 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
10836 return false;
10837
10838 break;
10839
10840 case eEncodingT2:
10841 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000010842 // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
10843 // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
10844 // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
10845 // if P == U && W == Ô1Õ then UNDEFINED;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010846 if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
10847 return false;
10848
10849 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
Greg Clayton061b79d2011-05-09 20:18:18 +000010850 // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010851 single_regs = true;
10852 add = BitIsSet (opcode, 23);
10853 wback = BitIsSet (opcode, 21);
10854 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
10855 n = Bits32 (opcode, 19, 16);
10856
Greg Clayton061b79d2011-05-09 20:18:18 +000010857 // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010858 imm32 = Bits32 (opcode, 7, 0) << 2;
10859 regs = Bits32 (opcode, 7, 0);
10860
10861 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
10862 if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
10863 return false;
10864
10865 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
10866 if ((regs == 0) || ((d + regs) > 32))
10867 return false;
10868
10869 break;
10870
10871 default:
10872 return false;
10873 }
10874
Greg Claytonc07d4512011-04-26 23:48:45 +000010875 RegisterInfo base_reg;
10876 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010877
10878 uint32_t Rn = ReadCoreReg (n, &success);
10879 if (!success)
10880 return false;
10881
10882 // address = if add then R[n] else R[n]-imm32;
10883 addr_t address;
10884 if (add)
10885 address = Rn;
10886 else
10887 address = Rn - imm32;
10888
10889 EmulateInstruction::Context context;
Greg Claytonc07d4512011-04-26 23:48:45 +000010890 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010891 if (wback)
10892 {
10893 uint32_t value;
10894 if (add)
10895 value = Rn + imm32;
10896 else
10897 value = Rn - imm32;
10898
10899 context.type = eContextAdjustBaseRegister;
10900 context.SetRegisterPlusOffset (base_reg, value - Rn);
10901
10902 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
10903 return false;
10904 }
10905
10906 const uint32_t addr_byte_size = GetAddressByteSize();
10907 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
10908
10909 context.type = eContextRegisterStore;
10910 // for r = 0 to regs-1
10911 for (int r = 0; r < regs; ++r)
10912 {
Greg Claytonc07d4512011-04-26 23:48:45 +000010913
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010914 if (single_regs)
10915 {
10916 // MemA[address,4] = S[d+r]; address = address+4;
10917 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10918 if (!success)
10919 return false;
Greg Claytonc07d4512011-04-26 23:48:45 +000010920
10921 RegisterInfo data_reg;
10922 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010923 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10924 if (!MemAWrite (context, address, data, addr_byte_size))
10925 return false;
10926
10927 address = address + 4;
10928 }
10929 else
10930 {
10931 // // Store as two word-aligned words in the correct order for current endianness.
10932 // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
10933 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
10934 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
10935 if (!success)
10936 return false;
10937
Greg Claytonc07d4512011-04-26 23:48:45 +000010938 RegisterInfo data_reg;
10939 GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010940
Greg Clayton888a7332011-04-26 04:39:08 +000010941 if (GetByteOrder() == eByteOrderBig)
Caroline Ticebf5a66b2011-03-31 03:26:23 +000010942 {
10943 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10944 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
10945 return false;
10946
10947 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10948 if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
10949 return false;
10950 }
10951 else
10952 {
10953 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
10954 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
10955 return false;
10956
10957 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
10958 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
10959 return false;
10960 }
10961 // address = address+8;
10962 address = address + 8;
10963 }
10964 }
10965 }
10966 return true;
10967}
10968
Caroline Tice917ad352011-03-31 05:05:30 +000010969// A8.6.320
10970// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
10971// an optional offset.
10972bool
10973EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
10974{
10975#if 0
10976 if ConditionPassed() then
10977 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
10978 base = if n == 15 then Align(PC,4) else R[n];
10979 address = if add then (base + imm32) else (base - imm32);
10980 if single_reg then
10981 S[d] = MemA[address,4];
10982 else
10983 word1 = MemA[address,4]; word2 = MemA[address+4,4];
10984 // Combine the word-aligned words in the correct order for current endianness.
10985 D[d] = if BigEndian() then word1:word2 else word2:word1;
10986#endif
10987
10988 bool success = false;
10989
10990 if (ConditionPassed (opcode))
10991 {
10992 bool single_reg;
10993 bool add;
10994 uint32_t imm32;
10995 uint32_t d;
10996 uint32_t n;
10997
10998 switch (encoding)
10999 {
11000 case eEncodingT1:
11001 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011002 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000011003 single_reg = false;
11004 add = BitIsSet (opcode, 23);
11005 imm32 = Bits32 (opcode, 7, 0) << 2;
11006
11007 // d = UInt(D:Vd); n = UInt(Rn);
11008 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11009 n = Bits32 (opcode, 19, 16);
11010
11011 break;
11012
11013 case eEncodingT2:
11014 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011015 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice917ad352011-03-31 05:05:30 +000011016 single_reg = true;
11017 add = BitIsSet (opcode, 23);
11018 imm32 = Bits32 (opcode, 7, 0) << 2;
11019
11020 // d = UInt(Vd:D); n = UInt(Rn);
11021 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11022 n = Bits32 (opcode, 19, 16);
11023
11024 break;
11025
11026 default:
11027 return false;
11028 }
Greg Claytonc07d4512011-04-26 23:48:45 +000011029 RegisterInfo base_reg;
11030 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice917ad352011-03-31 05:05:30 +000011031
11032 uint32_t Rn = ReadCoreReg (n, &success);
11033 if (!success)
11034 return false;
11035
11036 // base = if n == 15 then Align(PC,4) else R[n];
11037 uint32_t base;
11038 if (n == 15)
11039 base = AlignPC (Rn);
11040 else
11041 base = Rn;
11042
11043 // address = if add then (base + imm32) else (base - imm32);
11044 addr_t address;
11045 if (add)
11046 address = base + imm32;
11047 else
11048 address = base - imm32;
11049
11050 const uint32_t addr_byte_size = GetAddressByteSize();
11051 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11052
11053 EmulateInstruction::Context context;
11054 context.type = eContextRegisterLoad;
11055 context.SetRegisterPlusOffset (base_reg, address - base);
Caroline Ticebf5a66b2011-03-31 03:26:23 +000011056
Caroline Tice917ad352011-03-31 05:05:30 +000011057 if (single_reg)
11058 {
11059 // S[d] = MemA[address,4];
11060 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
11061 if (!success)
11062 return false;
11063
11064 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
11065 return false;
11066 }
11067 else
11068 {
11069 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11070 uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
11071 if (!success)
11072 return false;
11073
11074 context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
11075 uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
11076 if (!success)
11077 return false;
11078 // // Combine the word-aligned words in the correct order for current endianness.
11079 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11080 uint64_t data64;
Greg Clayton888a7332011-04-26 04:39:08 +000011081 if (GetByteOrder() == eByteOrderBig)
Caroline Tice917ad352011-03-31 05:05:30 +000011082 {
11083 data64 = word1;
11084 data64 = (data64 << 32) | word2;
11085 }
11086 else
11087 {
11088 data64 = word2;
11089 data64 = (data64 << 32) | word1;
11090 }
11091
11092 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
11093 return false;
11094 }
11095 }
11096 return true;
11097}
Caroline Tice424652f2011-03-31 05:38:36 +000011098
11099// A8.6.400 VSTR
11100// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
11101// optional offset.
11102bool
11103EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
11104{
11105#if 0
11106 if ConditionPassed() then
11107 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11108 address = if add then (R[n] + imm32) else (R[n] - imm32);
11109 if single_reg then
11110 MemA[address,4] = S[d];
11111 else
11112 // Store as two word-aligned words in the correct order for current endianness.
11113 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11114 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11115#endif
11116
11117 bool success = false;
11118
11119 if (ConditionPassed (opcode))
11120 {
11121 bool single_reg;
11122 bool add;
11123 uint32_t imm32;
11124 uint32_t d;
11125 uint32_t n;
11126
11127 switch (encoding)
11128 {
11129 case eEncodingT1:
11130 case eEncodingA1:
Greg Clayton061b79d2011-05-09 20:18:18 +000011131 // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011132 single_reg = false;
11133 add = BitIsSet (opcode, 23);
11134 imm32 = Bits32 (opcode, 7, 0) << 2;
11135
11136 // d = UInt(D:Vd); n = UInt(Rn);
11137 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11138 n = Bits32 (opcode, 19, 16);
11139
11140 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11141 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11142 return false;
11143
11144 break;
11145
11146 case eEncodingT2:
11147 case eEncodingA2:
Greg Clayton061b79d2011-05-09 20:18:18 +000011148 // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
Caroline Tice424652f2011-03-31 05:38:36 +000011149 single_reg = true;
11150 add = BitIsSet (opcode, 23);
11151 imm32 = Bits32 (opcode, 7, 0) << 2;
11152
11153 // d = UInt(Vd:D); n = UInt(Rn);
11154 d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
11155 n = Bits32 (opcode, 19, 16);
11156
11157 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11158 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11159 return false;
11160
11161 break;
11162
11163 default:
11164 return false;
11165 }
11166
Greg Claytonc07d4512011-04-26 23:48:45 +000011167 RegisterInfo base_reg;
11168 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011169
11170 uint32_t Rn = ReadCoreReg (n, &success);
11171 if (!success)
11172 return false;
11173
11174 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11175 addr_t address;
11176 if (add)
11177 address = Rn + imm32;
11178 else
11179 address = Rn - imm32;
11180
11181 const uint32_t addr_byte_size = GetAddressByteSize();
11182 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11183
Greg Claytonc07d4512011-04-26 23:48:45 +000011184 RegisterInfo data_reg;
11185 GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
Caroline Tice424652f2011-03-31 05:38:36 +000011186 EmulateInstruction::Context context;
11187 context.type = eContextRegisterStore;
11188 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11189
11190 if (single_reg)
11191 {
11192 // MemA[address,4] = S[d];
11193 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11194 if (!success)
11195 return false;
11196
11197 if (!MemAWrite (context, address, data, addr_byte_size))
11198 return false;
11199 }
11200 else
11201 {
11202 // // Store as two word-aligned words in the correct order for current endianness.
11203 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11204 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11205 uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
11206 if (!success)
11207 return false;
11208
Greg Clayton888a7332011-04-26 04:39:08 +000011209 if (GetByteOrder() == eByteOrderBig)
Caroline Tice424652f2011-03-31 05:38:36 +000011210 {
11211 if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
11212 return false;
11213
11214 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11215 if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
11216 return false;
11217 }
11218 else
11219 {
11220 if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
11221 return false;
11222
11223 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
11224 if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
11225 return false;
11226 }
11227 }
11228 }
11229 return true;
11230}
Caroline Tice9121b352011-03-31 16:41:19 +000011231
11232// A8.6.307 VLDI1 (multiple single elements)
11233// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every
11234// element of each register is loaded.
11235bool
11236EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
11237{
11238#if 0
11239 if ConditionPassed() then
11240 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11241 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11242 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11243 for r = 0 to regs-1
11244 for e = 0 to elements-1
11245 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11246 address = address + ebytes;
11247#endif
11248
11249 bool success = false;
11250
11251 if (ConditionPassed (opcode))
11252 {
11253 uint32_t regs;
11254 uint32_t alignment;
11255 uint32_t ebytes;
11256 uint32_t esize;
11257 uint32_t elements;
11258 uint32_t d;
11259 uint32_t n;
11260 uint32_t m;
11261 bool wback;
11262 bool register_index;
11263
11264 switch (encoding)
11265 {
11266 case eEncodingT1:
11267 case eEncodingA1:
11268 {
11269 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011270 // when Ô0111Õ
11271 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
11272 // when Ô1010Õ
11273 // regs = 2; if align == Ô11Õ then UNDEFINED;
11274 // when Ô0110Õ
11275 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
11276 // when Ô0010Õ
Caroline Tice9121b352011-03-31 16:41:19 +000011277 // regs = 4;
11278 // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011279 // SEE ÒRelated encodingsÓ;
Caroline Tice9121b352011-03-31 16:41:19 +000011280 uint32_t type = Bits32 (opcode, 11, 8);
11281 uint32_t align = Bits32 (opcode, 5, 4);
11282 if (type == 7) // '0111'
11283 {
11284 regs = 1;
11285 if (BitIsSet (align, 1))
11286 return false;
11287 }
11288 else if (type == 10) // '1010'
11289 {
11290 regs = 2;
11291 if (align == 3)
11292 return false;
11293
11294 }
11295 else if (type == 6) // '0110'
11296 {
11297 regs = 3;
11298 if (BitIsSet (align, 1))
11299 return false;
11300 }
11301 else if (type == 2) // '0010'
11302 {
11303 regs = 4;
11304 }
11305 else
11306 return false;
11307
Greg Clayton061b79d2011-05-09 20:18:18 +000011308 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice9121b352011-03-31 16:41:19 +000011309 if (align == 0)
11310 alignment = 1;
11311 else
11312 alignment = 4 << align;
11313
11314 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11315 ebytes = 1 << Bits32 (opcode, 7, 6);
11316 esize = 8 * ebytes;
11317 elements = 8 / ebytes;
11318
11319 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11320 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11321 n = Bits32 (opcode, 19, 15);
11322 m = Bits32 (opcode, 3, 0);
11323
11324 // wback = (m != 15); register_index = (m != 15 && m != 13);
11325 wback = (m != 15);
11326 register_index = ((m != 15) && (m != 13));
11327
11328 // if d+regs > 32 then UNPREDICTABLE;
11329 if ((d + regs) > 32)
11330 return false;
11331 }
11332 break;
11333
11334 default:
11335 return false;
11336 }
11337
Greg Claytonc07d4512011-04-26 23:48:45 +000011338 RegisterInfo base_reg;
11339 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice9121b352011-03-31 16:41:19 +000011340
11341 uint32_t Rn = ReadCoreReg (n, &success);
11342 if (!success)
11343 return false;
11344
11345 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11346 addr_t address = Rn;
11347 if ((address % alignment) != 0)
11348 return false;
11349
11350 EmulateInstruction::Context context;
11351 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11352 if (wback)
11353 {
11354 uint32_t Rm = ReadCoreReg (m, &success);
11355 if (!success)
11356 return false;
11357
11358 uint32_t offset;
11359 if (register_index)
11360 offset = Rm;
11361 else
11362 offset = 8 * regs;
11363
11364 uint32_t value = Rn + offset;
11365 context.type = eContextAdjustBaseRegister;
11366 context.SetRegisterPlusOffset (base_reg, offset);
11367
11368 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11369 return false;
11370
11371 }
11372
11373 // for r = 0 to regs-1
11374 for (int r = 0; r < regs; ++r)
11375 {
11376 // for e = 0 to elements-1
11377 uint64_t assembled_data = 0;
11378 for (int e = 0; e < elements; ++e)
11379 {
11380 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11381 context.type = eContextRegisterLoad;
11382 context.SetRegisterPlusOffset (base_reg, address - Rn);
11383 uint64_t data = MemURead (context, address, ebytes, 0, &success);
11384 if (!success)
11385 return false;
11386
11387 assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
11388
11389 // address = address + ebytes;
11390 address = address + ebytes;
11391 }
11392 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
11393 return false;
11394 }
11395 }
11396 return true;
11397}
11398
Caroline Ticeb6281b12011-03-31 17:58:23 +000011399// A8.6.308 VLD1 (single element to one lane)
11400//
11401bool
11402EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
11403{
11404#if 0
11405 if ConditionPassed() then
11406 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11407 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11408 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11409 Elem[D[d],index,esize] = MemU[address,ebytes];
11410#endif
11411
11412 bool success = false;
11413
11414 if (ConditionPassed (opcode))
11415 {
11416 uint32_t ebytes;
11417 uint32_t esize;
11418 uint32_t index;
11419 uint32_t alignment;
11420 uint32_t d;
11421 uint32_t n;
11422 uint32_t m;
11423 bool wback;
11424 bool register_index;
11425
11426 switch (encoding)
11427 {
11428 case eEncodingT1:
11429 case eEncodingA1:
11430 {
11431 uint32_t size = Bits32 (opcode, 11, 10);
11432 uint32_t index_align = Bits32 (opcode, 7, 4);
Greg Clayton061b79d2011-05-09 20:18:18 +000011433 // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011434 if (size == 3)
11435 return EmulateVLD1SingleAll (opcode, encoding);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011436 // case size of
11437 if (size == 0) // when '00'
11438 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011439 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011440 if (BitIsClear (index_align, 0))
11441 return false;
11442
11443 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11444 ebytes = 1;
11445 esize = 8;
11446 index = Bits32 (index_align, 3, 1);
11447 alignment = 1;
11448 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011449 else if (size == 1) // when Ô01Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011450 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011451 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011452 if (BitIsClear (index_align, 1))
11453 return false;
11454
11455 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11456 ebytes = 2;
11457 esize = 16;
11458 index = Bits32 (index_align, 3, 2);
11459
Greg Clayton061b79d2011-05-09 20:18:18 +000011460 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011461 if (BitIsClear (index_align, 0))
11462 alignment = 1;
11463 else
11464 alignment = 2;
11465 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011466 else if (size == 2) // when Ô10Õ
Caroline Ticeb6281b12011-03-31 17:58:23 +000011467 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011468 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011469 if (BitIsClear (index_align, 2))
11470 return false;
11471
Greg Clayton061b79d2011-05-09 20:18:18 +000011472 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011473 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11474 return false;
11475
11476 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11477 ebytes = 4;
11478 esize = 32;
11479 index = Bit32 (index_align, 3);
11480
Greg Clayton061b79d2011-05-09 20:18:18 +000011481 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Ticeb6281b12011-03-31 17:58:23 +000011482 if (Bits32 (index_align, 1, 0) == 0)
11483 alignment = 1;
11484 else
11485 alignment = 4;
11486 }
11487 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11488 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11489 n = Bits32 (opcode, 19, 16);
11490 m = Bits32 (opcode, 3, 0);
11491
11492 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11493 wback = (m != 15);
11494 register_index = ((m != 15) && (m != 13));
11495
11496 if (n == 15)
11497 return false;
11498
11499 }
11500 break;
11501
11502 default:
11503 return false;
11504 }
11505
Greg Claytonc07d4512011-04-26 23:48:45 +000011506 RegisterInfo base_reg;
11507 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Ticeb6281b12011-03-31 17:58:23 +000011508
11509 uint32_t Rn = ReadCoreReg (n, &success);
11510 if (!success)
11511 return false;
11512
11513 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11514 addr_t address = Rn;
11515 if ((address % alignment) != 0)
11516 return false;
11517
11518 EmulateInstruction::Context context;
11519 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11520 if (wback)
11521 {
11522 uint32_t Rm = ReadCoreReg (m, &success);
11523 if (!success)
11524 return false;
11525
11526 uint32_t offset;
11527 if (register_index)
11528 offset = Rm;
11529 else
11530 offset = ebytes;
11531
11532 uint32_t value = Rn + offset;
11533
11534 context.type = eContextAdjustBaseRegister;
11535 context.SetRegisterPlusOffset (base_reg, offset);
11536
11537 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
11538 return false;
11539 }
11540
11541 // Elem[D[d],index,esize] = MemU[address,ebytes];
11542 uint32_t element = MemURead (context, address, esize, 0, &success);
11543 if (!success)
11544 return false;
11545
11546 element = element << (index * esize);
11547
11548 uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11549 if (!success)
11550 return false;
11551
11552 uint64_t all_ones = -1;
11553 uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's
11554 // at element & to the right of element.
11555 if (index > 0)
Caroline Tice7b880942011-03-31 19:17:12 +000011556 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 +000011557 // now mask should be 0's where element goes & 1's
11558 // everywhere else.
11559
11560 uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits
11561 reg_data = masked_reg & element; // Put 'element' into those bits in reg_data.
11562
11563 context.type = eContextRegisterLoad;
11564 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
11565 return false;
11566 }
11567 return true;
11568}
11569
Caroline Tice1e542e32011-03-31 18:44:04 +000011570// A8.6.391 VST1 (multiple single elements)
11571// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
11572// interleaving. Every element of each register is stored.
11573bool
11574EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
11575{
11576#if 0
11577 if ConditionPassed() then
11578 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11579 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11580 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11581 for r = 0 to regs-1
11582 for e = 0 to elements-1
11583 MemU[address,ebytes] = Elem[D[d+r],e,esize];
11584 address = address + ebytes;
11585#endif
11586
11587 bool success = false;
11588
11589 if (ConditionPassed (opcode))
11590 {
11591 uint32_t regs;
11592 uint32_t alignment;
11593 uint32_t ebytes;
11594 uint32_t esize;
11595 uint32_t elements;
11596 uint32_t d;
11597 uint32_t n;
11598 uint32_t m;
11599 bool wback;
11600 bool register_index;
11601
11602 switch (encoding)
11603 {
11604 case eEncodingT1:
11605 case eEncodingA1:
11606 {
11607 uint32_t type = Bits32 (opcode, 11, 8);
11608 uint32_t align = Bits32 (opcode, 5, 4);
11609
11610 // case type of
Greg Clayton061b79d2011-05-09 20:18:18 +000011611 if (type == 7) // when Ô0111Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011612 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011613 // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011614 regs = 1;
11615 if (BitIsSet (align, 1))
11616 return false;
11617 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011618 else if (type == 10) // when Ô1010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011619 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011620 // regs = 2; if align == Ô11Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011621 regs = 2;
11622 if (align == 3)
11623 return false;
11624 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011625 else if (type == 6) // when Ô0110Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011626 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011627 // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
Caroline Tice1e542e32011-03-31 18:44:04 +000011628 regs = 3;
11629 if (BitIsSet (align, 1))
11630 return false;
11631 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011632 else if (type == 2) // when Ô0010Õ
Caroline Tice1e542e32011-03-31 18:44:04 +000011633 // regs = 4;
11634 regs = 4;
11635 else // otherwise
Greg Clayton061b79d2011-05-09 20:18:18 +000011636 // SEE ÒRelated encodingsÓ;
Caroline Tice1e542e32011-03-31 18:44:04 +000011637 return false;
11638
Greg Clayton061b79d2011-05-09 20:18:18 +000011639 // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
Caroline Tice1e542e32011-03-31 18:44:04 +000011640 if (align == 0)
11641 alignment = 0;
11642 else
11643 alignment = 4 << align;
11644
11645 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11646 ebytes = 1 << Bits32 (opcode,7, 6);
11647 esize = 8 * ebytes;
11648 elements = 8 / ebytes;
11649
11650 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11651 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11652 n = Bits32 (opcode, 19, 16);
11653 m = Bits32 (opcode, 3, 0);
11654
11655 // wback = (m != 15); register_index = (m != 15 && m != 13);
11656 wback = (m != 15);
11657 register_index = ((m != 15) && (m != 13));
11658
11659 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11660 if ((d + regs) > 32)
11661 return false;
11662
11663 if (n == 15)
11664 return false;
11665
11666 }
11667 break;
11668
11669 default:
11670 return false;
11671 }
11672
Greg Claytonc07d4512011-04-26 23:48:45 +000011673 RegisterInfo base_reg;
11674 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011675
11676 uint32_t Rn = ReadCoreReg (n, &success);
11677 if (!success)
11678 return false;
11679
11680 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11681 addr_t address = Rn;
11682 if ((address % alignment) != 0)
11683 return false;
11684
11685 EmulateInstruction::Context context;
11686 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11687 if (wback)
11688 {
11689 uint32_t Rm = ReadCoreReg (m, &success);
11690 if (!success)
11691 return false;
11692
11693 uint32_t offset;
11694 if (register_index)
11695 offset = Rm;
11696 else
11697 offset = 8 * regs;
11698
11699 context.type = eContextAdjustBaseRegister;
11700 context.SetRegisterPlusOffset (base_reg, offset);
11701
11702 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11703 return false;
11704 }
11705
Greg Claytonc07d4512011-04-26 23:48:45 +000011706 RegisterInfo data_reg;
Caroline Tice1e542e32011-03-31 18:44:04 +000011707 context.type = eContextRegisterStore;
Caroline Tice1e542e32011-03-31 18:44:04 +000011708 // for r = 0 to regs-1
11709 for (int r = 0; r < regs; ++r)
11710 {
Greg Claytonc07d4512011-04-26 23:48:45 +000011711 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
Caroline Tice1e542e32011-03-31 18:44:04 +000011712 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
11713 if (!success)
11714 return false;
11715
11716 // for e = 0 to elements-1
11717 for (int e = 0; e < elements; ++e)
11718 {
11719 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
Caroline Tice7b880942011-03-31 19:17:12 +000011720 uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
Caroline Tice1e542e32011-03-31 18:44:04 +000011721
11722 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11723 if (!MemUWrite (context, address, word, ebytes))
11724 return false;
11725
11726 // address = address + ebytes;
11727 address = address + ebytes;
11728 }
11729 }
11730 }
11731 return true;
11732}
11733
Caroline Tice7b880942011-03-31 19:17:12 +000011734// A8.6.392 VST1 (single element from one lane)
11735// This instruction stores one element to memory from one element of a register.
11736bool
11737EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
11738{
11739#if 0
11740 if ConditionPassed() then
11741 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11742 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11743 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11744 MemU[address,ebytes] = Elem[D[d],index,esize];
11745#endif
11746
11747 bool success = false;
11748
11749 if (ConditionPassed (opcode))
11750 {
11751 uint32_t ebytes;
11752 uint32_t esize;
11753 uint32_t index;
11754 uint32_t alignment;
11755 uint32_t d;
11756 uint32_t n;
11757 uint32_t m;
11758 bool wback;
11759 bool register_index;
11760
11761 switch (encoding)
11762 {
11763 case eEncodingT1:
11764 case eEncodingA1:
11765 {
11766 uint32_t size = Bits32 (opcode, 11, 10);
11767 uint32_t index_align = Bits32 (opcode, 7, 4);
11768
Greg Clayton061b79d2011-05-09 20:18:18 +000011769 // if size == Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011770 if (size == 3)
11771 return false;
11772
11773 // case size of
Greg Clayton061b79d2011-05-09 20:18:18 +000011774 if (size == 0) // when Ô00Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011775 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011776 // if index_align<0> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011777 if (BitIsClear (index_align, 0))
11778 return false;
11779 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
11780 ebytes = 1;
11781 esize = 8;
11782 index = Bits32 (index_align, 3, 1);
11783 alignment = 1;
11784 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011785 else if (size == 1) // when Ô01Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011786 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011787 // if index_align<1> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011788 if (BitIsClear (index_align, 1))
11789 return false;
11790
11791 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
11792 ebytes = 2;
11793 esize = 16;
11794 index = Bits32 (index_align, 3, 2);
11795
Greg Clayton061b79d2011-05-09 20:18:18 +000011796 // alignment = if index_align<0> == Ô0Õ then 1 else 2;
Caroline Tice7b880942011-03-31 19:17:12 +000011797 if (BitIsClear (index_align, 0))
11798 alignment = 1;
11799 else
11800 alignment = 2;
11801 }
Greg Clayton061b79d2011-05-09 20:18:18 +000011802 else if (size == 2) // when Ô10Õ
Caroline Tice7b880942011-03-31 19:17:12 +000011803 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011804 // if index_align<2> != Ô0Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011805 if (BitIsClear (index_align, 2))
11806 return false;
11807
Greg Clayton061b79d2011-05-09 20:18:18 +000011808 // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
Caroline Tice7b880942011-03-31 19:17:12 +000011809 if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
11810 return false;
11811
11812 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
11813 ebytes = 4;
11814 esize = 32;
11815 index = Bit32 (index_align, 3);
11816
Greg Clayton061b79d2011-05-09 20:18:18 +000011817 // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
Caroline Tice7b880942011-03-31 19:17:12 +000011818 if (Bits32 (index_align, 1, 0) == 0)
11819 alignment = 1;
11820 else
11821 alignment = 4;
11822 }
11823 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11824 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11825 n = Bits32 (opcode, 19, 16);
11826 m = Bits32 (opcode, 3, 0);
11827
11828 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
11829 wback = (m != 15);
11830 register_index = ((m != 15) && (m != 13));
11831
11832 if (n == 15)
11833 return false;
11834 }
11835 break;
11836
11837 default:
11838 return false;
11839 }
11840
Greg Claytonc07d4512011-04-26 23:48:45 +000011841 RegisterInfo base_reg;
11842 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011843
11844 uint32_t Rn = ReadCoreReg (n, &success);
11845 if (!success)
11846 return false;
11847
11848 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11849 addr_t address = Rn;
11850 if ((address % alignment) != 0)
11851 return false;
11852
11853 EmulateInstruction::Context context;
11854 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11855 if (wback)
11856 {
11857 uint32_t Rm = ReadCoreReg (m, &success);
11858 if (!success)
11859 return false;
11860
11861 uint32_t offset;
11862 if (register_index)
11863 offset = Rm;
11864 else
11865 offset = ebytes;
11866
11867 context.type = eContextAdjustBaseRegister;
11868 context.SetRegisterPlusOffset (base_reg, offset);
11869
11870 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11871 return false;
11872 }
11873
11874 // MemU[address,ebytes] = Elem[D[d],index,esize];
11875 uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
11876 if (!success)
11877 return false;
11878
11879 uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize);
11880
Greg Claytonc07d4512011-04-26 23:48:45 +000011881 RegisterInfo data_reg;
11882 GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
Caroline Tice7b880942011-03-31 19:17:12 +000011883 context.type = eContextRegisterStore;
11884 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
11885
11886 if (!MemUWrite (context, address, word, ebytes))
11887 return false;
11888 }
11889 return true;
11890}
11891
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011892// A8.6.309 VLD1 (single element to all lanes)
11893// This instruction loads one element from memory into every element of one or two vectors.
Caroline Tice93767b82011-03-31 21:15:29 +000011894bool
Caroline Tice8d24b4a2011-03-31 21:31:50 +000011895EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice93767b82011-03-31 21:15:29 +000011896{
11897#if 0
11898 if ConditionPassed() then
11899 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11900 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11901 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11902 replicated_element = Replicate(MemU[address,ebytes], elements);
11903 for r = 0 to regs-1
11904 D[d+r] = replicated_element;
11905#endif
11906
11907 bool success = false;
11908
11909 if (ConditionPassed (opcode))
11910 {
11911 uint32_t ebytes;
11912 uint32_t elements;
11913 uint32_t regs;
11914 uint32_t alignment;
11915 uint32_t d;
11916 uint32_t n;
11917 uint32_t m;
11918 bool wback;
11919 bool register_index;
11920
11921 switch (encoding)
11922 {
11923 case eEncodingT1:
11924 case eEncodingA1:
11925 {
Greg Clayton061b79d2011-05-09 20:18:18 +000011926 //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
Caroline Tice93767b82011-03-31 21:15:29 +000011927 uint32_t size = Bits32 (opcode, 7, 6);
11928 if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
11929 return false;
11930
Greg Clayton061b79d2011-05-09 20:18:18 +000011931 //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
Caroline Tice93767b82011-03-31 21:15:29 +000011932 ebytes = 1 << size;
11933 elements = 8 / ebytes;
11934 if (BitIsClear (opcode, 5))
11935 regs = 1;
11936 else
11937 regs = 2;
11938
Greg Clayton061b79d2011-05-09 20:18:18 +000011939 //alignment = if a == Ô0Õ then 1 else ebytes;
Caroline Tice93767b82011-03-31 21:15:29 +000011940 if (BitIsClear (opcode, 4))
11941 alignment = 1;
11942 else
11943 alignment = ebytes;
11944
11945 //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11946 d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
11947 n = Bits32 (opcode, 19, 16);
11948 m = Bits32 (opcode, 3, 0);
11949
11950 //wback = (m != 15); register_index = (m != 15 && m != 13);
11951 wback = (m != 15);
11952 register_index = ((m != 15) && (m != 13));
11953
11954 //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
11955 if ((d + regs) > 32)
11956 return false;
11957
11958 if (n == 15)
11959 return false;
11960 }
11961 break;
11962
11963 default:
11964 break;
11965 }
11966
Greg Claytonc07d4512011-04-26 23:48:45 +000011967 RegisterInfo base_reg;
11968 GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
Caroline Tice93767b82011-03-31 21:15:29 +000011969
11970 uint32_t Rn = ReadCoreReg (n, &success);
11971 if (!success)
11972 return false;
11973
11974 // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11975 addr_t address = Rn;
11976 if ((address % alignment) != 0)
11977 return false;
11978
11979 EmulateInstruction::Context context;
11980 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
11981 if (wback)
11982 {
11983 uint32_t Rm = ReadCoreReg (m, &success);
11984 if (!success)
11985 return false;
11986
11987 uint32_t offset;
11988 if (register_index)
11989 offset = Rm;
11990 else
11991 offset = ebytes;
11992
11993 context.type = eContextAdjustBaseRegister;
11994 context.SetRegisterPlusOffset (base_reg, offset);
11995
11996 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
11997 return false;
11998 }
11999
12000 // replicated_element = Replicate(MemU[address,ebytes], elements);
12001
12002 context.type = eContextRegisterLoad;
12003 uint64_t word = MemURead (context, address, ebytes, 0, &success);
12004 if (!success)
12005 return false;
12006
12007 uint64_t replicated_element;
12008 uint32_t esize = ebytes * 8;
12009 for (int e = 0; e < elements; ++e)
12010 replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
12011
12012 // for r = 0 to regs-1
12013 for (int r = 0; r < regs; ++r)
12014 {
12015 // D[d+r] = replicated_element;
12016 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
12017 return false;
12018 }
12019 }
12020 return true;
12021}
12022
Caroline Tice1f954f52011-04-11 15:51:10 +000012023// B6.2.13 SUBS PC, LR and related instructions
12024//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the
12025// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
12026bool
12027EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
12028{
12029#if 0
12030 if ConditionPassed() then
12031 EncodingSpecificOperations();
12032 if CurrentInstrSet() == InstrSet_ThumbEE then
12033 UNPREDICTABLE;
12034 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12035 case opcode of
Greg Clayton061b79d2011-05-09 20:18:18 +000012036 when Ô0000Õ result = R[n] AND operand2; // AND
12037 when Ô0001Õ result = R[n] EOR operand2; // EOR
12038 when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
12039 when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
12040 when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
12041 when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12042 when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12043 when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12044 when Ô1100Õ result = R[n] OR operand2; // ORR
12045 when Ô1101Õ result = operand2; // MOV
12046 when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
12047 when Ô1111Õ result = NOT(operand2); // MVN
12048 CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012049 BranchWritePC(result);
12050#endif
12051
12052 bool success = false;
12053
12054 if (ConditionPassed (opcode))
12055 {
12056 uint32_t n;
12057 uint32_t m;
12058 uint32_t imm32;
12059 bool register_form;
12060 ARM_ShifterType shift_t;
12061 uint32_t shift_n;
12062 uint32_t code;
12063
12064 switch (encoding)
12065 {
12066 case eEncodingT1:
12067 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
Greg Clayton061b79d2011-05-09 20:18:18 +000012068 // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012069 n = 14;
12070 imm32 = Bits32 (opcode, 7, 0);
12071 register_form = false;
12072 code = 2;
12073
12074 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12075 if (InITBlock() && !LastInITBlock())
12076 return false;
12077
12078 break;
12079
12080 case eEncodingA1:
12081 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12082 n = Bits32 (opcode, 19, 16);
12083 imm32 = ARMExpandImm (opcode);
12084 register_form = false;
12085 code = Bits32 (opcode, 24, 21);
12086
12087 break;
12088
12089 case eEncodingA2:
12090 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12091 n = Bits32 (opcode, 19, 16);
12092 m = Bits32 (opcode, 3, 0);
12093 register_form = true;
12094
12095 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12096 shift_n = DecodeImmShiftARM (opcode, shift_t);
12097
12098 break;
12099
12100 default:
12101 return false;
12102 }
12103
12104 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12105 uint32_t operand2;
12106 if (register_form)
12107 {
12108 uint32_t Rm = ReadCoreReg (m, &success);
12109 if (!success)
12110 return false;
12111
Johnny Chena4438a72011-06-02 22:50:51 +000012112 operand2 = Shift (Rm, shift_t, shift_n, APSR_C, &success);
12113 if (!success)
12114 return false;
Caroline Tice1f954f52011-04-11 15:51:10 +000012115 }
12116 else
12117 {
12118 operand2 = imm32;
12119 }
12120
12121 uint32_t Rn = ReadCoreReg (n, &success);
12122 if (!success)
12123 return false;
12124
12125 AddWithCarryResult result;
12126
12127 // case opcode of
12128 switch (code)
12129 {
Greg Clayton061b79d2011-05-09 20:18:18 +000012130 case 0: // when Ô0000Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012131 // result = R[n] AND operand2; // AND
12132 result.result = Rn & operand2;
12133 break;
12134
Greg Clayton061b79d2011-05-09 20:18:18 +000012135 case 1: // when Ô0001Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012136 // result = R[n] EOR operand2; // EOR
12137 result.result = Rn ^ operand2;
12138 break;
12139
Greg Clayton061b79d2011-05-09 20:18:18 +000012140 case 2: // when Ô0010Õ
12141 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
Caroline Tice1f954f52011-04-11 15:51:10 +000012142 result = AddWithCarry (Rn, ~(operand2), 1);
12143 break;
12144
Greg Clayton061b79d2011-05-09 20:18:18 +000012145 case 3: // when Ô0011Õ
12146 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
Caroline Tice1f954f52011-04-11 15:51:10 +000012147 result = AddWithCarry (~(Rn), operand2, 1);
12148 break;
12149
Greg Clayton061b79d2011-05-09 20:18:18 +000012150 case 4: // when Ô0100Õ
12151 // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
Caroline Tice1f954f52011-04-11 15:51:10 +000012152 result = AddWithCarry (Rn, operand2, 0);
12153 break;
12154
Greg Clayton061b79d2011-05-09 20:18:18 +000012155 case 5: // when Ô0101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012156 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12157 result = AddWithCarry (Rn, operand2, APSR_C);
12158 break;
12159
Greg Clayton061b79d2011-05-09 20:18:18 +000012160 case 6: // when Ô0110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012161 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12162 result = AddWithCarry (Rn, ~(operand2), APSR_C);
12163 break;
12164
Greg Clayton061b79d2011-05-09 20:18:18 +000012165 case 7: // when Ô0111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012166 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12167 result = AddWithCarry (~(Rn), operand2, APSR_C);
12168 break;
12169
Greg Clayton061b79d2011-05-09 20:18:18 +000012170 case 10: // when Ô1100Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012171 // result = R[n] OR operand2; // ORR
12172 result.result = Rn | operand2;
12173 break;
12174
Greg Clayton061b79d2011-05-09 20:18:18 +000012175 case 11: // when Ô1101Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012176 // result = operand2; // MOV
12177 result.result = operand2;
12178 break;
12179
Greg Clayton061b79d2011-05-09 20:18:18 +000012180 case 12: // when Ô1110Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012181 // result = R[n] AND NOT(operand2); // BIC
12182 result.result = Rn & ~(operand2);
12183 break;
12184
Greg Clayton061b79d2011-05-09 20:18:18 +000012185 case 15: // when Ô1111Õ
Caroline Tice1f954f52011-04-11 15:51:10 +000012186 // result = NOT(operand2); // MVN
12187 result.result = ~(operand2);
12188 break;
12189
12190 default:
12191 return false;
12192 }
Greg Clayton061b79d2011-05-09 20:18:18 +000012193 // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
Caroline Tice1f954f52011-04-11 15:51:10 +000012194
12195 // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
12196 // the best.
12197 uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12198 if (!success)
12199 return false;
12200
12201 CPSRWriteByInstr (spsr, 15, true);
12202
12203 // BranchWritePC(result);
12204 EmulateInstruction::Context context;
12205 context.type = eContextAdjustPC;
12206 context.SetImmediate (result.result);
12207
12208 BranchWritePC (context, result.result);
12209 }
12210 return true;
12211}
12212
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012213EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012214EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Greg Clayton64c84432011-01-21 22:02:52 +000012215{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012216 static ARMOpcode
12217 g_arm_opcodes[] =
12218 {
12219 //----------------------------------------------------------------------
12220 // Prologue instructions
12221 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000012222
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012223 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012224 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12225 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000012226
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012227 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012228 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
12229 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000012230 // copy the stack pointer to ip
Caroline Tice4f605582011-03-31 00:02:51 +000012231 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
12232 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
12233 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000012234
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012235 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012236 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12237 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000012238
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012239 // push one register
12240 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice4f605582011-03-31 00:02:51 +000012241 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000012242
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012243 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012244 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12245 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000012246
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012247 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000012248 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012249 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000012250
Caroline Tice4f605582011-03-31 00:02:51 +000012251 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12252 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12253 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12254 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012255
12256 //----------------------------------------------------------------------
12257 // Supervisor Call (previously Software Interrupt)
12258 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012259 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012260
12261 //----------------------------------------------------------------------
12262 // Branch instructions
12263 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012264 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000012265 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
Caroline Tice4f605582011-03-31 00:02:51 +000012266 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12267 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12268 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012269 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012270 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012271 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012272 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012273
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012274 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000012275 // Data-processing instructions
12276 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012277 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012278 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen157b9592011-02-18 21:13:05 +000012279 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012280 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012281 // add (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012282 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000012283 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012284 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000012285 // add (register-shifted register)
Caroline Tice0fe5a532011-04-08 23:33:06 +000012286 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000012287 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012288 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12289 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012290 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012291 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012292 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012293 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012294 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012295 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012296 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012297 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012298 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012299 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012300 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012301 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012302 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012303 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012304 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012305 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012306 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012307 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012308 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012309 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012310 // rsc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012311 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen90e607b2011-02-23 00:07:09 +000012312 // rsc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012313 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000012314 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012315 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012316 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012317 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012318 // sub (immediate, ARM)
Caroline Tice4f605582011-03-31 00:02:51 +000012319 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012320 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012321 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012322 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012323 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000012324 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012325 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
Johnny Chen2115b412011-02-21 23:42:44 +000012326 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012327 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012328 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012329 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
Johnny Chende3cce32011-02-21 21:24:49 +000012330 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012331 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012332
Caroline Tice89c6d582011-03-29 19:53:44 +000012333 // mov (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012334 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12335 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000012336 // mov (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012337 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012338 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012339 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012340 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012341 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012342 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012343 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen3847dad2011-02-22 02:00:12 +000012344 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012345 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012346 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012347 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012348 // cmp (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012349 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012350 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012351 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012352 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012353 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012354 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012355 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012356 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012357 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012358 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012359 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012360 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012361 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012362 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012363 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012364 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012365 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012366 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012367 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012368 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012369 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012370
12371 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012372 { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" },
12373 { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
Johnny Chen28070c32011-02-12 01:27:26 +000012374
12375 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012376 // Load instructions
12377 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012378 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12379 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
12380 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12381 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
12382 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
12383 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
12384 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
12385 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
12386 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12387 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12388 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
12389 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
12390 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12391 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
12392 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12393 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
12394 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
12395 { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice9121b352011-03-31 16:41:19 +000012396 { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12397 { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12398 { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12399 { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012400 { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
12401 { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012402 { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012403
12404 //----------------------------------------------------------------------
12405 // Store instructions
12406 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012407 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12408 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
12409 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12410 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
12411 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
12412 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
12413 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
12414 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
12415 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice0fe5a532011-04-08 23:33:06 +000012416 { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
Caroline Tice4f605582011-03-31 00:02:51 +000012417 { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012418 { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12419 { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
12420 { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
12421 { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
12422 { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012423 { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice1511f502011-02-15 00:19:42 +000012424
Caroline Tice6bf65162011-03-03 17:42:58 +000012425 //----------------------------------------------------------------------
12426 // Other instructions
12427 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012428 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
12429 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
12430 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
12431 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
12432 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000012433
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012434 };
12435 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
12436
12437 for (size_t i=0; i<k_num_arm_opcodes; ++i)
12438 {
Greg Clayton888a7332011-04-26 04:39:08 +000012439 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
12440 (g_arm_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012441 return &g_arm_opcodes[i];
12442 }
12443 return NULL;
12444}
Greg Clayton64c84432011-01-21 22:02:52 +000012445
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012446
12447EmulateInstructionARM::ARMOpcode*
Greg Clayton888a7332011-04-26 04:39:08 +000012448EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
Johnny Chen347320d2011-01-24 23:40:59 +000012449{
Johnny Chenfdd179e2011-01-31 20:09:28 +000012450
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012451 static ARMOpcode
12452 g_thumb_opcodes[] =
12453 {
12454 //----------------------------------------------------------------------
12455 // Prologue instructions
12456 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000012457
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012458 // push register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012459 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
12460 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
12461 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000012462
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012463 // set r7 to point to a stack offset
Caroline Tice4f605582011-03-31 00:02:51 +000012464 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012465 // copy the stack pointer to r7
Caroline Tice4f605582011-03-31 00:02:51 +000012466 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000012467 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Caroline Tice4f605582011-03-31 00:02:51 +000012468 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000012469
Johnny Chen864a8e82011-02-18 00:07:39 +000012470 // PC-relative load into register (see also EmulateADDSPRm)
Caroline Tice4f605582011-03-31 00:02:51 +000012471 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000012472
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012473 // adjust the stack pointer
Caroline Tice4f605582011-03-31 00:02:51 +000012474 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
12475 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
12476 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
12477 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
12478 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000012479
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012480 // vector push consecutive extension register(s)
Caroline Tice4f605582011-03-31 00:02:51 +000012481 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12482 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000012483
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012484 //----------------------------------------------------------------------
12485 // Epilogue instructions
12486 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000012487
Caroline Tice4f605582011-03-31 00:02:51 +000012488 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
12489 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
12490 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12491 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
12492 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
12493 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12494 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000012495
12496 //----------------------------------------------------------------------
12497 // Supervisor Call (previously Software Interrupt)
12498 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012499 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
Johnny Chenc315f862011-02-05 00:46:10 +000012500
12501 //----------------------------------------------------------------------
12502 // If Then makes up to four following instructions conditional.
12503 //----------------------------------------------------------------------
Greg Clayton04d397c2011-05-23 18:04:09 +000012504 // The next 5 opcode _must_ come before the if then instruction
12505 { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"},
12506 { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
12507 { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
12508 { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
12509 { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
12510 { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
Johnny Chen3b620b32011-02-07 20:11:47 +000012511
12512 //----------------------------------------------------------------------
12513 // Branch instructions
12514 //----------------------------------------------------------------------
12515 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
Caroline Tice4f605582011-03-31 00:02:51 +000012516 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
12517 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
12518 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
12519 { 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 +000012520 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012521 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000012522 // J1 == J2 == 1
Caroline Tice4f605582011-03-31 00:02:51 +000012523 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12524 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000012525 // for example, "bx lr"
Caroline Tice4f605582011-03-31 00:02:51 +000012526 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000012527 // bxj
Caroline Tice4f605582011-03-31 00:02:51 +000012528 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000012529 // compare and branch
Caroline Tice4f605582011-03-31 00:02:51 +000012530 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012531 // table branch byte
Caroline Tice4f605582011-03-31 00:02:51 +000012532 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000012533 // table branch halfword
Caroline Tice4f605582011-03-31 00:02:51 +000012534 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012535
12536 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000012537 // Data-processing instructions
12538 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000012539 // adc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012540 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen157b9592011-02-18 21:13:05 +000012541 // adc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012542 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
12543 { 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 +000012544 // add (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012545 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000012546 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Caroline Tice4f605582011-03-31 00:02:51 +000012547 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000012548 // adr
Caroline Tice4f605582011-03-31 00:02:51 +000012549 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12550 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12551 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012552 // and (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012553 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000012554 // and (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012555 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
12556 { 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 +000012557 // bic (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012558 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000012559 // bic (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012560 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
12561 { 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 +000012562 // eor (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012563 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012564 // eor (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012565 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
12566 { 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 +000012567 // orr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012568 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012569 // orr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012570 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
12571 { 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 +000012572 // rsb (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012573 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
12574 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
Johnny Chened32e7c2011-02-22 23:42:58 +000012575 // rsb (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012576 { 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 +000012577 // sbc (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012578 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chen9b381772011-02-23 01:01:21 +000012579 // sbc (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012580 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
12581 { 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 +000012582 // add (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012583 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
12584 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
12585 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
12586 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000012587 // sub (immediate, Thumb)
Caroline Tice4f605582011-03-31 00:02:51 +000012588 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
12589 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
12590 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
12591 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000012592 // sub (sp minus immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012593 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
12594 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000012595 // sub (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012596 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
12597 { 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 +000012598 // teq (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012599 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +000012600 // teq (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012601 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012602 // tst (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012603 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000012604 // tst (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012605 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
12606 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000012607
Johnny Chen7c5234d2011-02-18 23:41:11 +000012608
Johnny Chen338bf542011-02-10 19:29:03 +000012609 // move from high register to high register
Caroline Tice4f605582011-03-31 00:02:51 +000012610 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000012611 // move from low register to low register
Caroline Tice4f605582011-03-31 00:02:51 +000012612 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000012613 // mov{s}<c>.w <Rd>, <Rm>
Caroline Tice4f605582011-03-31 00:02:51 +000012614 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000012615 // move immediate
Caroline Tice4f605582011-03-31 00:02:51 +000012616 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
12617 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
12618 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012619 // mvn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012620 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000012621 // mvn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012622 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
12623 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012624 // cmn (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012625 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012626 // cmn (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012627 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
12628 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012629 // cmp (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012630 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
12631 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012632 // cmp (register) (Rn and Rm both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012633 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000012634 // cmp (register) (Rn and Rm not both from r0-r7)
Caroline Tice4f605582011-03-31 00:02:51 +000012635 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000012636 // asr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012637 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
12638 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000012639 // asr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012640 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
12641 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012642 // lsl (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012643 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
12644 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012645 // lsl (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012646 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
12647 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012648 // lsr (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012649 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
12650 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000012651 // lsr (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012652 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
12653 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012654 // rrx is a special case encoding of ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012655 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012656 // ror (immediate)
Caroline Tice4f605582011-03-31 00:02:51 +000012657 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Cheneeab4852011-02-16 22:14:44 +000012658 // ror (register)
Caroline Tice4f605582011-03-31 00:02:51 +000012659 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
12660 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012661 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012662 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000012663 // mul
Caroline Tice4f605582011-03-31 00:02:51 +000012664 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6b8d3b52011-04-19 23:30:03 +000012665
12666 // subs pc, lr and related instructions
Caroline Tice1f954f52011-04-11 15:51:10 +000012667 { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
Caroline Tice080bf612011-04-05 18:46:00 +000012668
12669 //----------------------------------------------------------------------
12670 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table;
12671 // otherwise the wrong instructions will be selected.
12672 //----------------------------------------------------------------------
Caroline Tice6bf65162011-03-03 17:42:58 +000012673
Caroline Tice080bf612011-04-05 18:46:00 +000012674 { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
12675 { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
12676
Johnny Chen26863dc2011-02-09 23:43:29 +000012677 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000012678 // Load instructions
12679 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012680 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
12681 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
12682 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
12683 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
12684 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
12685 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
12686 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
Caroline Ticebaf1f642011-03-24 19:23:45 +000012687 // Thumb2 PC-relative load into register
Caroline Tice4f605582011-03-31 00:02:51 +000012688 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
12689 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
12690 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
12691 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
12692 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
Caroline Tice0fe5a532011-04-08 23:33:06 +000012693 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice4f605582011-03-31 00:02:51 +000012694 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
12695 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
12696 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12697 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
12698 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
12699 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
12700 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
12701 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
12702 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12703 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
12704 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12705 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
12706 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
12707 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
12708 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
12709 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
12710 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
12711 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
12712 { 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 +000012713 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Tice9121b352011-03-31 16:41:19 +000012714 { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
12715 { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
12716 { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12717 { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
Caroline Ticeb6281b12011-03-31 17:58:23 +000012718 { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
12719 { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
Caroline Tice93767b82011-03-31 21:15:29 +000012720 { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Ticefa172202011-02-11 22:49:54 +000012721
12722 //----------------------------------------------------------------------
12723 // Store instructions
12724 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012725 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
12726 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
12727 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
12728 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
12729 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
12730 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
12731 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
12732 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
12733 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
12734 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
12735 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
12736 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
12737 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
12738 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
12739 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
12740 { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
Caroline Tice1e542e32011-03-31 18:44:04 +000012741 { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12742 { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
12743 { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
12744 { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
12745 { 0xffb00000, 0xfa000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice7b880942011-03-31 19:17:12 +000012746 { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
Caroline Tice6bf65162011-03-03 17:42:58 +000012747
12748 //----------------------------------------------------------------------
12749 // Other instructions
12750 //----------------------------------------------------------------------
Caroline Tice4f605582011-03-31 00:02:51 +000012751 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
12752 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12753 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
12754 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
12755 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
12756 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
12757 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
12758 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012759 };
12760
12761 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
12762 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
12763 {
Greg Clayton888a7332011-04-26 04:39:08 +000012764 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
12765 (g_thumb_opcodes[i].variants & arm_isa) != 0)
Greg Clayton2b8e8b02011-02-01 00:49:32 +000012766 return &g_thumb_opcodes[i];
12767 }
12768 return NULL;
12769}
Greg Clayton64c84432011-01-21 22:02:52 +000012770
Greg Clayton31e2a382011-01-30 20:03:56 +000012771bool
Greg Clayton395fc332011-02-15 21:59:32 +000012772EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000012773{
Caroline Tice080bf612011-04-05 18:46:00 +000012774 m_arch = arch;
Greg Clayton31e2a382011-01-30 20:03:56 +000012775 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000012776 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000012777 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000012778 {
Greg Clayton395fc332011-02-15 21:59:32 +000012779 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
12780 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
12781 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
12782 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
12783 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
12784 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
12785 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
12786 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
12787 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
12788 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Johnny Chen1d29a852011-04-26 18:51:57 +000012789 else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll;
12790 else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll;
Greg Clayton31e2a382011-01-30 20:03:56 +000012791 }
12792 return m_arm_isa != 0;
12793}
12794
Caroline Tice080bf612011-04-05 18:46:00 +000012795bool
Greg Clayton888a7332011-04-26 04:39:08 +000012796EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
Caroline Tice080bf612011-04-05 18:46:00 +000012797{
Greg Clayton888a7332011-04-26 04:39:08 +000012798 if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
12799 {
12800 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
12801 m_opcode_mode = eModeThumb;
12802 else
12803 {
12804 AddressClass addr_class = inst_addr.GetAddressClass();
Caroline Tice080bf612011-04-05 18:46:00 +000012805
Greg Clayton888a7332011-04-26 04:39:08 +000012806 if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
12807 m_opcode_mode = eModeARM;
12808 else if (addr_class == eAddressClassCodeAlternateISA)
12809 m_opcode_mode = eModeThumb;
12810 else
12811 return false;
12812 }
12813 if (m_opcode_mode == eModeThumb)
12814 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
12815 else
12816 m_opcode_cpsr = CPSR_MODE_USR;
12817 return true;
12818 }
12819 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000012820}
Greg Clayton31e2a382011-01-30 20:03:56 +000012821
Greg Clayton64c84432011-01-21 22:02:52 +000012822bool
12823EmulateInstructionARM::ReadInstruction ()
12824{
12825 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000012826 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012827 if (success)
12828 {
12829 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
12830 if (success)
12831 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000012832 Context read_inst_context;
12833 read_inst_context.type = eContextReadOpcode;
12834 read_inst_context.SetNoArgs ();
12835
Greg Claytonb3448432011-03-24 21:19:54 +000012836 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000012837 {
Greg Claytonb3448432011-03-24 21:19:54 +000012838 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000012839 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000012840
12841 if (success)
12842 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012843 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000012844 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012845 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012846 }
12847 else
12848 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012849 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012850 }
12851 }
12852 }
12853 else
12854 {
Greg Claytonb3448432011-03-24 21:19:54 +000012855 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000012856 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000012857 }
12858 }
12859 }
12860 if (!success)
12861 {
Greg Claytonb3448432011-03-24 21:19:54 +000012862 m_opcode_mode = eModeInvalid;
Greg Clayton3063c952011-04-29 22:50:31 +000012863 m_addr = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000012864 }
12865 return success;
12866}
12867
Johnny Chenee9b1f72011-02-09 01:00:31 +000012868uint32_t
12869EmulateInstructionARM::ArchVersion ()
12870{
12871 return m_arm_isa;
12872}
12873
Greg Clayton64c84432011-01-21 22:02:52 +000012874bool
Greg Clayton107e53d2011-07-06 04:07:21 +000012875EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional)
Greg Clayton64c84432011-01-21 22:02:52 +000012876{
Greg Clayton888a7332011-04-26 04:39:08 +000012877 // If we are ignoring conditions, then always return true.
12878 // this allows us to iterate over disassembly code and still
12879 // emulate an instruction even if we don't have all the right
12880 // bits set in the CPSR register...
12881 if (m_ignore_conditions)
12882 return true;
Greg Clayton107e53d2011-07-06 04:07:21 +000012883
12884 if (is_conditional)
12885 *is_conditional = true;
Greg Clayton64c84432011-01-21 22:02:52 +000012886
Greg Clayton7bc39082011-03-24 23:53:38 +000012887 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000012888
12889 if (cond == UINT32_MAX)
12890 return false;
12891
12892 bool result = false;
12893 switch (UnsignedBits(cond, 3, 1))
12894 {
Caroline Tice080bf612011-04-05 18:46:00 +000012895 case 0:
12896 if (m_opcode_cpsr == 0)
Greg Clayton107e53d2011-07-06 04:07:21 +000012897 result = true;
12898 else
12899 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
Caroline Tice080bf612011-04-05 18:46:00 +000012900 break;
12901 case 1:
Greg Clayton107e53d2011-07-06 04:07:21 +000012902 if (m_opcode_cpsr == 0)
12903 result = true;
12904 else
12905 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
Caroline Tice080bf612011-04-05 18:46:00 +000012906 break;
12907 case 2:
Greg Clayton107e53d2011-07-06 04:07:21 +000012908 if (m_opcode_cpsr == 0)
12909 result = true;
12910 else
12911 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
Caroline Tice080bf612011-04-05 18:46:00 +000012912 break;
12913 case 3:
Greg Clayton107e53d2011-07-06 04:07:21 +000012914 if (m_opcode_cpsr == 0)
12915 result = true;
12916 else
12917 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
Caroline Tice080bf612011-04-05 18:46:00 +000012918 break;
12919 case 4:
Greg Clayton107e53d2011-07-06 04:07:21 +000012920 if (m_opcode_cpsr == 0)
12921 result = true;
12922 else
12923 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Caroline Tice080bf612011-04-05 18:46:00 +000012924 break;
Greg Clayton64c84432011-01-21 22:02:52 +000012925 case 5:
Greg Clayton107e53d2011-07-06 04:07:21 +000012926 if (m_opcode_cpsr == 0)
12927 result = true;
12928 else
Caroline Tice080bf612011-04-05 18:46:00 +000012929 {
Greg Claytonb3448432011-03-24 21:19:54 +000012930 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12931 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000012932 result = n == v;
12933 }
12934 break;
12935 case 6:
Greg Clayton107e53d2011-07-06 04:07:21 +000012936 if (m_opcode_cpsr == 0)
12937 result = true;
12938 else
Caroline Tice080bf612011-04-05 18:46:00 +000012939 {
Greg Claytonb3448432011-03-24 21:19:54 +000012940 bool n = (m_opcode_cpsr & MASK_CPSR_N);
12941 bool v = (m_opcode_cpsr & MASK_CPSR_V);
12942 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000012943 }
12944 break;
12945 case 7:
Greg Clayton107e53d2011-07-06 04:07:21 +000012946 // Always execute (cond == 0b1110, or the special 0b1111 which gives
12947 // opcodes different meanings, but always means execution happpens.
12948 if (is_conditional)
12949 *is_conditional = false;
Greg Clayton64c84432011-01-21 22:02:52 +000012950 result = true;
12951 break;
12952 }
12953
12954 if (cond & 1)
12955 result = !result;
12956 return result;
12957}
12958
Johnny Chen9ee056b2011-02-08 00:06:35 +000012959uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000012960EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012961{
Greg Claytonb3448432011-03-24 21:19:54 +000012962 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000012963 {
12964 default:
12965 case eModeInvalid:
12966 break;
12967
12968 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000012969 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000012970
12971 case eModeThumb:
12972 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
12973 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000012974 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012975 const uint32_t byte_size = m_opcode.GetByteSize();
12976 if (byte_size == 2)
12977 {
12978 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
12979 return Bits32(opcode, 11, 7);
12980 }
Johnny Chen6dc5a1a2011-06-02 23:19:06 +000012981 else if (byte_size == 4)
Greg Clayton7bc39082011-03-24 23:53:38 +000012982 {
Greg Clayton7bc39082011-03-24 23:53:38 +000012983 if (Bits32(opcode, 31, 27) == 0x1e &&
12984 Bits32(opcode, 15, 14) == 0x02 &&
12985 Bits32(opcode, 12, 12) == 0x00 &&
12986 Bits32(opcode, 25, 22) <= 0x0d)
12987 {
12988 return Bits32(opcode, 25, 22);
12989 }
12990 }
Johnny Chen6dc5a1a2011-06-02 23:19:06 +000012991 else
12992 // We have an invalid thumb instruction, let's bail out.
12993 break;
Greg Clayton7bc39082011-03-24 23:53:38 +000012994
12995 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000012996 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000012997 }
12998 return UINT32_MAX; // Return invalid value
12999}
13000
Johnny Chen9ee056b2011-02-08 00:06:35 +000013001bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000013002EmulateInstructionARM::InITBlock()
13003{
13004 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13005}
13006
13007bool
13008EmulateInstructionARM::LastInITBlock()
13009{
13010 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13011}
13012
Caroline Ticeb27771d2011-03-03 22:37:46 +000013013bool
13014EmulateInstructionARM::BadMode (uint32_t mode)
13015{
13016
13017 switch (mode)
13018 {
13019 case 16: return false; // '10000'
13020 case 17: return false; // '10001'
13021 case 18: return false; // '10010'
13022 case 19: return false; // '10011'
13023 case 22: return false; // '10110'
13024 case 23: return false; // '10111'
13025 case 27: return false; // '11011'
13026 case 31: return false; // '11111'
13027 default: return true;
13028 }
13029 return true;
13030}
13031
13032bool
13033EmulateInstructionARM::CurrentModeIsPrivileged ()
13034{
Greg Claytonb3448432011-03-24 21:19:54 +000013035 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000013036
13037 if (BadMode (mode))
13038 return false;
13039
13040 if (mode == 16)
Greg Clayton888a7332011-04-26 04:39:08 +000013041 return false;
Caroline Ticeb27771d2011-03-03 22:37:46 +000013042
13043 return true;
13044}
13045
13046void
13047EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
13048{
13049 bool privileged = CurrentModeIsPrivileged();
13050
13051 uint32_t tmp_cpsr = 0;
13052
Greg Claytonb3448432011-03-24 21:19:54 +000013053 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000013054
13055 if (BitIsSet (bytemask, 3))
13056 {
13057 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
13058 if (affect_execstate)
13059 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
13060 }
13061
13062 if (BitIsSet (bytemask, 2))
13063 {
13064 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
13065 }
13066
13067 if (BitIsSet (bytemask, 1))
13068 {
13069 if (affect_execstate)
13070 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
13071 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
13072 if (privileged)
13073 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
13074 }
13075
13076 if (BitIsSet (bytemask, 0))
13077 {
13078 if (privileged)
13079 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
13080 if (affect_execstate)
13081 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
13082 if (privileged)
13083 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
13084 }
13085
Greg Claytonb3448432011-03-24 21:19:54 +000013086 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000013087}
13088
13089
Johnny Chen098ae2d2011-02-12 00:50:05 +000013090bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000013091EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
13092{
13093 addr_t target;
13094
Johnny Chenee9b1f72011-02-09 01:00:31 +000013095 // Check the current instruction set.
13096 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013097 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013098 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000013099 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013100
Johnny Chen9ee056b2011-02-08 00:06:35 +000013101 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013102 return false;
13103
13104 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013105}
13106
13107// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
13108bool
Johnny Chen668b4512011-02-15 21:08:58 +000013109EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000013110{
13111 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000013112 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
13113 // we want to record it and issue a WriteRegister callback so the clients
13114 // can track the mode changes accordingly.
13115 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013116
13117 if (BitIsSet(addr, 0))
13118 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013119 if (CurrentInstrSet() != eModeThumb)
13120 {
13121 SelectInstrSet(eModeThumb);
13122 cpsr_changed = true;
13123 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013124 target = addr & 0xfffffffe;
Greg Claytonc07d4512011-04-26 23:48:45 +000013125 context.SetISA (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013126 }
13127 else if (BitIsClear(addr, 1))
13128 {
Johnny Chen0f309db2011-02-09 19:11:32 +000013129 if (CurrentInstrSet() != eModeARM)
13130 {
13131 SelectInstrSet(eModeARM);
13132 cpsr_changed = true;
13133 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013134 target = addr & 0xfffffffc;
Greg Claytonc07d4512011-04-26 23:48:45 +000013135 context.SetISA (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000013136 }
13137 else
13138 return false; // address<1:0> == '10' => UNPREDICTABLE
13139
Johnny Chen0f309db2011-02-09 19:11:32 +000013140 if (cpsr_changed)
13141 {
Johnny Chen558133b2011-02-09 23:59:17 +000013142 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000013143 return false;
13144 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000013145 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000013146 return false;
13147
13148 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000013149}
Greg Clayton64c84432011-01-21 22:02:52 +000013150
Johnny Chenee9b1f72011-02-09 01:00:31 +000013151// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
13152bool
Johnny Chen668b4512011-02-15 21:08:58 +000013153EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000013154{
13155 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000013156 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000013157 else
13158 return BranchWritePC((const Context)context, addr);
13159}
13160
Johnny Chen26863dc2011-02-09 23:43:29 +000013161// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
13162bool
Johnny Chen668b4512011-02-15 21:08:58 +000013163EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000013164{
13165 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000013166 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000013167 else
13168 return BranchWritePC((const Context)context, addr);
13169}
13170
Johnny Chenee9b1f72011-02-09 01:00:31 +000013171EmulateInstructionARM::Mode
13172EmulateInstructionARM::CurrentInstrSet ()
13173{
Greg Claytonb3448432011-03-24 21:19:54 +000013174 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013175}
13176
Greg Claytonb3448432011-03-24 21:19:54 +000013177// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000013178// ReadInstruction() is performed. This function has a side effect of updating
13179// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000013180bool
13181EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
13182{
Greg Claytonb3448432011-03-24 21:19:54 +000013183 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013184 switch (arm_or_thumb)
13185 {
13186 default:
13187 return false;
13188 eModeARM:
13189 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013190 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013191 break;
13192 eModeThumb:
13193 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000013194 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000013195 break;
13196 }
13197 return true;
13198}
13199
Johnny Chenef21b592011-02-10 01:52:38 +000013200// This function returns TRUE if the processor currently provides support for
13201// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
13202// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
13203bool
13204EmulateInstructionARM::UnalignedSupport()
13205{
13206 return (ArchVersion() >= ARMv7);
13207}
13208
Johnny Chenbf6ad172011-02-11 01:29:53 +000013209// The main addition and subtraction instructions can produce status information
13210// about both unsigned carry and signed overflow conditions. This status
13211// information can be used to synthesize multi-word additions and subtractions.
13212EmulateInstructionARM::AddWithCarryResult
13213EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
13214{
13215 uint32_t result;
13216 uint8_t carry_out;
13217 uint8_t overflow;
13218
13219 uint64_t unsigned_sum = x + y + carry_in;
13220 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
13221
13222 result = UnsignedBits(unsigned_sum, 31, 0);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013223// carry_out = (result == unsigned_sum ? 0 : 1);
Johnny Chenbf6ad172011-02-11 01:29:53 +000013224 overflow = ((int32_t)result == signed_sum ? 0 : 1);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013225
13226 if (carry_in)
Caroline Tice523c5542011-04-13 00:42:12 +000013227 carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013228 else
13229 carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
Johnny Chenbf6ad172011-02-11 01:29:53 +000013230
13231 AddWithCarryResult res = { result, carry_out, overflow };
13232 return res;
13233}
13234
Johnny Chen157b9592011-02-18 21:13:05 +000013235uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000013236EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000013237{
Johnny Chene39f22d2011-02-19 01:36:13 +000013238 uint32_t reg_kind, reg_num;
13239 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000013240 {
Johnny Chene39f22d2011-02-19 01:36:13 +000013241 case SP_REG:
13242 reg_kind = eRegisterKindGeneric;
13243 reg_num = LLDB_REGNUM_GENERIC_SP;
13244 break;
13245 case LR_REG:
13246 reg_kind = eRegisterKindGeneric;
13247 reg_num = LLDB_REGNUM_GENERIC_RA;
13248 break;
13249 case PC_REG:
13250 reg_kind = eRegisterKindGeneric;
13251 reg_num = LLDB_REGNUM_GENERIC_PC;
13252 break;
13253 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000013254 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000013255 {
13256 reg_kind = eRegisterKindDWARF;
13257 reg_num = dwarf_r0 + num;
13258 }
Johnny Chen157b9592011-02-18 21:13:05 +000013259 else
Johnny Chene39f22d2011-02-19 01:36:13 +000013260 {
Greg Claytone1f47bb2011-06-02 22:23:35 +000013261 //assert(0 && "Invalid register number");
Johnny Chene39f22d2011-02-19 01:36:13 +000013262 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000013263 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000013264 }
13265 break;
Johnny Chen157b9592011-02-18 21:13:05 +000013266 }
Johnny Chene39f22d2011-02-19 01:36:13 +000013267
13268 // Read our register.
13269 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
13270
13271 // When executing an ARM instruction , PC reads as the address of the current
13272 // instruction plus 8.
13273 // When executing a Thumb instruction , PC reads as the address of the current
13274 // instruction plus 4.
13275 if (num == 15)
13276 {
13277 if (CurrentInstrSet() == eModeARM)
13278 val += 8;
13279 else
13280 val += 4;
13281 }
Johnny Chen157b9592011-02-18 21:13:05 +000013282
13283 return val;
13284}
13285
Johnny Chenca67d1c2011-02-17 01:35:27 +000013286// Write the result to the ARM core register Rd, and optionally update the
13287// condition flags based on the result.
13288//
13289// This helper method tries to encapsulate the following pseudocode from the
13290// ARM Architecture Reference Manual:
13291//
13292// if d == 15 then // Can only occur for encoding A1
13293// ALUWritePC(result); // setflags is always FALSE here
13294// else
13295// R[d] = result;
13296// if setflags then
13297// APSR.N = result<31>;
13298// APSR.Z = IsZeroBit(result);
13299// APSR.C = carry;
13300// // APSR.V unchanged
13301//
13302// In the above case, the API client does not pass in the overflow arg, which
13303// defaults to ~0u.
13304bool
Johnny Chen10530c22011-02-17 22:37:12 +000013305EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
13306 const uint32_t result,
13307 const uint32_t Rd,
13308 bool setflags,
13309 const uint32_t carry,
13310 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000013311{
13312 if (Rd == 15)
13313 {
13314 if (!ALUWritePC (context, result))
13315 return false;
13316 }
13317 else
13318 {
Johnny Chena695f952011-02-23 21:24:25 +000013319 uint32_t reg_kind, reg_num;
13320 switch (Rd)
13321 {
13322 case SP_REG:
13323 reg_kind = eRegisterKindGeneric;
13324 reg_num = LLDB_REGNUM_GENERIC_SP;
13325 break;
13326 case LR_REG:
13327 reg_kind = eRegisterKindGeneric;
13328 reg_num = LLDB_REGNUM_GENERIC_RA;
13329 break;
13330 default:
13331 reg_kind = eRegisterKindDWARF;
13332 reg_num = dwarf_r0 + Rd;
13333 }
13334 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000013335 return false;
13336 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000013337 return WriteFlags (context, result, carry, overflow);
13338 }
13339 return true;
13340}
13341
13342// This helper method tries to encapsulate the following pseudocode from the
13343// ARM Architecture Reference Manual:
13344//
13345// APSR.N = result<31>;
13346// APSR.Z = IsZeroBit(result);
13347// APSR.C = carry;
13348// APSR.V = overflow
13349//
13350// Default arguments can be specified for carry and overflow parameters, which means
13351// not to update the respective flags.
13352bool
13353EmulateInstructionARM::WriteFlags (Context &context,
13354 const uint32_t result,
13355 const uint32_t carry,
13356 const uint32_t overflow)
13357{
Greg Claytonb3448432011-03-24 21:19:54 +000013358 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000013359 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
13360 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000013361 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013362 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000013363 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000013364 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000013365 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000013366 {
13367 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
13368 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000013369 }
13370 return true;
13371}
13372
Greg Clayton64c84432011-01-21 22:02:52 +000013373bool
Greg Clayton888a7332011-04-26 04:39:08 +000013374EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
Greg Clayton64c84432011-01-21 22:02:52 +000013375{
Johnny Chenc315f862011-02-05 00:46:10 +000013376 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000013377 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000013378 m_it_session.ITAdvance();
13379
Greg Clayton888a7332011-04-26 04:39:08 +000013380 ARMOpcode *opcode_data = NULL;
Caroline Tice080bf612011-04-05 18:46:00 +000013381
13382 if (m_opcode_mode == eModeThumb)
Greg Clayton888a7332011-04-26 04:39:08 +000013383 opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
Caroline Tice080bf612011-04-05 18:46:00 +000013384 else if (m_opcode_mode == eModeARM)
Greg Clayton888a7332011-04-26 04:39:08 +000013385 opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
13386
13387 if (opcode_data == NULL)
Caroline Tice080bf612011-04-05 18:46:00 +000013388 return false;
Caroline Tice080bf612011-04-05 18:46:00 +000013389
Greg Clayton888a7332011-04-26 04:39:08 +000013390 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
13391 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
Caroline Tice0fe5a532011-04-08 23:33:06 +000013392
Greg Clayton888a7332011-04-26 04:39:08 +000013393 bool success = false;
13394 if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
Caroline Tice0fe5a532011-04-08 23:33:06 +000013395 {
Greg Clayton888a7332011-04-26 04:39:08 +000013396 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF,
Greg Clayton061b79d2011-05-09 20:18:18 +000013397 dwarf_cpsr,
13398 0,
13399 &success);
Caroline Tice0fe5a532011-04-08 23:33:06 +000013400 }
13401
Greg Clayton888a7332011-04-26 04:39:08 +000013402 // Only return false if we are unable to read the CPSR if we care about conditions
13403 if (success == false && m_ignore_conditions == false)
13404 return false;
13405
13406 uint32_t orig_pc_value = 0;
13407 if (auto_advance_pc)
13408 {
13409 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13410 if (!success)
13411 return false;
13412 }
13413
13414 // Call the Emulate... function.
13415 success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);
13416 if (!success)
13417 return false;
13418
13419 if (auto_advance_pc)
13420 {
13421 uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
13422 if (!success)
13423 return false;
13424
13425 if (auto_advance_pc && (after_pc_value == orig_pc_value))
13426 {
13427 if (opcode_data->size == eSize32)
13428 after_pc_value += 4;
13429 else if (opcode_data->size == eSize16)
13430 after_pc_value += 2;
13431
13432 EmulateInstruction::Context context;
13433 context.type = eContextAdvancePC;
13434 context.SetNoArgs();
13435 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
13436 return false;
13437
13438 }
13439 }
Caroline Tice0fe5a532011-04-08 23:33:06 +000013440 return true;
Greg Clayton64c84432011-01-21 22:02:52 +000013441}
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013442
13443bool
Caroline Ticedfb2e202011-04-22 05:08:45 +000013444EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013445{
Caroline Ticedfb2e202011-04-22 05:08:45 +000013446 if (!test_data)
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013447 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013448 out_stream->Printf ("TestEmulation: Missing test data.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013449 return false;
13450 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013451
13452 static ConstString opcode_key ("opcode");
13453 static ConstString before_key ("before_state");
13454 static ConstString after_key ("after_state");
13455
13456 OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013457
13458 uint32_t test_opcode;
Caroline Ticedfb2e202011-04-22 05:08:45 +000013459 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013460 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013461 out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013462 return false;
13463 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013464 test_opcode = value_sp->GetUInt64Value ();
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013465
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013466 if (arch.GetTriple().getArch() == llvm::Triple::arm)
13467 {
13468 m_opcode_mode = eModeARM;
13469 m_opcode.SetOpcode32 (test_opcode);
13470 }
13471 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
13472 {
13473 m_opcode_mode = eModeThumb;
13474 if (test_opcode < 0x10000)
13475 m_opcode.SetOpcode16 (test_opcode);
13476 else
13477 m_opcode.SetOpcode32 (test_opcode);
13478
13479 }
13480 else
13481 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013482 out_stream->Printf ("TestEmulation: Invalid arch.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013483 return false;
13484 }
13485
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013486 EmulationStateARM before_state;
13487 EmulationStateARM after_state;
13488
Caroline Ticedfb2e202011-04-22 05:08:45 +000013489 value_sp = test_data->GetValueForKey (before_key);
13490 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013491 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013492 out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013493 return false;
13494 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013495
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013496 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013497 if (!before_state.LoadStateFromDictionary (state_dictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013498 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013499 out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013500 return false;
13501 }
13502
Caroline Ticedfb2e202011-04-22 05:08:45 +000013503 value_sp = test_data->GetValueForKey (after_key);
13504 if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013505 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013506 out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013507 return false;
13508 }
Caroline Ticedfb2e202011-04-22 05:08:45 +000013509
Greg Clayton57b3c6b2011-04-27 22:04:39 +000013510 state_dictionary = value_sp->GetAsDictionary ();
Caroline Ticedfb2e202011-04-22 05:08:45 +000013511 if (!after_state.LoadStateFromDictionary (state_dictionary))
13512 {
13513 out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
13514 return false;
13515 }
13516
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013517 SetBaton ((void *) &before_state);
13518 SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
13519 &EmulationStateARM::WritePseudoMemory,
13520 &EmulationStateARM::ReadPseudoRegister,
13521 &EmulationStateARM::WritePseudoRegister);
13522
Greg Clayton888a7332011-04-26 04:39:08 +000013523 bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013524 if (!success)
13525 {
Caroline Ticedfb2e202011-04-22 05:08:45 +000013526 out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n");
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013527 return false;
13528 }
13529
13530 success = before_state.CompareState (after_state);
Caroline Ticedfb2e202011-04-22 05:08:45 +000013531 if (!success)
13532 out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n");
13533
Caroline Tice6b8d3b52011-04-19 23:30:03 +000013534 return success;
13535}
Greg Claytonc07d4512011-04-26 23:48:45 +000013536//
13537//
13538//const char *
13539//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
13540//{
13541// if (reg_kind == eRegisterKindGeneric)
13542// {
13543// switch (reg_num)
13544// {
13545// case LLDB_REGNUM_GENERIC_PC: return "pc";
13546// case LLDB_REGNUM_GENERIC_SP: return "sp";
13547// case LLDB_REGNUM_GENERIC_FP: return "fp";
13548// case LLDB_REGNUM_GENERIC_RA: return "lr";
13549// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
13550// default: return NULL;
13551// }
13552// }
13553// else if (reg_kind == eRegisterKindDWARF)
13554// {
13555// return GetARMDWARFRegisterName (reg_num);
13556// }
13557// return NULL;
13558//}
13559//
13560bool
13561EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
Greg Clayton888a7332011-04-26 04:39:08 +000013562{
Greg Clayton75906e42011-05-11 18:39:18 +000013563 unwind_plan.Clear();
Greg Claytonc07d4512011-04-26 23:48:45 +000013564 unwind_plan.SetRegisterKind (eRegisterKindDWARF);
13565
13566 UnwindPlan::Row row;
Greg Claytonc07d4512011-04-26 23:48:45 +000013567
13568 // Our previous Call Frame Address is the stack pointer
13569 row.SetCFARegister (dwarf_sp);
13570
13571 // Our previous PC is in the LR
Greg Clayton75906e42011-05-11 18:39:18 +000013572 row.SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
Greg Claytonc07d4512011-04-26 23:48:45 +000013573 unwind_plan.AppendRow (row);
13574
13575 // All other registers are the same.
13576
13577 unwind_plan.SetSourceName ("EmulateInstructionARM");
13578 return true;
Greg Clayton888a7332011-04-26 04:39:08 +000013579}
13580
Greg Claytonc07d4512011-04-26 23:48:45 +000013581
13582
13583