blob: a459de9278a2ea7deef961f30578ac43cb3f81dc [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"
Greg Clayton395fc332011-02-15 21:59:32 +000013#include "lldb/Core/ArchSpec.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000014#include "lldb/Core/ConstString.h"
15
Greg Claytonf29a08f2011-02-09 17:41:27 +000016#include "Plugins/Process/Utility/ARMDefines.h"
17#include "Plugins/Process/Utility/ARMUtils.h"
18#include "Utility/ARM_DWARF_Registers.h"
19
Johnny Chen9b8d7832011-02-02 01:13:56 +000020#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000021 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chene97c0d52011-02-18 19:32:20 +000026// Convenient macro definitions.
Johnny Chen24348842011-02-23 00:15:56 +000027#define APSR_C Bit32(m_inst_cpsr, CPSR_C_POS)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000029
Caroline Ticef55261f2011-02-18 22:24:22 +000030#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
31
Johnny Chen0e00af22011-02-10 19:40:42 +000032//----------------------------------------------------------------------
33//
34// ITSession implementation
35//
36//----------------------------------------------------------------------
37
Johnny Chen93070472011-02-04 23:02:47 +000038// A8.6.50
39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
40static unsigned short CountITSize(unsigned ITMask) {
41 // First count the trailing zeros of the IT mask.
42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
43 if (TZ > 3)
44 {
45 printf("Encoding error: IT Mask '0000'\n");
46 return 0;
47 }
48 return (4 - TZ);
49}
50
51// Init ITState. Note that at least one bit is always 1 in mask.
52bool ITSession::InitIT(unsigned short bits7_0)
53{
54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
55 if (ITCounter == 0)
56 return false;
57
58 // A8.6.50 IT
59 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
60 if (FirstCond == 0xF)
61 {
62 printf("Encoding error: IT FirstCond '1111'\n");
63 return false;
64 }
65 if (FirstCond == 0xE && ITCounter != 1)
66 {
67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
68 return false;
69 }
70
71 ITState = bits7_0;
72 return true;
73}
74
75// Update ITState if necessary.
76void ITSession::ITAdvance()
77{
78 assert(ITCounter);
79 --ITCounter;
80 if (ITCounter == 0)
81 ITState = 0;
82 else
83 {
84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
85 SetBits32(ITState, 4, 0, NewITState4_0);
86 }
87}
88
89// Return true if we're inside an IT Block.
90bool ITSession::InITBlock()
91{
92 return ITCounter != 0;
93}
94
Johnny Chenc315f862011-02-05 00:46:10 +000095// Return true if we're the last instruction inside an IT Block.
96bool ITSession::LastInITBlock()
97{
98 return ITCounter == 1;
99}
100
Johnny Chen93070472011-02-04 23:02:47 +0000101// Get condition bits for the current thumb instruction.
102uint32_t ITSession::GetCond()
103{
Johnny Chenc315f862011-02-05 00:46:10 +0000104 if (InITBlock())
105 return Bits32(ITState, 7, 4);
106 else
107 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000108}
109
Greg Clayton64c84432011-01-21 22:02:52 +0000110// ARM constants used during decoding
111#define REG_RD 0
112#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000113#define SP_REG 13
114#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define PC_REG 15
116#define PC_REGLIST_BIT 0x8000
117
Johnny Chen251af6a2011-01-21 22:47:25 +0000118#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000119#define ARMv4T (1u << 1)
120#define ARMv5T (1u << 2)
121#define ARMv5TE (1u << 3)
122#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMv6K (1u << 6)
125#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000126#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000127#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000128#define ARMvAll (0xffffffffu)
129
Johnny Chen9b8d7832011-02-02 01:13:56 +0000130#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
131#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000132#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000133#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000134#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000135
Johnny Chen0e00af22011-02-10 19:40:42 +0000136//----------------------------------------------------------------------
137//
138// EmulateInstructionARM implementation
139//
140//----------------------------------------------------------------------
141
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000142void
143EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000144{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000145}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000146
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000147void
148EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000149{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000150}
151
Caroline Ticefa172202011-02-11 22:49:54 +0000152// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
153bool
154EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
155{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000156 EmulateInstruction::Context context;
157 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
158 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000159
160 uint32_t random_data = rand ();
161 const uint32_t addr_byte_size = GetAddressByteSize();
162
Caroline Ticecc96eb52011-02-17 19:20:40 +0000163 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000164 return false;
165
166 return true;
167}
168
Caroline Tice713c2662011-02-11 17:59:55 +0000169// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
170bool
171EmulateInstructionARM::WriteBits32Unknown (int n)
172{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000173 EmulateInstruction::Context context;
174 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
175 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000176
Johnny Chen62ff6f52011-02-11 18:11:22 +0000177 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000178 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
179
180 if (!success)
181 return false;
182
183 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
184 return false;
185
186 return true;
187}
188
Johnny Chen08c25e82011-01-31 18:02:28 +0000189// Push Multiple Registers stores multiple registers to the stack, storing to
190// consecutive memory locations ending just below the address in SP, and updates
191// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000192bool
Johnny Chen9f687722011-02-18 00:02:28 +0000193EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000194{
195#if 0
196 // ARM pseudo code...
197 if (ConditionPassed())
198 {
199 EncodingSpecificOperations();
200 NullCheckIfThumbEE(13);
201 address = SP - 4*BitCount(registers);
202
203 for (i = 0 to 14)
204 {
205 if (registers<i> == ’1’)
206 {
207 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
208 MemA[address,4] = bits(32) UNKNOWN;
209 else
210 MemA[address,4] = R[i];
211 address = address + 4;
212 }
213 }
214
215 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
216 MemA[address,4] = PCStoreValue();
217
218 SP = SP - 4*BitCount(registers);
219 }
220#endif
221
222 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000224 if (!success)
225 return false;
226
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000227 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000228 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000229 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000230 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000231 if (!success)
232 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000233 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000234 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000235 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000236 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000237 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000238 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000239 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000240 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000241 // if BitCount(registers) < 1 then UNPREDICTABLE;
242 if (BitCount(registers) < 1)
243 return false;
244 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000245 case eEncodingT2:
246 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000247 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000248 // if BitCount(registers) < 2 then UNPREDICTABLE;
249 if (BitCount(registers) < 2)
250 return false;
251 break;
252 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000253 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000255 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000256 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000257 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000258 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000259 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000260 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000261 // Instead of return false, let's handle the following case as well,
262 // which amounts to pushing one reg onto the full descending stacks.
263 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000264 break;
265 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000266 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000267 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000268 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000269 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000270 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000271 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000272 default:
273 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000274 }
Johnny Chence1ca772011-01-25 01:13:00 +0000275 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000276 addr_t addr = sp - sp_offset;
277 uint32_t i;
278
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000279 EmulateInstruction::Context context;
280 context.type = EmulateInstruction::eContextPushRegisterOnStack;
281 Register dwarf_reg;
282 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000283 Register sp_reg;
284 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
Greg Clayton64c84432011-01-21 22:02:52 +0000285 for (i=0; i<15; ++i)
286 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000287 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000288 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000289 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000290 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000291 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000292 if (!success)
293 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000294 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000295 return false;
296 addr += addr_byte_size;
297 }
298 }
299
Johnny Chen7c1bf922011-02-08 23:49:37 +0000300 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000301 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000302 dwarf_reg.num = dwarf_pc;
303 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000304 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000305 if (!success)
306 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000307 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000308 return false;
309 }
310
311 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000312 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000313
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000314 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000315 return false;
316 }
317 return true;
318}
319
Johnny Chenef85e912011-01-31 23:07:40 +0000320// Pop Multiple Registers loads multiple registers from the stack, loading from
321// consecutive memory locations staring at the address in SP, and updates
322// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000323bool
Johnny Chen9f687722011-02-18 00:02:28 +0000324EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000325{
326#if 0
327 // ARM pseudo code...
328 if (ConditionPassed())
329 {
330 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
331 address = SP;
332 for i = 0 to 14
333 if registers<i> == ‘1’ then
334 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
335 if registers<15> == ‘1’ then
336 if UnalignedAllowed then
337 LoadWritePC(MemU[address,4]);
338 else
339 LoadWritePC(MemA[address,4]);
340 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
341 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
342 }
343#endif
344
345 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000347 if (!success)
348 return false;
349
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000350 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000351 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000352 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000353 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000354 if (!success)
355 return false;
356 uint32_t registers = 0;
357 uint32_t Rt; // the destination register
358 switch (encoding) {
359 case eEncodingT1:
360 registers = Bits32(opcode, 7, 0);
361 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000362 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000363 registers |= (1u << 15);
364 // if BitCount(registers) < 1 then UNPREDICTABLE;
365 if (BitCount(registers) < 1)
366 return false;
367 break;
368 case eEncodingT2:
369 // Ignore bit 13.
370 registers = Bits32(opcode, 15, 0) & ~0x2000;
371 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000372 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000373 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000374 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
375 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
376 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000377 break;
378 case eEncodingT3:
379 Rt = Bits32(opcode, 15, 12);
380 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000381 if (Rt == 13)
382 return false;
383 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000384 return false;
385 registers = (1u << Rt);
386 break;
387 case eEncodingA1:
388 registers = Bits32(opcode, 15, 0);
389 // Instead of return false, let's handle the following case as well,
390 // which amounts to popping one reg from the full descending stacks.
391 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
392
393 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000394 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000395 return false;
396 break;
397 case eEncodingA2:
398 Rt = Bits32(opcode, 15, 12);
399 // if t == 13 then UNPREDICTABLE;
400 if (Rt == dwarf_sp)
401 return false;
402 registers = (1u << Rt);
403 break;
404 default:
405 return false;
406 }
407 addr_t sp_offset = addr_byte_size * BitCount (registers);
408 addr_t addr = sp;
409 uint32_t i, data;
410
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000411 EmulateInstruction::Context context;
412 context.type = EmulateInstruction::eContextPopRegisterOffStack;
413 Register dwarf_reg;
414 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice8ce836d2011-03-16 22:46:55 +0000415 Register sp_reg;
416 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Johnny Chenef85e912011-01-31 23:07:40 +0000417 for (i=0; i<15; ++i)
418 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000419 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000420 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000421 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000422 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000423 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000424 if (!success)
425 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000426 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 return false;
428 addr += addr_byte_size;
429 }
430 }
431
Johnny Chen7c1bf922011-02-08 23:49:37 +0000432 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000433 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000434 dwarf_reg.num = dwarf_pc;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000435 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000436 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000437 if (!success)
438 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000439 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000440 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000441 return false;
442 addr += addr_byte_size;
443 }
444
445 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000446 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000447
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000448 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000449 return false;
450 }
451 return true;
452}
453
Johnny Chen5b442b72011-01-27 19:34:30 +0000454// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000455// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000456bool
Johnny Chen9f687722011-02-18 00:02:28 +0000457EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000458{
459#if 0
460 // ARM pseudo code...
461 if (ConditionPassed())
462 {
463 EncodingSpecificOperations();
464 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
465 if d == 15 then
466 ALUWritePC(result); // setflags is always FALSE here
467 else
468 R[d] = result;
469 if setflags then
470 APSR.N = result<31>;
471 APSR.Z = IsZeroBit(result);
472 APSR.C = carry;
473 APSR.V = overflow;
474 }
475#endif
476
477 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000478 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000479 if (!success)
480 return false;
481
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000482 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000483 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000484 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000485 if (!success)
486 return false;
487 uint32_t Rd; // the destination register
488 uint32_t imm32;
489 switch (encoding) {
490 case eEncodingT1:
491 Rd = 7;
492 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
493 break;
494 case eEncodingA1:
495 Rd = Bits32(opcode, 15, 12);
496 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
497 break;
498 default:
499 return false;
500 }
501 addr_t sp_offset = imm32;
502 addr_t addr = sp + sp_offset; // a pointer to the stack area
503
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000504 EmulateInstruction::Context context;
505 context.type = EmulateInstruction::eContextRegisterPlusOffset;
506 Register sp_reg;
507 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
508 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000509
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000510 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000511 return false;
512 }
513 return true;
514}
515
Johnny Chen2ccad832011-01-28 19:57:25 +0000516// Set r7 or ip to the current stack pointer.
517// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000518bool
Johnny Chen9f687722011-02-18 00:02:28 +0000519EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000520{
521#if 0
522 // ARM pseudo code...
523 if (ConditionPassed())
524 {
525 EncodingSpecificOperations();
526 result = R[m];
527 if d == 15 then
528 ALUWritePC(result); // setflags is always FALSE here
529 else
530 R[d] = result;
531 if setflags then
532 APSR.N = result<31>;
533 APSR.Z = IsZeroBit(result);
534 // APSR.C unchanged
535 // APSR.V unchanged
536 }
537#endif
538
539 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000540 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000541 //if (!success)
542 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000543
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000544 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000545 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000546 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000547 if (!success)
548 return false;
549 uint32_t Rd; // the destination register
550 switch (encoding) {
551 case eEncodingT1:
552 Rd = 7;
553 break;
554 case eEncodingA1:
555 Rd = 12;
556 break;
557 default:
558 return false;
559 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000560
561 EmulateInstruction::Context context;
562 context.type = EmulateInstruction::eContextRegisterPlusOffset;
563 Register sp_reg;
564 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
565 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000566
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000567 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000568 return false;
569 }
570 return true;
571}
572
Johnny Chen1c13b622011-01-29 00:11:15 +0000573// Move from high register (r8-r15) to low register (r0-r7).
574// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000575bool
Johnny Chen9f687722011-02-18 00:02:28 +0000576EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000577{
Johnny Chen9f687722011-02-18 00:02:28 +0000578 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000579}
580
581// Move from register to register.
582// MOV (register)
583bool
Johnny Chen9f687722011-02-18 00:02:28 +0000584EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000585{
Johnny Chen1c13b622011-01-29 00:11:15 +0000586#if 0
587 // ARM pseudo code...
588 if (ConditionPassed())
589 {
590 EncodingSpecificOperations();
591 result = R[m];
592 if d == 15 then
593 ALUWritePC(result); // setflags is always FALSE here
594 else
595 R[d] = result;
596 if setflags then
597 APSR.N = result<31>;
598 APSR.Z = IsZeroBit(result);
599 // APSR.C unchanged
600 // APSR.V unchanged
601 }
602#endif
603
604 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000605 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000606 if (!success)
607 return false;
608
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000609 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000610 {
611 uint32_t Rm; // the source register
612 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000613 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000614 switch (encoding) {
615 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000616 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000617 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000618 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000619 if (Rd == 15 && InITBlock() && !LastInITBlock())
620 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000621 break;
622 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000623 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000624 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000625 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000626 if (InITBlock())
627 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000628 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000629 case eEncodingT3:
630 Rd = Bits32(opcode, 11, 8);
631 Rm = Bits32(opcode, 3, 0);
632 setflags = BitIsSet(opcode, 20);
633 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
634 if (setflags && (BadReg(Rd) || BadReg(Rm)))
635 return false;
636 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
637 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
638 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000639 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000640 case eEncodingA1:
641 Rd = Bits32(opcode, 15, 12);
642 Rm = Bits32(opcode, 3, 0);
643 setflags = BitIsSet(opcode, 20);
644 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
645 // TODO: Emulate SUBS PC, LR and related instructions.
646 if (Rd == 15 && setflags)
647 return false;
648 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000649 default:
650 return false;
651 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000652 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000653 if (!success)
654 return false;
655
656 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000657 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000658 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000659 Register dwarf_reg;
660 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000661 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000662
Johnny Chen10530c22011-02-17 22:37:12 +0000663 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000664 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000665 }
666 return true;
667}
668
Johnny Chen357c30f2011-02-14 22:04:25 +0000669// Move (immediate) writes an immediate value to the destination register. It
670// can optionally update the condition flags based on the value.
671// MOV (immediate)
672bool
Johnny Chen9f687722011-02-18 00:02:28 +0000673EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000674{
675#if 0
676 // ARM pseudo code...
677 if (ConditionPassed())
678 {
679 EncodingSpecificOperations();
680 result = imm32;
681 if d == 15 then // Can only occur for ARM encoding
682 ALUWritePC(result); // setflags is always FALSE here
683 else
684 R[d] = result;
685 if setflags then
686 APSR.N = result<31>;
687 APSR.Z = IsZeroBit(result);
688 APSR.C = carry;
689 // APSR.V unchanged
690 }
691#endif
692 bool success = false;
693 const uint32_t opcode = OpcodeAsUnsigned (&success);
694 if (!success)
695 return false;
696
697 if (ConditionPassed())
698 {
699 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000700 uint32_t imm32; // the immediate value to be written to Rd
701 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
702 bool setflags;
703 switch (encoding) {
704 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000705 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000706 setflags = !InITBlock();
707 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000708 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000709 break;
710 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000711 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000712 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000713 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000714 if (BadReg(Rd))
715 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000716 break;
717 default:
718 return false;
719 }
720 uint32_t result = imm32;
721
722 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000723 EmulateInstruction::Context context;
724 context.type = EmulateInstruction::eContextImmediate;
725 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000726
Johnny Chen10530c22011-02-17 22:37:12 +0000727 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000728 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000729 }
730 return true;
731}
732
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000733// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
734// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
735// unsigned values.
736//
737// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
738// limited to only a few forms of the instruction.
739bool
740EmulateInstructionARM::EmulateMUL (ARMEncoding encoding)
741{
742#if 0
743 if ConditionPassed() then
744 EncodingSpecificOperations();
745 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
746 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
747 result = operand1 * operand2;
748 R[d] = result<31:0>;
749 if setflags then
750 APSR.N = result<31>;
751 APSR.Z = IsZeroBit(result);
752 if ArchVersion() == 4 then
753 APSR.C = bit UNKNOWN;
754 // else APSR.C unchanged
755 // APSR.V always unchanged
756#endif
757
758 bool success = false;
759 const uint32_t opcode = OpcodeAsUnsigned (&success);
760 if (!success)
761 return false;
762
763 if (ConditionPassed())
764 {
765 uint32_t d;
766 uint32_t n;
767 uint32_t m;
768 bool setflags;
769
770 // EncodingSpecificOperations();
771 switch (encoding)
772 {
773 case eEncodingT1:
774 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
775 d = Bits32 (opcode, 2, 0);
776 n = Bits32 (opcode, 5, 3);
777 m = Bits32 (opcode, 2, 0);
778 setflags = !InITBlock();
779
780 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
781 if ((ArchVersion() < ARMv6) && (d == n))
782 return false;
783
784 break;
785
786 case eEncodingT2:
787 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
788 d = Bits32 (opcode, 11, 8);
789 n = Bits32 (opcode, 19, 16);
790 m = Bits32 (opcode, 3, 0);
791 setflags = false;
792
793 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
794 if (BadReg (d) || BadReg (n) || BadReg (m))
795 return false;
796
797 break;
798
799 case eEncodingA1:
800 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ’1’);
801 d = Bits32 (opcode, 19, 16);
802 n = Bits32 (opcode, 3, 0);
803 m = Bits32 (opcode, 11, 8);
804 setflags = BitIsSet (opcode, 20);
805
806 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
807 if ((d == 15) || (n == 15) || (m == 15))
808 return false;
809
810 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
811 if ((ArchVersion() < ARMv6) && (d == n))
812 return false;
813
814 break;
815
816 default:
817 return false;
818 }
819
820 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
821 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
822 if (!success)
823 return false;
824
825 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
826 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
827 if (!success)
828 return false;
829
830 // result = operand1 * operand2;
831 uint64_t result = operand1 * operand2;
832
833 // R[d] = result<31:0>;
834 Register op1_reg;
835 Register op2_reg;
836 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
837 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
838
839 EmulateInstruction::Context context;
840 context.type = eContextMultiplication;
841 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
842
843 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
844 return false;
845
846 // if setflags then
847 if (setflags)
848 {
849 // APSR.N = result<31>;
850 // APSR.Z = IsZeroBit(result);
851 m_new_inst_cpsr = m_inst_cpsr;
852 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
853 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
854 if (m_new_inst_cpsr != m_inst_cpsr)
855 {
856 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
857 return false;
858 }
859
860 // if ArchVersion() == 4 then
861 // APSR.C = bit UNKNOWN;
862 }
863 }
864 return true;
865}
866
Johnny Chend642a6a2011-02-22 01:01:03 +0000867// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
868// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000869bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000870EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000871{
872#if 0
873 // ARM pseudo code...
874 if (ConditionPassed())
875 {
876 EncodingSpecificOperations();
877 result = NOT(imm32);
878 if d == 15 then // Can only occur for ARM encoding
879 ALUWritePC(result); // setflags is always FALSE here
880 else
881 R[d] = result;
882 if setflags then
883 APSR.N = result<31>;
884 APSR.Z = IsZeroBit(result);
885 APSR.C = carry;
886 // APSR.V unchanged
887 }
888#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000889 bool success = false;
890 const uint32_t opcode = OpcodeAsUnsigned (&success);
891 if (!success)
892 return false;
893
894 if (ConditionPassed())
895 {
896 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000897 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
898 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000899 bool setflags;
900 switch (encoding) {
901 case eEncodingT1:
902 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000903 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000904 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000905 break;
906 case eEncodingA1:
907 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000908 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000909 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
910 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
911 // TODO: Emulate SUBS PC, LR and related instructions.
912 if (Rd == 15 && setflags)
913 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000914 break;
915 default:
916 return false;
917 }
918 uint32_t result = ~imm32;
919
920 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000921 EmulateInstruction::Context context;
922 context.type = EmulateInstruction::eContextImmediate;
923 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000924
Johnny Chen10530c22011-02-17 22:37:12 +0000925 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000926 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000927 }
928 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000929}
930
Johnny Chend642a6a2011-02-22 01:01:03 +0000931// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
932// It can optionally update the condition flags based on the result.
933bool
934EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
935{
936#if 0
937 // ARM pseudo code...
938 if (ConditionPassed())
939 {
940 EncodingSpecificOperations();
941 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
942 result = NOT(shifted);
943 if d == 15 then // Can only occur for ARM encoding
944 ALUWritePC(result); // setflags is always FALSE here
945 else
946 R[d] = result;
947 if setflags then
948 APSR.N = result<31>;
949 APSR.Z = IsZeroBit(result);
950 APSR.C = carry;
951 // APSR.V unchanged
952 }
953#endif
954
955 bool success = false;
956 const uint32_t opcode = OpcodeAsUnsigned (&success);
957 if (!success)
958 return false;
959
960 if (ConditionPassed())
961 {
962 uint32_t Rm; // the source register
963 uint32_t Rd; // the destination register
964 ARM_ShifterType shift_t;
965 uint32_t shift_n; // the shift applied to the value read from Rm
966 bool setflags;
967 uint32_t carry; // the carry bit after the shift operation
968 switch (encoding) {
969 case eEncodingT1:
970 Rd = Bits32(opcode, 2, 0);
971 Rm = Bits32(opcode, 5, 3);
972 setflags = !InITBlock();
973 shift_t = SRType_LSL;
974 shift_n = 0;
975 if (InITBlock())
976 return false;
977 break;
978 case eEncodingT2:
979 Rd = Bits32(opcode, 11, 8);
980 Rm = Bits32(opcode, 3, 0);
981 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000982 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000983 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000984 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000985 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000986 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000987 case eEncodingA1:
988 Rd = Bits32(opcode, 15, 12);
989 Rm = Bits32(opcode, 3, 0);
990 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000991 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000992 break;
993 default:
994 return false;
995 }
996 uint32_t value = ReadCoreReg(Rm, &success);
997 if (!success)
998 return false;
999
1000 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1001 uint32_t result = ~shifted;
1002
1003 // The context specifies that an immediate is to be moved into Rd.
1004 EmulateInstruction::Context context;
1005 context.type = EmulateInstruction::eContextImmediate;
1006 context.SetNoArgs ();
1007
1008 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1009 return false;
1010 }
1011 return true;
1012}
1013
Johnny Chen788e0552011-01-27 22:52:23 +00001014// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1015// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001016bool
Johnny Chenc9de9102011-02-11 19:12:30 +00001017EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001018{
1019#if 0
1020 // ARM pseudo code...
1021 if (ConditionPassed())
1022 {
1023 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1024 base = Align(PC,4);
1025 address = if add then (base + imm32) else (base - imm32);
1026 data = MemU[address,4];
1027 if t == 15 then
1028 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
1029 elsif UnalignedSupport() || address<1:0> = ‘00’ then
1030 R[t] = data;
1031 else // Can only apply before ARMv7
1032 if CurrentInstrSet() == InstrSet_ARM then
1033 R[t] = ROR(data, 8*UInt(address<1:0>));
1034 else
1035 R[t] = bits(32) UNKNOWN;
1036 }
1037#endif
1038
1039 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001040 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +00001041 if (!success)
1042 return false;
1043
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001044 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +00001045 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001046 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001047 if (!success)
1048 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001049
1050 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001051 EmulateInstruction::Context context;
1052 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1053 Register pc_reg;
1054 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1055 context.SetRegisterPlusOffset (pc_reg, 0);
1056
Johnny Chenc9de9102011-02-11 19:12:30 +00001057 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001058 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001059 bool add; // +imm32 or -imm32?
1060 addr_t base; // the base address
1061 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001062 uint32_t data; // the literal data value from the PC relative load
1063 switch (encoding) {
1064 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001065 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001066 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001067 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001068 break;
1069 case eEncodingT2:
1070 Rt = Bits32(opcode, 15, 12);
1071 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1072 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001073 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001074 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001075 break;
1076 default:
1077 return false;
1078 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001079
Johnny Chene39f22d2011-02-19 01:36:13 +00001080 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001081 if (add)
1082 address = base + imm32;
1083 else
1084 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001085
1086 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001087 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001088 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001089 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001090
1091 if (Rt == 15)
1092 {
1093 if (Bits32(address, 1, 0) == 0)
1094 {
1095 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001096 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001097 return false;
1098 }
1099 else
1100 return false;
1101 }
1102 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1103 {
1104 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1105 return false;
1106 }
1107 else // We don't handle ARM for now.
1108 return false;
1109
1110 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +00001111 return false;
1112 }
1113 return true;
1114}
1115
Johnny Chen5b442b72011-01-27 19:34:30 +00001116// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001117// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001118bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001119EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001120{
1121#if 0
1122 // ARM pseudo code...
1123 if (ConditionPassed())
1124 {
1125 EncodingSpecificOperations();
1126 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
1127 if d == 15 then // Can only occur for ARM encoding
1128 ALUWritePC(result); // setflags is always FALSE here
1129 else
1130 R[d] = result;
1131 if setflags then
1132 APSR.N = result<31>;
1133 APSR.Z = IsZeroBit(result);
1134 APSR.C = carry;
1135 APSR.V = overflow;
1136 }
1137#endif
1138
1139 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001140 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001141 if (!success)
1142 return false;
1143
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001144 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +00001145 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001146 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001147 if (!success)
1148 return false;
1149 uint32_t imm32; // the immediate operand
1150 switch (encoding) {
1151 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001152 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001153 break;
1154 default:
1155 return false;
1156 }
1157 addr_t sp_offset = imm32;
1158 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1159
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001160 EmulateInstruction::Context context;
1161 context.type = EmulateInstruction::eContextAdjustStackPointer;
1162 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001163
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001164 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001165 return false;
1166 }
1167 return true;
1168}
1169
1170// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001171// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001172bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001173EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001174{
1175#if 0
1176 // ARM pseudo code...
1177 if (ConditionPassed())
1178 {
1179 EncodingSpecificOperations();
1180 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1181 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1182 if d == 15 then
1183 ALUWritePC(result); // setflags is always FALSE here
1184 else
1185 R[d] = result;
1186 if setflags then
1187 APSR.N = result<31>;
1188 APSR.Z = IsZeroBit(result);
1189 APSR.C = carry;
1190 APSR.V = overflow;
1191 }
1192#endif
1193
1194 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001195 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001196 if (!success)
1197 return false;
1198
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001199 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001200 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001201 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001202 if (!success)
1203 return false;
1204 uint32_t Rm; // the second operand
1205 switch (encoding) {
1206 case eEncodingT2:
1207 Rm = Bits32(opcode, 6, 3);
1208 break;
1209 default:
1210 return false;
1211 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001212 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001213 if (!success)
1214 return false;
1215
1216 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1217
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001218 EmulateInstruction::Context context;
1219 context.type = EmulateInstruction::eContextAdjustStackPointer;
1220 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001221
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001222 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001223 return false;
1224 }
1225 return true;
1226}
1227
Johnny Chen9b8d7832011-02-02 01:13:56 +00001228// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1229// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1230// from Thumb to ARM.
1231// BLX (immediate)
1232bool
1233EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1234{
1235#if 0
1236 // ARM pseudo code...
1237 if (ConditionPassed())
1238 {
1239 EncodingSpecificOperations();
1240 if CurrentInstrSet() == InstrSet_ARM then
1241 LR = PC - 4;
1242 else
1243 LR = PC<31:1> : '1';
1244 if targetInstrSet == InstrSet_ARM then
1245 targetAddress = Align(PC,4) + imm32;
1246 else
1247 targetAddress = PC + imm32;
1248 SelectInstrSet(targetInstrSet);
1249 BranchWritePC(targetAddress);
1250 }
1251#endif
1252
1253 bool success = false;
1254 const uint32_t opcode = OpcodeAsUnsigned (&success);
1255 if (!success)
1256 return false;
1257
1258 if (ConditionPassed())
1259 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001260 EmulateInstruction::Context context;
1261 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001262 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001263 if (!success)
1264 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001265 addr_t lr; // next instruction address
1266 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001267 int32_t imm32; // PC-relative offset
1268 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001269 case eEncodingT1:
1270 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001271 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001272 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001273 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001274 uint32_t J1 = Bit32(opcode, 13);
1275 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001276 uint32_t imm11 = Bits32(opcode, 10, 0);
1277 uint32_t I1 = !(J1 ^ S);
1278 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001279 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001280 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001281 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001282 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001283 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001284 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001285 break;
1286 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001287 case eEncodingT2:
1288 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001289 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001290 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001291 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001292 uint32_t J1 = Bit32(opcode, 13);
1293 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001294 uint32_t imm10L = Bits32(opcode, 10, 1);
1295 uint32_t I1 = !(J1 ^ S);
1296 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001297 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001298 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001299 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001300 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001301 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001302 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001303 break;
1304 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001305 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001306 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001307 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001308 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001309 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001310 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001311 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001312 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001313 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001314 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001315 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001316 break;
1317 default:
1318 return false;
1319 }
1320 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1321 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001322 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001323 return false;
1324 }
1325 return true;
1326}
1327
1328// Branch with Link and Exchange (register) calls a subroutine at an address and
1329// instruction set specified by a register.
1330// BLX (register)
1331bool
1332EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1333{
1334#if 0
1335 // ARM pseudo code...
1336 if (ConditionPassed())
1337 {
1338 EncodingSpecificOperations();
1339 target = R[m];
1340 if CurrentInstrSet() == InstrSet_ARM then
1341 next_instr_addr = PC - 4;
1342 LR = next_instr_addr;
1343 else
1344 next_instr_addr = PC - 2;
1345 LR = next_instr_addr<31:1> : ‘1’;
1346 BXWritePC(target);
1347 }
1348#endif
1349
1350 bool success = false;
1351 const uint32_t opcode = OpcodeAsUnsigned (&success);
1352 if (!success)
1353 return false;
1354
1355 if (ConditionPassed())
1356 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001357 EmulateInstruction::Context context;
1358 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001359 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001360 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001361 if (!success)
1362 return false;
1363 uint32_t Rm; // the register with the target address
1364 switch (encoding) {
1365 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001366 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001367 Rm = Bits32(opcode, 6, 3);
1368 // if m == 15 then UNPREDICTABLE;
1369 if (Rm == 15)
1370 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001371 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001372 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001373 break;
1374 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001375 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001376 Rm = Bits32(opcode, 3, 0);
1377 // if m == 15 then UNPREDICTABLE;
1378 if (Rm == 15)
1379 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001380 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001381 default:
1382 return false;
1383 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001384 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001385 if (!success)
1386 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001387 Register dwarf_reg;
1388 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1389 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001390 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1391 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001392 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001393 return false;
1394 }
1395 return true;
1396}
1397
Johnny Chenab3b3512011-02-12 00:10:51 +00001398// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001399bool
1400EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1401{
1402#if 0
1403 // ARM pseudo code...
1404 if (ConditionPassed())
1405 {
1406 EncodingSpecificOperations();
1407 BXWritePC(R[m]);
1408 }
1409#endif
1410
1411 bool success = false;
1412 const uint32_t opcode = OpcodeAsUnsigned (&success);
1413 if (!success)
1414 return false;
1415
1416 if (ConditionPassed())
1417 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001418 EmulateInstruction::Context context;
1419 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001420 uint32_t Rm; // the register with the target address
1421 switch (encoding) {
1422 case eEncodingT1:
1423 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001424 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001425 return false;
1426 break;
1427 case eEncodingA1:
1428 Rm = Bits32(opcode, 3, 0);
1429 break;
1430 default:
1431 return false;
1432 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001433 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001434 if (!success)
1435 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001436
1437 Register dwarf_reg;
1438 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001439 context.SetRegister (dwarf_reg);
1440 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001441 return false;
1442 }
1443 return true;
1444}
1445
Johnny Chen59e6ab72011-02-24 21:01:20 +00001446// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1447// address and instruction set specified by a register as though it were a BX instruction.
1448//
1449// TODO: Emulate Jazelle architecture?
1450// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1451bool
1452EmulateInstructionARM::EmulateBXJRm (ARMEncoding encoding)
1453{
1454#if 0
1455 // ARM pseudo code...
1456 if (ConditionPassed())
1457 {
1458 EncodingSpecificOperations();
1459 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1460 BXWritePC(R[m]);
1461 else
1462 if JazelleAcceptsExecution() then
1463 SwitchToJazelleExecution();
1464 else
1465 SUBARCHITECTURE_DEFINED handler call;
1466 }
1467#endif
1468
1469 bool success = false;
1470 const uint32_t opcode = OpcodeAsUnsigned (&success);
1471 if (!success)
1472 return false;
1473
1474 if (ConditionPassed())
1475 {
1476 EmulateInstruction::Context context;
1477 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1478 uint32_t Rm; // the register with the target address
1479 switch (encoding) {
1480 case eEncodingT1:
1481 Rm = Bits32(opcode, 19, 16);
1482 if (BadReg(Rm))
1483 return false;
1484 if (InITBlock() && !LastInITBlock())
1485 return false;
1486 break;
1487 case eEncodingA1:
1488 Rm = Bits32(opcode, 3, 0);
1489 if (Rm == 15)
1490 return false;
1491 break;
1492 default:
1493 return false;
1494 }
1495 addr_t target = ReadCoreReg (Rm, &success);
1496 if (!success)
1497 return false;
1498
1499 Register dwarf_reg;
1500 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1501 context.SetRegister (dwarf_reg);
1502 if (!BXWritePC(context, target))
1503 return false;
1504 }
1505 return true;
1506}
1507
Johnny Chen0d0148e2011-01-28 02:26:08 +00001508// Set r7 to point to some ip offset.
1509// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001510bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001511EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001512{
1513#if 0
1514 // ARM pseudo code...
1515 if (ConditionPassed())
1516 {
1517 EncodingSpecificOperations();
1518 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1519 if d == 15 then // Can only occur for ARM encoding
1520 ALUWritePC(result); // setflags is always FALSE here
1521 else
1522 R[d] = result;
1523 if setflags then
1524 APSR.N = result<31>;
1525 APSR.Z = IsZeroBit(result);
1526 APSR.C = carry;
1527 APSR.V = overflow;
1528 }
1529#endif
1530
1531 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001532 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001533 if (!success)
1534 return false;
1535
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001536 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001537 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001538 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001539 if (!success)
1540 return false;
1541 uint32_t imm32;
1542 switch (encoding) {
1543 case eEncodingA1:
1544 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1545 break;
1546 default:
1547 return false;
1548 }
1549 addr_t ip_offset = imm32;
1550 addr_t addr = ip - ip_offset; // the adjusted ip value
1551
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001552 EmulateInstruction::Context context;
1553 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1554 Register dwarf_reg;
1555 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1556 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001557
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001558 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001559 return false;
1560 }
1561 return true;
1562}
1563
1564// Set ip to point to some stack offset.
1565// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001566bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001567EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001568{
1569#if 0
1570 // ARM pseudo code...
1571 if (ConditionPassed())
1572 {
1573 EncodingSpecificOperations();
1574 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1575 if d == 15 then // Can only occur for ARM encoding
1576 ALUWritePC(result); // setflags is always FALSE here
1577 else
1578 R[d] = result;
1579 if setflags then
1580 APSR.N = result<31>;
1581 APSR.Z = IsZeroBit(result);
1582 APSR.C = carry;
1583 APSR.V = overflow;
1584 }
1585#endif
1586
1587 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001588 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001589 if (!success)
1590 return false;
1591
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001592 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001593 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001594 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001595 if (!success)
1596 return false;
1597 uint32_t imm32;
1598 switch (encoding) {
1599 case eEncodingA1:
1600 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1601 break;
1602 default:
1603 return false;
1604 }
1605 addr_t sp_offset = imm32;
1606 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1607
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001608 EmulateInstruction::Context context;
1609 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1610 Register dwarf_reg;
1611 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1612 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001613
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001614 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001615 return false;
1616 }
1617 return true;
1618}
1619
Johnny Chenc9e747f2011-02-23 01:55:07 +00001620// This instruction subtracts an immediate value from the SP value, and writes
1621// the result to the destination register.
1622//
1623// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001624bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001625EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001626{
1627#if 0
1628 // ARM pseudo code...
1629 if (ConditionPassed())
1630 {
1631 EncodingSpecificOperations();
1632 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001633 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001634 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001635 else
1636 R[d] = result;
1637 if setflags then
1638 APSR.N = result<31>;
1639 APSR.Z = IsZeroBit(result);
1640 APSR.C = carry;
1641 APSR.V = overflow;
1642 }
1643#endif
1644
1645 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001646 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001647 if (!success)
1648 return false;
1649
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001650 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001651 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001652 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001653 if (!success)
1654 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001655
1656 uint32_t Rd;
1657 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001658 uint32_t imm32;
1659 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001660 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001661 Rd = 13;
1662 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001663 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001664 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001665 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001666 Rd = Bits32(opcode, 11, 8);
1667 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001668 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001669 if (Rd == 15 && setflags)
1670 return EmulateCMPImm(eEncodingT2);
1671 if (Rd == 15 && !setflags)
1672 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001673 break;
1674 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001675 Rd = Bits32(opcode, 11, 8);
1676 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001677 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001678 if (Rd == 15)
1679 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001680 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001681 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001682 Rd = Bits32(opcode, 15, 12);
1683 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001684 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001685 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1686 // TODO: Emulate SUBS PC, LR and related instructions.
1687 if (Rd == 15 && setflags)
1688 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001689 break;
1690 default:
1691 return false;
1692 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001693 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1694
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001695 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001696 if (Rd == 13)
1697 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001698 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1699 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001700 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001701 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001702 }
1703 else
1704 {
1705 context.type = EmulateInstruction::eContextImmediate;
1706 context.SetNoArgs ();
1707 }
1708
1709 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001710 return false;
1711 }
1712 return true;
1713}
1714
Johnny Chen08c25e82011-01-31 18:02:28 +00001715// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001716bool
1717EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001718{
1719#if 0
1720 // ARM pseudo code...
1721 if (ConditionPassed())
1722 {
1723 EncodingSpecificOperations();
1724 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1725 address = if index then offset_addr else R[n];
1726 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1727 if wback then R[n] = offset_addr;
1728 }
1729#endif
1730
1731 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001732 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001733 if (!success)
1734 return false;
1735
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001736 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001737 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001738 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001739 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001740 if (!success)
1741 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001742 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001743 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001744 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1745
1746 bool index;
1747 bool add;
1748 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001749 switch (encoding) {
1750 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001751 Rt = Bits32(opcode, 15, 12);
1752 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001753 Rn = Bits32 (opcode, 19, 16);
1754
1755 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1756 return false;
1757
1758 index = BitIsSet (opcode, 24);
1759 add = BitIsSet (opcode, 23);
1760 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1761
1762 if (wback && ((Rn == 15) || (Rn == Rt)))
1763 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001764 break;
1765 default:
1766 return false;
1767 }
Caroline Tice3e407972011-03-18 19:41:00 +00001768 addr_t offset_addr;
1769 if (add)
1770 offset_addr = sp + imm12;
1771 else
1772 offset_addr = sp - imm12;
1773
1774 addr_t addr;
1775 if (index)
1776 addr = offset_addr;
1777 else
1778 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001779
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001780 EmulateInstruction::Context context;
1781 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001782 Register sp_reg;
1783 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1784 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001785 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001786 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001787 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001788 if (!success)
1789 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001790 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001791 return false;
1792 }
1793 else
1794 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001795 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001796 if (!success)
1797 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001798 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001799 return false;
1800 }
1801
Caroline Tice3e407972011-03-18 19:41:00 +00001802
1803 if (wback)
1804 {
1805 context.type = EmulateInstruction::eContextAdjustStackPointer;
1806 context.SetImmediateSigned (addr - sp);
1807 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1808 return false;
1809 }
Johnny Chence1ca772011-01-25 01:13:00 +00001810 }
1811 return true;
1812}
1813
Johnny Chen08c25e82011-01-31 18:02:28 +00001814// Vector Push stores multiple extension registers to the stack.
1815// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001816bool
1817EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001818{
1819#if 0
1820 // ARM pseudo code...
1821 if (ConditionPassed())
1822 {
1823 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1824 address = SP - imm32;
1825 SP = SP - imm32;
1826 if single_regs then
1827 for r = 0 to regs-1
1828 MemA[address,4] = S[d+r]; address = address+4;
1829 else
1830 for r = 0 to regs-1
1831 // Store as two word-aligned words in the correct order for current endianness.
1832 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1833 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1834 address = address+8;
1835 }
1836#endif
1837
1838 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001839 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001840 if (!success)
1841 return false;
1842
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001843 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001844 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001845 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001846 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001847 if (!success)
1848 return false;
1849 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001850 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001851 uint32_t imm32; // stack offset
1852 uint32_t regs; // number of registers
1853 switch (encoding) {
1854 case eEncodingT1:
1855 case eEncodingA1:
1856 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001857 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001858 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1859 // If UInt(imm8) is odd, see "FSTMX".
1860 regs = Bits32(opcode, 7, 0) / 2;
1861 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1862 if (regs == 0 || regs > 16 || (d + regs) > 32)
1863 return false;
1864 break;
1865 case eEncodingT2:
1866 case eEncodingA2:
1867 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001868 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001869 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1870 regs = Bits32(opcode, 7, 0);
1871 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1872 if (regs == 0 || regs > 16 || (d + regs) > 32)
1873 return false;
1874 break;
1875 default:
1876 return false;
1877 }
1878 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1879 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1880 addr_t sp_offset = imm32;
1881 addr_t addr = sp - sp_offset;
1882 uint32_t i;
1883
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001884 EmulateInstruction::Context context;
1885 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1886 Register dwarf_reg;
1887 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001888 for (i=d; i<regs; ++i)
1889 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001890 dwarf_reg.num = start_reg + i;
1891 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001892 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001893 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001894 if (!success)
1895 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001896 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001897 return false;
1898 addr += reg_byte_size;
1899 }
1900
1901 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001902 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001903
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001904 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001905 return false;
1906 }
1907 return true;
1908}
1909
Johnny Chen587a0a42011-02-01 18:35:28 +00001910// Vector Pop loads multiple extension registers from the stack.
1911// It also updates SP to point just above the loaded data.
1912bool
1913EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1914{
1915#if 0
1916 // ARM pseudo code...
1917 if (ConditionPassed())
1918 {
1919 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1920 address = SP;
1921 SP = SP + imm32;
1922 if single_regs then
1923 for r = 0 to regs-1
1924 S[d+r] = MemA[address,4]; address = address+4;
1925 else
1926 for r = 0 to regs-1
1927 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1928 // Combine the word-aligned words in the correct order for current endianness.
1929 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1930 }
1931#endif
1932
1933 bool success = false;
1934 const uint32_t opcode = OpcodeAsUnsigned (&success);
1935 if (!success)
1936 return false;
1937
1938 if (ConditionPassed())
1939 {
1940 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001941 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001942 if (!success)
1943 return false;
1944 bool single_regs;
1945 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1946 uint32_t imm32; // stack offset
1947 uint32_t regs; // number of registers
1948 switch (encoding) {
1949 case eEncodingT1:
1950 case eEncodingA1:
1951 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001952 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001953 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1954 // If UInt(imm8) is odd, see "FLDMX".
1955 regs = Bits32(opcode, 7, 0) / 2;
1956 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1957 if (regs == 0 || regs > 16 || (d + regs) > 32)
1958 return false;
1959 break;
1960 case eEncodingT2:
1961 case eEncodingA2:
1962 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001963 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001964 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1965 regs = Bits32(opcode, 7, 0);
1966 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1967 if (regs == 0 || regs > 16 || (d + regs) > 32)
1968 return false;
1969 break;
1970 default:
1971 return false;
1972 }
1973 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1974 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1975 addr_t sp_offset = imm32;
1976 addr_t addr = sp;
1977 uint32_t i;
1978 uint64_t data; // uint64_t to accomodate 64-bit registers.
1979
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001980 EmulateInstruction::Context context;
1981 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1982 Register dwarf_reg;
1983 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001984 for (i=d; i<regs; ++i)
1985 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001986 dwarf_reg.num = start_reg + i;
1987 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001988 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001989 if (!success)
1990 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001991 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001992 return false;
1993 addr += reg_byte_size;
1994 }
1995
1996 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001997 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001998
1999 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2000 return false;
2001 }
2002 return true;
2003}
2004
Johnny Chenb77be412011-02-04 00:40:18 +00002005// SVC (previously SWI)
2006bool
2007EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
2008{
2009#if 0
2010 // ARM pseudo code...
2011 if (ConditionPassed())
2012 {
2013 EncodingSpecificOperations();
2014 CallSupervisor();
2015 }
2016#endif
2017
2018 bool success = false;
2019 const uint32_t opcode = OpcodeAsUnsigned (&success);
2020 if (!success)
2021 return false;
2022
2023 if (ConditionPassed())
2024 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002025 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002026 addr_t lr; // next instruction address
2027 if (!success)
2028 return false;
2029 uint32_t imm32; // the immediate constant
2030 uint32_t mode; // ARM or Thumb mode
2031 switch (encoding) {
2032 case eEncodingT1:
2033 lr = (pc + 2) | 1u; // return address
2034 imm32 = Bits32(opcode, 7, 0);
2035 mode = eModeThumb;
2036 break;
2037 case eEncodingA1:
2038 lr = pc + 4; // return address
2039 imm32 = Bits32(opcode, 23, 0);
2040 mode = eModeARM;
2041 break;
2042 default:
2043 return false;
2044 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002045
2046 EmulateInstruction::Context context;
2047 context.type = EmulateInstruction::eContextSupervisorCall;
2048 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002049 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2050 return false;
2051 }
2052 return true;
2053}
2054
Johnny Chenc315f862011-02-05 00:46:10 +00002055// If Then makes up to four following instructions (the IT block) conditional.
2056bool
2057EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
2058{
2059#if 0
2060 // ARM pseudo code...
2061 EncodingSpecificOperations();
2062 ITSTATE.IT<7:0> = firstcond:mask;
2063#endif
2064
2065 bool success = false;
2066 const uint32_t opcode = OpcodeAsUnsigned (&success);
2067 if (!success)
2068 return false;
2069
2070 m_it_session.InitIT(Bits32(opcode, 7, 0));
2071 return true;
2072}
2073
Johnny Chen3b620b32011-02-07 20:11:47 +00002074// Branch causes a branch to a target address.
2075bool
2076EmulateInstructionARM::EmulateB (ARMEncoding encoding)
2077{
2078#if 0
2079 // ARM pseudo code...
2080 if (ConditionPassed())
2081 {
2082 EncodingSpecificOperations();
2083 BranchWritePC(PC + imm32);
2084 }
2085#endif
2086
2087 bool success = false;
2088 const uint32_t opcode = OpcodeAsUnsigned (&success);
2089 if (!success)
2090 return false;
2091
Johnny Chen9ee056b2011-02-08 00:06:35 +00002092 if (ConditionPassed())
2093 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002094 EmulateInstruction::Context context;
2095 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002096 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002097 if (!success)
2098 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002099 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002100 int32_t imm32; // PC-relative offset
2101 switch (encoding) {
2102 case eEncodingT1:
2103 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2104 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002105 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002106 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002107 break;
2108 case eEncodingT2:
2109 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002110 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002111 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002112 break;
2113 case eEncodingT3:
2114 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2115 {
Johnny Chenbd599902011-02-10 21:39:01 +00002116 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002117 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002118 uint32_t J1 = Bit32(opcode, 13);
2119 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002120 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002121 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002122 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002123 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002124 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002125 break;
2126 }
2127 case eEncodingT4:
2128 {
Johnny Chenbd599902011-02-10 21:39:01 +00002129 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002130 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002131 uint32_t J1 = Bit32(opcode, 13);
2132 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002133 uint32_t imm11 = Bits32(opcode, 10, 0);
2134 uint32_t I1 = !(J1 ^ S);
2135 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002136 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002137 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002138 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002139 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002140 break;
2141 }
2142 case eEncodingA1:
2143 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002144 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002145 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002146 break;
2147 default:
2148 return false;
2149 }
2150 if (!BranchWritePC(context, target))
2151 return false;
2152 }
2153 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002154}
2155
Johnny Chen53ebab72011-02-08 23:21:57 +00002156// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2157// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2158// CBNZ, CBZ
2159bool
2160EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
2161{
2162#if 0
2163 // ARM pseudo code...
2164 EncodingSpecificOperations();
2165 if nonzero ^ IsZero(R[n]) then
2166 BranchWritePC(PC + imm32);
2167#endif
2168
2169 bool success = false;
2170 const uint32_t opcode = OpcodeAsUnsigned (&success);
2171 if (!success)
2172 return false;
2173
2174 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002175 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002176 if (!success)
2177 return false;
2178
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002179 EmulateInstruction::Context context;
2180 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002181 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002182 if (!success)
2183 return false;
2184
2185 addr_t target; // target address
2186 uint32_t imm32; // PC-relative offset to branch forward
2187 bool nonzero;
2188 switch (encoding) {
2189 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002190 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002191 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002192 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002193 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002194 break;
2195 default:
2196 return false;
2197 }
2198 if (nonzero ^ (reg_val == 0))
2199 if (!BranchWritePC(context, target))
2200 return false;
2201
2202 return true;
2203}
2204
Johnny Chen60299ec2011-02-17 19:34:27 +00002205// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2206// A base register provides a pointer to the table, and a second register supplies an index into the table.
2207// The branch length is twice the value of the byte returned from the table.
2208//
2209// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2210// A base register provides a pointer to the table, and a second register supplies an index into the table.
2211// The branch length is twice the value of the halfword returned from the table.
2212// TBB, TBH
2213bool
2214EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
2215{
2216#if 0
2217 // ARM pseudo code...
2218 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2219 if is_tbh then
2220 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2221 else
2222 halfwords = UInt(MemU[R[n]+R[m], 1]);
2223 BranchWritePC(PC + 2*halfwords);
2224#endif
2225
2226 bool success = false;
2227 const uint32_t opcode = OpcodeAsUnsigned (&success);
2228 if (!success)
2229 return false;
2230
2231 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2232 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2233 bool is_tbh; // true if table branch halfword
2234 switch (encoding) {
2235 case eEncodingT1:
2236 Rn = Bits32(opcode, 19, 16);
2237 Rm = Bits32(opcode, 3, 0);
2238 is_tbh = BitIsSet(opcode, 4);
2239 if (Rn == 13 || BadReg(Rm))
2240 return false;
2241 if (InITBlock() && !LastInITBlock())
2242 return false;
2243 break;
2244 default:
2245 return false;
2246 }
2247
2248 // Read the address of the table from the operand register Rn.
2249 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002250 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002251 if (!success)
2252 return false;
2253
2254 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002255 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002256 if (!success)
2257 return false;
2258
2259 // the offsetted table address
2260 addr_t addr = base + (is_tbh ? index*2 : index);
2261
2262 // PC-relative offset to branch forward
2263 EmulateInstruction::Context context;
2264 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002265 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002266 if (!success)
2267 return false;
2268
Johnny Chene39f22d2011-02-19 01:36:13 +00002269 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002270 if (!success)
2271 return false;
2272
2273 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002274 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002275 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2276 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2277
2278 if (!BranchWritePC(context, target))
2279 return false;
2280
2281 return true;
2282}
2283
Caroline Ticedcc11b32011-03-02 23:57:02 +00002284// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2285// It can optionally update the condition flags based on the result.
2286bool
2287EmulateInstructionARM::EmulateADDImmThumb (ARMEncoding encoding)
2288{
2289#if 0
2290 if ConditionPassed() then
2291 EncodingSpecificOperations();
2292 (result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2293 R[d] = result;
2294 if setflags then
2295 APSR.N = result<31>;
2296 APSR.Z = IsZeroBit(result);
2297 APSR.C = carry;
2298 APSR.V = overflow;
2299#endif
2300
2301 bool success = false;
2302 const uint32_t opcode = OpcodeAsUnsigned (&success);
2303 if (!success)
2304 return false;
2305
2306 if (ConditionPassed())
2307 {
2308 uint32_t d;
2309 uint32_t n;
2310 bool setflags;
2311 uint32_t imm32;
2312 uint32_t carry_out;
2313
2314 //EncodingSpecificOperations();
2315 switch (encoding)
2316 {
2317 case eEncodingT1:
2318 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2319 d = Bits32 (opcode, 2, 0);
2320 n = Bits32 (opcode, 5, 3);
2321 setflags = !InITBlock();
2322 imm32 = Bits32 (opcode, 8,6);
2323
2324 break;
2325
2326 case eEncodingT2:
2327 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2328 d = Bits32 (opcode, 10, 8);
2329 n = Bits32 (opcode, 10, 8);
2330 setflags = !InITBlock();
2331 imm32 = Bits32 (opcode, 7, 0);
2332
2333 break;
2334
2335 case eEncodingT3:
2336 // if Rd == ’1111’ && S == ’1’ then SEE CMN (immediate);
2337 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2338 // d = UInt(Rd); n = UInt(Rn); setflags = (S == ’1’); imm32 = ThumbExpandImm(i:imm3:imm8);
2339 d = Bits32 (opcode, 11, 8);
2340 n = Bits32 (opcode, 19, 16);
2341 setflags = BitIsSet (opcode, 20);
2342 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2343
2344 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2345 if (BadReg (d) || (n == 15))
2346 return false;
2347
2348 break;
2349
2350 case eEncodingT4:
2351 {
2352 // if Rn == ’1111’ then SEE ADR;
2353 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2354 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2355 d = Bits32 (opcode, 11, 8);
2356 n = Bits32 (opcode, 19, 16);
2357 setflags = false;
2358 uint32_t i = Bit32 (opcode, 26);
2359 uint32_t imm3 = Bits32 (opcode, 14, 12);
2360 uint32_t imm8 = Bits32 (opcode, 7, 0);
2361 imm32 = (i << 11) | (imm3 << 8) | imm8;
2362
2363 // if BadReg(d) then UNPREDICTABLE;
2364 if (BadReg (d))
2365 return false;
2366
2367 break;
2368 }
2369 default:
2370 return false;
2371 }
2372
2373 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2374 if (!success)
2375 return false;
2376
2377 //(result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2378 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2379
2380 Register reg_n;
2381 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2382
2383 EmulateInstruction::Context context;
2384 context.type = eContextAddition;
2385 context.SetRegisterPlusOffset (reg_n, imm32);
2386
2387 //R[d] = result;
2388 //if setflags then
2389 //APSR.N = result<31>;
2390 //APSR.Z = IsZeroBit(result);
2391 //APSR.C = carry;
2392 //APSR.V = overflow;
2393 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2394 return false;
2395
2396 }
2397 return true;
2398}
2399
Johnny Chen8fa20592011-02-18 01:22:22 +00002400// This instruction adds an immediate value to a register value, and writes the result to the destination
2401// register. It can optionally update the condition flags based on the result.
2402bool
2403EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2404{
2405#if 0
2406 // ARM pseudo code...
2407 if ConditionPassed() then
2408 EncodingSpecificOperations();
2409 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2410 if d == 15 then
2411 ALUWritePC(result); // setflags is always FALSE here
2412 else
2413 R[d] = result;
2414 if setflags then
2415 APSR.N = result<31>;
2416 APSR.Z = IsZeroBit(result);
2417 APSR.C = carry;
2418 APSR.V = overflow;
2419#endif
2420
2421 bool success = false;
2422 const uint32_t opcode = OpcodeAsUnsigned (&success);
2423 if (!success)
2424 return false;
2425
2426 if (ConditionPassed())
2427 {
2428 uint32_t Rd, Rn;
2429 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2430 bool setflags;
2431 switch (encoding)
2432 {
2433 case eEncodingA1:
2434 Rd = Bits32(opcode, 15, 12);
2435 Rn = Bits32(opcode, 19, 16);
2436 setflags = BitIsSet(opcode, 20);
2437 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2438 break;
2439 default:
2440 return false;
2441 }
2442
Johnny Chen8fa20592011-02-18 01:22:22 +00002443 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002444 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002445 if (!success)
2446 return false;
2447
2448 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2449
2450 EmulateInstruction::Context context;
2451 context.type = EmulateInstruction::eContextImmediate;
2452 context.SetNoArgs ();
2453
2454 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2455 return false;
2456 }
2457 return true;
2458}
2459
Johnny Chend761dcf2011-02-17 22:03:29 +00002460// This instruction adds a register value and an optionally-shifted register value, and writes the result
2461// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002462bool
Johnny Chen9f687722011-02-18 00:02:28 +00002463EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002464{
2465#if 0
2466 // ARM pseudo code...
2467 if ConditionPassed() then
2468 EncodingSpecificOperations();
2469 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2470 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2471 if d == 15 then
2472 ALUWritePC(result); // setflags is always FALSE here
2473 else
2474 R[d] = result;
2475 if setflags then
2476 APSR.N = result<31>;
2477 APSR.Z = IsZeroBit(result);
2478 APSR.C = carry;
2479 APSR.V = overflow;
2480#endif
2481
2482 bool success = false;
2483 const uint32_t opcode = OpcodeAsUnsigned (&success);
2484 if (!success)
2485 return false;
2486
2487 if (ConditionPassed())
2488 {
2489 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002490 ARM_ShifterType shift_t;
2491 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002492 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002493 switch (encoding)
2494 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002495 case eEncodingT1:
2496 Rd = Bits32(opcode, 2, 0);
2497 Rn = Bits32(opcode, 5, 3);
2498 Rm = Bits32(opcode, 8, 6);
2499 setflags = !InITBlock();
2500 shift_t = SRType_LSL;
2501 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002502 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002503 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002504 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002505 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002506 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002507 shift_t = SRType_LSL;
2508 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002509 if (Rn == 15 && Rm == 15)
2510 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002511 if (Rd == 15 && InITBlock() && !LastInITBlock())
2512 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002513 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002514 case eEncodingA1:
2515 Rd = Bits32(opcode, 15, 12);
2516 Rn = Bits32(opcode, 19, 16);
2517 Rm = Bits32(opcode, 3, 0);
2518 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002519 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002520 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002521 default:
2522 return false;
2523 }
2524
Johnny Chen26863dc2011-02-09 23:43:29 +00002525 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002526 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002527 if (!success)
2528 return false;
2529
2530 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002531 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002532 if (!success)
2533 return false;
2534
Johnny Chene97c0d52011-02-18 19:32:20 +00002535 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002536 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002537
2538 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002539 context.type = EmulateInstruction::eContextAddition;
2540 Register op1_reg;
2541 Register op2_reg;
2542 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2543 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2544 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002545
Johnny Chen10530c22011-02-17 22:37:12 +00002546 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002547 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002548 }
2549 return true;
2550}
2551
Johnny Chen34075cb2011-02-22 01:56:31 +00002552// Compare Negative (immediate) adds a register value and an immediate value.
2553// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002554bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002555EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2556{
2557#if 0
2558 // ARM pseudo code...
2559 if ConditionPassed() then
2560 EncodingSpecificOperations();
2561 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2562 APSR.N = result<31>;
2563 APSR.Z = IsZeroBit(result);
2564 APSR.C = carry;
2565 APSR.V = overflow;
2566#endif
2567
2568 bool success = false;
2569 const uint32_t opcode = OpcodeAsUnsigned (&success);
2570 if (!success)
2571 return false;
2572
2573 uint32_t Rn; // the first operand
2574 uint32_t imm32; // the immediate value to be compared with
2575 switch (encoding) {
2576 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002577 Rn = Bits32(opcode, 19, 16);
2578 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2579 if (Rn == 15)
2580 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002581 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002582 case eEncodingA1:
2583 Rn = Bits32(opcode, 19, 16);
2584 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2585 break;
2586 default:
2587 return false;
2588 }
2589 // Read the register value from the operand register Rn.
2590 uint32_t reg_val = ReadCoreReg(Rn, &success);
2591 if (!success)
2592 return false;
2593
Johnny Chen078fbc62011-02-22 19:48:22 +00002594 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002595
2596 EmulateInstruction::Context context;
2597 context.type = EmulateInstruction::eContextImmediate;
2598 context.SetNoArgs ();
2599 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2600 return false;
2601
2602 return true;
2603}
2604
2605// Compare Negative (register) adds a register value and an optionally-shifted register value.
2606// It updates the condition flags based on the result, and discards the result.
2607bool
2608EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2609{
2610#if 0
2611 // ARM pseudo code...
2612 if ConditionPassed() then
2613 EncodingSpecificOperations();
2614 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2615 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2616 APSR.N = result<31>;
2617 APSR.Z = IsZeroBit(result);
2618 APSR.C = carry;
2619 APSR.V = overflow;
2620#endif
2621
2622 bool success = false;
2623 const uint32_t opcode = OpcodeAsUnsigned (&success);
2624 if (!success)
2625 return false;
2626
2627 uint32_t Rn; // the first operand
2628 uint32_t Rm; // the second operand
2629 ARM_ShifterType shift_t;
2630 uint32_t shift_n; // the shift applied to the value read from Rm
2631 switch (encoding) {
2632 case eEncodingT1:
2633 Rn = Bits32(opcode, 2, 0);
2634 Rm = Bits32(opcode, 5, 3);
2635 shift_t = SRType_LSL;
2636 shift_n = 0;
2637 break;
2638 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002639 Rn = Bits32(opcode, 19, 16);
2640 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002641 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002642 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2643 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002644 return false;
2645 break;
2646 case eEncodingA1:
2647 Rn = Bits32(opcode, 19, 16);
2648 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002649 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002650 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002651 default:
2652 return false;
2653 }
2654 // Read the register value from register Rn.
2655 uint32_t val1 = ReadCoreReg(Rn, &success);
2656 if (!success)
2657 return false;
2658
2659 // Read the register value from register Rm.
2660 uint32_t val2 = ReadCoreReg(Rm, &success);
2661 if (!success)
2662 return false;
2663
2664 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002665 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002666
2667 EmulateInstruction::Context context;
2668 context.type = EmulateInstruction::eContextImmediate;
2669 context.SetNoArgs();
2670 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2671 return false;
2672
2673 return true;
2674}
2675
2676// Compare (immediate) subtracts an immediate value from a register value.
2677// It updates the condition flags based on the result, and discards the result.
2678bool
2679EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002680{
2681#if 0
2682 // ARM pseudo code...
2683 if ConditionPassed() then
2684 EncodingSpecificOperations();
2685 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2686 APSR.N = result<31>;
2687 APSR.Z = IsZeroBit(result);
2688 APSR.C = carry;
2689 APSR.V = overflow;
2690#endif
2691
2692 bool success = false;
2693 const uint32_t opcode = OpcodeAsUnsigned (&success);
2694 if (!success)
2695 return false;
2696
2697 uint32_t Rn; // the first operand
2698 uint32_t imm32; // the immediate value to be compared with
2699 switch (encoding) {
2700 case eEncodingT1:
2701 Rn = Bits32(opcode, 10, 8);
2702 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002703 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002704 case eEncodingT2:
2705 Rn = Bits32(opcode, 19, 16);
2706 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2707 if (Rn == 15)
2708 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002709 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002710 case eEncodingA1:
2711 Rn = Bits32(opcode, 19, 16);
2712 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002713 break;
2714 default:
2715 return false;
2716 }
2717 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002718 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002719 if (!success)
2720 return false;
2721
Johnny Chen10530c22011-02-17 22:37:12 +00002722 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2723
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002724 EmulateInstruction::Context context;
2725 context.type = EmulateInstruction::eContextImmediate;
2726 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002727 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2728 return false;
2729
Johnny Chend4dc4442011-02-11 02:02:56 +00002730 return true;
2731}
2732
Johnny Chen34075cb2011-02-22 01:56:31 +00002733// Compare (register) subtracts an optionally-shifted register value from a register value.
2734// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002735bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002736EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002737{
2738#if 0
2739 // ARM pseudo code...
2740 if ConditionPassed() then
2741 EncodingSpecificOperations();
2742 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2743 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2744 APSR.N = result<31>;
2745 APSR.Z = IsZeroBit(result);
2746 APSR.C = carry;
2747 APSR.V = overflow;
2748#endif
2749
2750 bool success = false;
2751 const uint32_t opcode = OpcodeAsUnsigned (&success);
2752 if (!success)
2753 return false;
2754
2755 uint32_t Rn; // the first operand
2756 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002757 ARM_ShifterType shift_t;
2758 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002759 switch (encoding) {
2760 case eEncodingT1:
2761 Rn = Bits32(opcode, 2, 0);
2762 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002763 shift_t = SRType_LSL;
2764 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002765 break;
2766 case eEncodingT2:
2767 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2768 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002769 shift_t = SRType_LSL;
2770 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002771 if (Rn < 8 && Rm < 8)
2772 return false;
2773 if (Rn == 15 || Rm == 15)
2774 return false;
2775 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002776 case eEncodingA1:
2777 Rn = Bits32(opcode, 19, 16);
2778 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002779 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002780 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002781 default:
2782 return false;
2783 }
2784 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002785 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002786 if (!success)
2787 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002788
Johnny Chene4a4d302011-02-11 21:53:58 +00002789 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002790 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002791 if (!success)
2792 return false;
2793
Johnny Chen34075cb2011-02-22 01:56:31 +00002794 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2795 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002796
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002797 EmulateInstruction::Context context;
2798 context.type = EmulateInstruction::eContextImmediate;
2799 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002800 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2801 return false;
2802
Johnny Chene4a4d302011-02-11 21:53:58 +00002803 return true;
2804}
2805
Johnny Chen82f16aa2011-02-15 20:10:55 +00002806// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2807// shifting in copies of its sign bit, and writes the result to the destination register. It can
2808// optionally update the condition flags based on the result.
2809bool
2810EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2811{
2812#if 0
2813 // ARM pseudo code...
2814 if ConditionPassed() then
2815 EncodingSpecificOperations();
2816 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2817 if d == 15 then // Can only occur for ARM encoding
2818 ALUWritePC(result); // setflags is always FALSE here
2819 else
2820 R[d] = result;
2821 if setflags then
2822 APSR.N = result<31>;
2823 APSR.Z = IsZeroBit(result);
2824 APSR.C = carry;
2825 // APSR.V unchanged
2826#endif
2827
Johnny Chen41a0a152011-02-16 01:27:54 +00002828 return EmulateShiftImm(encoding, SRType_ASR);
2829}
2830
2831// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2832// shifting in copies of its sign bit, and writes the result to the destination register.
2833// The variable number of bits is read from the bottom byte of a register. It can optionally update
2834// the condition flags based on the result.
2835bool
2836EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2837{
2838#if 0
2839 // ARM pseudo code...
2840 if ConditionPassed() then
2841 EncodingSpecificOperations();
2842 shift_n = UInt(R[m]<7:0>);
2843 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2844 R[d] = result;
2845 if setflags then
2846 APSR.N = result<31>;
2847 APSR.Z = IsZeroBit(result);
2848 APSR.C = carry;
2849 // APSR.V unchanged
2850#endif
2851
2852 return EmulateShiftReg(encoding, SRType_ASR);
2853}
2854
2855// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2856// shifting in zeros, and writes the result to the destination register. It can optionally
2857// update the condition flags based on the result.
2858bool
2859EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2860{
2861#if 0
2862 // ARM pseudo code...
2863 if ConditionPassed() then
2864 EncodingSpecificOperations();
2865 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2866 if d == 15 then // Can only occur for ARM encoding
2867 ALUWritePC(result); // setflags is always FALSE here
2868 else
2869 R[d] = result;
2870 if setflags then
2871 APSR.N = result<31>;
2872 APSR.Z = IsZeroBit(result);
2873 APSR.C = carry;
2874 // APSR.V unchanged
2875#endif
2876
2877 return EmulateShiftImm(encoding, SRType_LSL);
2878}
2879
2880// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2881// shifting in zeros, and writes the result to the destination register. The variable number
2882// of bits is read from the bottom byte of a register. It can optionally update the condition
2883// flags based on the result.
2884bool
2885EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2886{
2887#if 0
2888 // ARM pseudo code...
2889 if ConditionPassed() then
2890 EncodingSpecificOperations();
2891 shift_n = UInt(R[m]<7:0>);
2892 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2893 R[d] = result;
2894 if setflags then
2895 APSR.N = result<31>;
2896 APSR.Z = IsZeroBit(result);
2897 APSR.C = carry;
2898 // APSR.V unchanged
2899#endif
2900
2901 return EmulateShiftReg(encoding, SRType_LSL);
2902}
2903
2904// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2905// shifting in zeros, and writes the result to the destination register. It can optionally
2906// update the condition flags based on the result.
2907bool
2908EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2909{
2910#if 0
2911 // ARM pseudo code...
2912 if ConditionPassed() then
2913 EncodingSpecificOperations();
2914 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2915 if d == 15 then // Can only occur for ARM encoding
2916 ALUWritePC(result); // setflags is always FALSE here
2917 else
2918 R[d] = result;
2919 if setflags then
2920 APSR.N = result<31>;
2921 APSR.Z = IsZeroBit(result);
2922 APSR.C = carry;
2923 // APSR.V unchanged
2924#endif
2925
2926 return EmulateShiftImm(encoding, SRType_LSR);
2927}
2928
2929// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2930// shifting in zeros, and writes the result to the destination register. The variable number
2931// of bits is read from the bottom byte of a register. It can optionally update the condition
2932// flags based on the result.
2933bool
2934EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2935{
2936#if 0
2937 // ARM pseudo code...
2938 if ConditionPassed() then
2939 EncodingSpecificOperations();
2940 shift_n = UInt(R[m]<7:0>);
2941 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2942 R[d] = result;
2943 if setflags then
2944 APSR.N = result<31>;
2945 APSR.Z = IsZeroBit(result);
2946 APSR.C = carry;
2947 // APSR.V unchanged
2948#endif
2949
2950 return EmulateShiftReg(encoding, SRType_LSR);
2951}
2952
Johnny Cheneeab4852011-02-16 22:14:44 +00002953// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2954// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2955// It can optionally update the condition flags based on the result.
2956bool
2957EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2958{
2959#if 0
2960 // ARM pseudo code...
2961 if ConditionPassed() then
2962 EncodingSpecificOperations();
2963 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2964 if d == 15 then // Can only occur for ARM encoding
2965 ALUWritePC(result); // setflags is always FALSE here
2966 else
2967 R[d] = result;
2968 if setflags then
2969 APSR.N = result<31>;
2970 APSR.Z = IsZeroBit(result);
2971 APSR.C = carry;
2972 // APSR.V unchanged
2973#endif
2974
2975 return EmulateShiftImm(encoding, SRType_ROR);
2976}
2977
2978// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2979// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2980// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2981// flags based on the result.
2982bool
2983EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2984{
2985#if 0
2986 // ARM pseudo code...
2987 if ConditionPassed() then
2988 EncodingSpecificOperations();
2989 shift_n = UInt(R[m]<7:0>);
2990 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2991 R[d] = result;
2992 if setflags then
2993 APSR.N = result<31>;
2994 APSR.Z = IsZeroBit(result);
2995 APSR.C = carry;
2996 // APSR.V unchanged
2997#endif
2998
2999 return EmulateShiftReg(encoding, SRType_ROR);
3000}
3001
3002// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
3003// with the carry flag shifted into bit [31].
3004//
3005// RRX can optionally update the condition flags based on the result.
3006// In that case, bit [0] is shifted into the carry flag.
3007bool
3008EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
3009{
3010#if 0
3011 // ARM pseudo code...
3012 if ConditionPassed() then
3013 EncodingSpecificOperations();
3014 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3015 if d == 15 then // Can only occur for ARM encoding
3016 ALUWritePC(result); // setflags is always FALSE here
3017 else
3018 R[d] = result;
3019 if setflags then
3020 APSR.N = result<31>;
3021 APSR.Z = IsZeroBit(result);
3022 APSR.C = carry;
3023 // APSR.V unchanged
3024#endif
3025
3026 return EmulateShiftImm(encoding, SRType_RRX);
3027}
3028
Johnny Chen41a0a152011-02-16 01:27:54 +00003029bool
3030EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
3031{
3032 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
3033
Johnny Chen82f16aa2011-02-15 20:10:55 +00003034 bool success = false;
3035 const uint32_t opcode = OpcodeAsUnsigned (&success);
3036 if (!success)
3037 return false;
3038
3039 if (ConditionPassed())
3040 {
Johnny Chene7f89532011-02-15 23:22:46 +00003041 uint32_t Rd; // the destination register
3042 uint32_t Rm; // the first operand register
3043 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003044 uint32_t carry; // the carry bit after the shift operation
3045 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003046
3047 // Special case handling!
3048 // A8.6.139 ROR (immediate) -- Encoding T1
3049 if (shift_type == SRType_ROR && encoding == eEncodingT1)
3050 {
3051 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3052 // have the same decoding of bit fields as the other Thumb2 shift operations.
3053 encoding = eEncodingT2;
3054 }
3055
Johnny Chen82f16aa2011-02-15 20:10:55 +00003056 switch (encoding) {
3057 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003058 // Due to the above special case handling!
3059 assert(shift_type != SRType_ROR);
3060
Johnny Chen82f16aa2011-02-15 20:10:55 +00003061 Rd = Bits32(opcode, 2, 0);
3062 Rm = Bits32(opcode, 5, 3);
3063 setflags = !InITBlock();
3064 imm5 = Bits32(opcode, 10, 6);
3065 break;
3066 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003067 // A8.6.141 RRX
3068 assert(shift_type != SRType_RRX);
3069
Johnny Chen82f16aa2011-02-15 20:10:55 +00003070 Rd = Bits32(opcode, 11, 8);
3071 Rm = Bits32(opcode, 3, 0);
3072 setflags = BitIsSet(opcode, 20);
3073 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3074 if (BadReg(Rd) || BadReg(Rm))
3075 return false;
3076 break;
3077 case eEncodingA1:
3078 Rd = Bits32(opcode, 15, 12);
3079 Rm = Bits32(opcode, 3, 0);
3080 setflags = BitIsSet(opcode, 20);
3081 imm5 = Bits32(opcode, 11, 7);
3082 break;
3083 default:
3084 return false;
3085 }
3086
Johnny Cheneeab4852011-02-16 22:14:44 +00003087 // A8.6.139 ROR (immediate)
3088 if (shift_type == SRType_ROR && imm5 == 0)
3089 shift_type = SRType_RRX;
3090
Johnny Chen82f16aa2011-02-15 20:10:55 +00003091 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003092 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003093 if (!success)
3094 return false;
3095
Johnny Cheneeab4852011-02-16 22:14:44 +00003096 // Decode the shift amount if not RRX.
3097 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003098
Johnny Chene97c0d52011-02-18 19:32:20 +00003099 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003100
3101 // The context specifies that an immediate is to be moved into Rd.
3102 EmulateInstruction::Context context;
3103 context.type = EmulateInstruction::eContextImmediate;
3104 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003105
Johnny Chen10530c22011-02-17 22:37:12 +00003106 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003107 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003108 }
3109 return true;
3110}
3111
Johnny Chene7f89532011-02-15 23:22:46 +00003112bool
Johnny Chen41a0a152011-02-16 01:27:54 +00003113EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003114{
Johnny Chen41a0a152011-02-16 01:27:54 +00003115 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003116
3117 bool success = false;
3118 const uint32_t opcode = OpcodeAsUnsigned (&success);
3119 if (!success)
3120 return false;
3121
3122 if (ConditionPassed())
3123 {
3124 uint32_t Rd; // the destination register
3125 uint32_t Rn; // the first operand register
3126 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3127 uint32_t carry; // the carry bit after the shift operation
3128 bool setflags;
3129 switch (encoding) {
3130 case eEncodingT1:
3131 Rd = Bits32(opcode, 2, 0);
3132 Rn = Rd;
3133 Rm = Bits32(opcode, 5, 3);
3134 setflags = !InITBlock();
3135 break;
3136 case eEncodingT2:
3137 Rd = Bits32(opcode, 11, 8);
3138 Rn = Bits32(opcode, 19, 16);
3139 Rm = Bits32(opcode, 3, 0);
3140 setflags = BitIsSet(opcode, 20);
3141 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3142 return false;
3143 break;
3144 case eEncodingA1:
3145 Rd = Bits32(opcode, 15, 12);
3146 Rn = Bits32(opcode, 3, 0);
3147 Rm = Bits32(opcode, 11, 8);
3148 setflags = BitIsSet(opcode, 20);
3149 if (Rd == 15 || Rn == 15 || Rm == 15)
3150 return false;
3151 break;
3152 default:
3153 return false;
3154 }
3155
3156 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003157 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003158 if (!success)
3159 return false;
3160 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003161 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003162 if (!success)
3163 return false;
3164
3165 // Get the shift amount.
3166 uint32_t amt = Bits32(val, 7, 0);
3167
Johnny Chene97c0d52011-02-18 19:32:20 +00003168 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003169
3170 // The context specifies that an immediate is to be moved into Rd.
3171 EmulateInstruction::Context context;
3172 context.type = EmulateInstruction::eContextImmediate;
3173 context.SetNoArgs ();
3174
Johnny Chen10530c22011-02-17 22:37:12 +00003175 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003176 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003177 }
3178 return true;
3179}
3180
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003181// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003182// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003183// can be written back to the base register.
3184bool
3185EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
3186{
3187#if 0
3188 // ARM pseudo code...
3189 if ConditionPassed()
3190 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3191 address = R[n];
3192
3193 for i = 0 to 14
3194 if registers<i> == '1' then
3195 R[i] = MemA[address, 4]; address = address + 4;
3196 if registers<15> == '1' then
3197 LoadWritePC (MemA[address, 4]);
3198
3199 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3200 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3201
3202#endif
3203
3204 bool success = false;
3205 const uint32_t opcode = OpcodeAsUnsigned (&success);
3206 if (!success)
3207 return false;
3208
3209 if (ConditionPassed())
3210 {
3211 uint32_t n;
3212 uint32_t registers = 0;
3213 bool wback;
3214 const uint32_t addr_byte_size = GetAddressByteSize();
3215 switch (encoding)
3216 {
3217 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003218 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003219 n = Bits32 (opcode, 10, 8);
3220 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003221 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003222 wback = BitIsClear (registers, n);
3223 // if BitCount(registers) < 1 then UNPREDICTABLE;
3224 if (BitCount(registers) < 1)
3225 return false;
3226 break;
3227 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003228 // if W == ’1’ && Rn == ’1101’ then SEE POP;
3229 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003230 n = Bits32 (opcode, 19, 16);
3231 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003232 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003233 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003234
3235 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003236 if ((n == 15)
3237 || (BitCount (registers) < 2)
3238 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3239 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003240
3241 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003242 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003243 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003244
3245 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003246 if (wback
3247 && BitIsSet (registers, n))
3248 return false;
3249 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003250
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003251 case eEncodingA1:
3252 n = Bits32 (opcode, 19, 16);
3253 registers = Bits32 (opcode, 15, 0);
3254 wback = BitIsSet (opcode, 21);
3255 if ((n == 15)
3256 || (BitCount (registers) < 1))
3257 return false;
3258 break;
3259 default:
3260 return false;
3261 }
3262
3263 int32_t offset = 0;
3264 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3265 if (!success)
3266 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003267
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003268 EmulateInstruction::Context context;
3269 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3270 Register dwarf_reg;
3271 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3272 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003273
3274 for (int i = 0; i < 14; ++i)
3275 {
3276 if (BitIsSet (registers, i))
3277 {
Caroline Tice85aab332011-02-08 23:56:10 +00003278 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003279 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003280 if (wback && (n == 13)) // Pop Instruction
3281 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3282
3283 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003284 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003285 if (!success)
3286 return false;
3287
3288 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3289 return false;
3290
3291 offset += addr_byte_size;
3292 }
3293 }
3294
3295 if (BitIsSet (registers, 15))
3296 {
3297 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003298 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003299 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003300 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003301 if (!success)
3302 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003303 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003304 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003305 return false;
3306 }
3307
3308 if (wback && BitIsClear (registers, n))
3309 {
Caroline Ticefa172202011-02-11 22:49:54 +00003310 // R[n] = R[n] + 4 * BitCount (registers)
3311 int32_t offset = addr_byte_size * BitCount (registers);
3312 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003313 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003314
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003315 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3316 return false;
3317 }
3318 if (wback && BitIsSet (registers, n))
3319 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003320 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003321 }
3322 return true;
3323}
Caroline Tice713c2662011-02-11 17:59:55 +00003324
3325// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3326// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3327// can optionally be written back tot he base registers.
3328bool
3329EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
3330{
3331#if 0
3332 // ARM pseudo code...
3333 if ConditionPassed() then
3334 EncodingSpecificOperations();
3335 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003336
Caroline Tice713c2662011-02-11 17:59:55 +00003337 for i = 0 to 14
3338 if registers<i> == ’1’ then
3339 R[i] = MemA[address,4]; address = address + 4;
3340
3341 if registers<15> == ’1’ then
3342 LoadWritePC(MemA[address,4]);
3343
3344 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3345 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3346#endif
3347
3348 bool success = false;
3349 const uint32_t opcode = OpcodeAsUnsigned (&success);
3350 if (!success)
3351 return false;
3352
3353 if (ConditionPassed())
3354 {
3355 uint32_t n;
3356 uint32_t registers = 0;
3357 bool wback;
3358 const uint32_t addr_byte_size = GetAddressByteSize();
3359
3360 // EncodingSpecificOperations();
3361 switch (encoding)
3362 {
3363 case eEncodingA1:
3364 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3365 n = Bits32 (opcode, 19, 16);
3366 registers = Bits32 (opcode, 15, 0);
3367 wback = BitIsSet (opcode, 21);
3368
3369 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3370 if ((n == 15) || (BitCount (registers) < 1))
3371 return false;
3372
3373 break;
3374
3375 default:
3376 return false;
3377 }
3378 // address = R[n] - 4*BitCount(registers) + 4;
3379
3380 int32_t offset = 0;
3381 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3382
3383 if (!success)
3384 return false;
3385
3386 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3387
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003388 EmulateInstruction::Context context;
3389 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3390 Register dwarf_reg;
3391 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3392 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003393
3394 // for i = 0 to 14
3395 for (int i = 0; i < 14; ++i)
3396 {
3397 // if registers<i> == ’1’ then
3398 if (BitIsSet (registers, i))
3399 {
3400 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003401 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003402 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003403 if (!success)
3404 return false;
3405 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3406 return false;
3407 offset += addr_byte_size;
3408 }
3409 }
3410
3411 // if registers<15> == ’1’ then
3412 // LoadWritePC(MemA[address,4]);
3413 if (BitIsSet (registers, 15))
3414 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003415 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003416 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003417 if (!success)
3418 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003419 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003420 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003421 return false;
3422 }
3423
3424 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3425 if (wback && BitIsClear (registers, n))
3426 {
Caroline Tice713c2662011-02-11 17:59:55 +00003427 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3428 if (!success)
3429 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003430
3431 offset = (addr_byte_size * BitCount (registers)) * -1;
3432 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003433 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003434 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003435 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3436 return false;
3437 }
3438
3439 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3440 if (wback && BitIsSet (registers, n))
3441 return WriteBits32Unknown (n);
3442 }
3443 return true;
3444}
3445
3446// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3447// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3448// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003449bool
3450EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3451{
3452#if 0
3453 // ARM pseudo code...
3454 if ConditionPassed() then
3455 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3456 address = R[n] - 4*BitCount(registers);
3457
3458 for i = 0 to 14
3459 if registers<i> == ’1’ then
3460 R[i] = MemA[address,4]; address = address + 4;
3461 if registers<15> == ’1’ then
3462 LoadWritePC(MemA[address,4]);
3463
3464 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3465 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3466#endif
3467
3468 bool success = false;
3469 const uint32_t opcode = OpcodeAsUnsigned (&success);
3470 if (!success)
3471 return false;
3472
3473 if (ConditionPassed())
3474 {
3475 uint32_t n;
3476 uint32_t registers = 0;
3477 bool wback;
3478 const uint32_t addr_byte_size = GetAddressByteSize();
3479 switch (encoding)
3480 {
3481 case eEncodingT1:
3482 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3483 n = Bits32 (opcode, 19, 16);
3484 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003485 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003486 wback = BitIsSet (opcode, 21);
3487
3488 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3489 if ((n == 15)
3490 || (BitCount (registers) < 2)
3491 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3492 return false;
3493
3494 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003495 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003496 return false;
3497
3498 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3499 if (wback && BitIsSet (registers, n))
3500 return false;
3501
3502 break;
3503
3504 case eEncodingA1:
3505 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3506 n = Bits32 (opcode, 19, 16);
3507 registers = Bits32 (opcode, 15, 0);
3508 wback = BitIsSet (opcode, 21);
3509
3510 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3511 if ((n == 15) || (BitCount (registers) < 1))
3512 return false;
3513
3514 break;
3515
3516 default:
3517 return false;
3518 }
3519
Caroline Tice713c2662011-02-11 17:59:55 +00003520 // address = R[n] - 4*BitCount(registers);
3521
Caroline Tice0b29e242011-02-08 23:16:02 +00003522 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003523 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3524
3525 if (!success)
3526 return false;
3527
3528 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003529 EmulateInstruction::Context context;
3530 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3531 Register dwarf_reg;
3532 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3533 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003534
3535 for (int i = 0; i < 14; ++i)
3536 {
3537 if (BitIsSet (registers, i))
3538 {
3539 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003540 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003541 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003542 if (!success)
3543 return false;
3544
3545 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3546 return false;
3547
3548 offset += addr_byte_size;
3549 }
3550 }
3551
3552 // if registers<15> == ’1’ then
3553 // LoadWritePC(MemA[address,4]);
3554 if (BitIsSet (registers, 15))
3555 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003556 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003557 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003558 if (!success)
3559 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003560 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003561 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003562 return false;
3563 }
3564
3565 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3566 if (wback && BitIsClear (registers, n))
3567 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003568 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3569 if (!success)
3570 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003571
3572 offset = (addr_byte_size * BitCount (registers)) * -1;
3573 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003574 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003575 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003576 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3577 return false;
3578 }
3579
3580 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3581 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003582 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003583 }
3584 return true;
3585}
Caroline Tice85aab332011-02-08 23:56:10 +00003586
Caroline Tice713c2662011-02-11 17:59:55 +00003587// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3588// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3589// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003590bool
3591EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3592{
3593#if 0
3594 if ConditionPassed() then
3595 EncodingSpecificOperations();
3596 address = R[n] + 4;
3597
3598 for i = 0 to 14
3599 if registers<i> == ’1’ then
3600 R[i] = MemA[address,4]; address = address + 4;
3601 if registers<15> == ’1’ then
3602 LoadWritePC(MemA[address,4]);
3603
3604 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3605 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3606#endif
3607
3608 bool success = false;
3609 const uint32_t opcode = OpcodeAsUnsigned (&success);
3610 if (!success)
3611 return false;
3612
3613 if (ConditionPassed())
3614 {
3615 uint32_t n;
3616 uint32_t registers = 0;
3617 bool wback;
3618 const uint32_t addr_byte_size = GetAddressByteSize();
3619 switch (encoding)
3620 {
3621 case eEncodingA1:
3622 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3623 n = Bits32 (opcode, 19, 16);
3624 registers = Bits32 (opcode, 15, 0);
3625 wback = BitIsSet (opcode, 21);
3626
3627 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3628 if ((n == 15) || (BitCount (registers) < 1))
3629 return false;
3630
3631 break;
3632 default:
3633 return false;
3634 }
3635 // address = R[n] + 4;
3636
3637 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003638 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3639
3640 if (!success)
3641 return false;
3642
3643 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003644
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003645 EmulateInstruction::Context context;
3646 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3647 Register dwarf_reg;
3648 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3649 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003650
3651 for (int i = 0; i < 14; ++i)
3652 {
3653 if (BitIsSet (registers, i))
3654 {
3655 // R[i] = MemA[address,4]; address = address + 4;
3656
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003657 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003658 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003659 if (!success)
3660 return false;
3661
3662 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3663 return false;
3664
3665 offset += addr_byte_size;
3666 }
3667 }
3668
3669 // if registers<15> == ’1’ then
3670 // LoadWritePC(MemA[address,4]);
3671 if (BitIsSet (registers, 15))
3672 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003673 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003674 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003675 if (!success)
3676 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003677 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003678 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003679 return false;
3680 }
3681
3682 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3683 if (wback && BitIsClear (registers, n))
3684 {
Caroline Tice85aab332011-02-08 23:56:10 +00003685 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3686 if (!success)
3687 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003688
3689 offset = addr_byte_size * BitCount (registers);
3690 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003691 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003692 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003693 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3694 return false;
3695 }
3696
3697 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3698 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003699 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003700 }
3701 return true;
3702}
Caroline Tice0b29e242011-02-08 23:16:02 +00003703
Johnny Chenef21b592011-02-10 01:52:38 +00003704// Load Register (immediate) calculates an address from a base register value and
3705// an immediate offset, loads a word from memory, and writes to a register.
3706// LDR (immediate, Thumb)
3707bool
3708EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3709{
3710#if 0
3711 // ARM pseudo code...
3712 if (ConditionPassed())
3713 {
3714 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3715 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3716 address = if index then offset_addr else R[n];
3717 data = MemU[address,4];
3718 if wback then R[n] = offset_addr;
3719 if t == 15 then
3720 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3721 elsif UnalignedSupport() || address<1:0> = '00' then
3722 R[t] = data;
3723 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3724 }
3725#endif
3726
3727 bool success = false;
3728 const uint32_t opcode = OpcodeAsUnsigned (&success);
3729 if (!success)
3730 return false;
3731
3732 if (ConditionPassed())
3733 {
3734 uint32_t Rt; // the destination register
3735 uint32_t Rn; // the base register
3736 uint32_t imm32; // the immediate offset used to form the address
3737 addr_t offset_addr; // the offset address
3738 addr_t address; // the calculated address
3739 uint32_t data; // the literal data value from memory load
3740 bool add, index, wback;
3741 switch (encoding) {
3742 case eEncodingT1:
3743 Rt = Bits32(opcode, 5, 3);
3744 Rn = Bits32(opcode, 2, 0);
3745 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3746 // index = TRUE; add = TRUE; wback = FALSE
3747 add = true;
3748 index = true;
3749 wback = false;
3750 break;
3751 default:
3752 return false;
3753 }
3754 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3755 if (!success)
3756 return false;
3757 if (add)
3758 offset_addr = base + imm32;
3759 else
3760 offset_addr = base - imm32;
3761
3762 address = (index ? offset_addr : base);
3763
3764 if (wback)
3765 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003766 EmulateInstruction::Context ctx;
3767 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3768 Register dwarf_reg;
3769 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3770 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3771
Johnny Chenef21b592011-02-10 01:52:38 +00003772 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3773 return false;
3774 }
3775
3776 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003777 EmulateInstruction::Context context;
3778 context.type = EmulateInstruction::eContextImmediate;
3779 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003780
3781 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003782 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003783 if (!success)
3784 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003785
3786 if (Rt == 15)
3787 {
3788 if (Bits32(address, 1, 0) == 0)
3789 {
Johnny Chen668b4512011-02-15 21:08:58 +00003790 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003791 return false;
3792 }
3793 else
3794 return false;
3795 }
3796 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3797 {
3798 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3799 return false;
3800 }
3801 else
3802 return false;
3803 }
3804 return true;
3805}
3806
Caroline Ticeaf556562011-02-15 18:42:15 +00003807// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3808// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3809// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003810bool
3811EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3812{
3813#if 0
3814 if ConditionPassed() then
3815 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3816 address = R[n];
3817
3818 for i = 0 to 14
3819 if registers<i> == ’1’ then
3820 if i == n && wback && i != LowestSetBit(registers) then
3821 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3822 else
3823 MemA[address,4] = R[i];
3824 address = address + 4;
3825
3826 if registers<15> == ’1’ then // Only possible for encoding A1
3827 MemA[address,4] = PCStoreValue();
3828 if wback then R[n] = R[n] + 4*BitCount(registers);
3829#endif
3830
3831 bool success = false;
3832 const uint32_t opcode = OpcodeAsUnsigned (&success);
3833 if (!success)
3834 return false;
3835
3836 if (ConditionPassed ())
3837 {
3838 uint32_t n;
3839 uint32_t registers = 0;
3840 bool wback;
3841 const uint32_t addr_byte_size = GetAddressByteSize();
3842
3843 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3844 switch (encoding)
3845 {
3846 case eEncodingT1:
3847 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3848 n = Bits32 (opcode, 10, 8);
3849 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003850 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003851 wback = true;
3852
3853 // if BitCount(registers) < 1 then UNPREDICTABLE;
3854 if (BitCount (registers) < 1)
3855 return false;
3856
3857 break;
3858
3859 case eEncodingT2:
3860 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3861 n = Bits32 (opcode, 19, 16);
3862 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003863 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003864 wback = BitIsSet (opcode, 21);
3865
3866 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3867 if ((n == 15) || (BitCount (registers) < 2))
3868 return false;
3869
3870 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3871 if (wback && BitIsSet (registers, n))
3872 return false;
3873
3874 break;
3875
3876 case eEncodingA1:
3877 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3878 n = Bits32 (opcode, 19, 16);
3879 registers = Bits32 (opcode, 15, 0);
3880 wback = BitIsSet (opcode, 21);
3881
3882 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3883 if ((n == 15) || (BitCount (registers) < 1))
3884 return false;
3885
3886 break;
3887
3888 default:
3889 return false;
3890 }
3891
3892 // address = R[n];
3893 int32_t offset = 0;
3894 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3895 if (!success)
3896 return false;
3897
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003898 EmulateInstruction::Context context;
3899 context.type = EmulateInstruction::eContextRegisterStore;
3900 Register base_reg;
3901 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003902
3903 // for i = 0 to 14
3904 for (int i = 0; i < 14; ++i)
3905 {
3906 int lowest_set_bit = 14;
3907 // if registers<i> == ’1’ then
3908 if (BitIsSet (registers, i))
3909 {
3910 if (i < lowest_set_bit)
3911 lowest_set_bit = i;
3912 // if i == n && wback && i != LowestSetBit(registers) then
3913 if ((i == n) && wback && (i != lowest_set_bit))
3914 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3915 WriteBits32UnknownToMemory (address + offset);
3916 else
3917 {
3918 // MemA[address,4] = R[i];
3919 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3920 if (!success)
3921 return false;
3922
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003923 Register data_reg;
3924 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3925 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003926 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003927 return false;
3928 }
3929
3930 // address = address + 4;
3931 offset += addr_byte_size;
3932 }
3933 }
3934
3935 // if registers<15> == ’1’ then // Only possible for encoding A1
3936 // MemA[address,4] = PCStoreValue();
3937 if (BitIsSet (registers, 15))
3938 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003939 Register pc_reg;
3940 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3941 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00003942 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00003943 if (!success)
3944 return false;
3945
Caroline Tice8d681f52011-03-17 23:50:16 +00003946 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003947 return false;
3948 }
3949
3950 // if wback then R[n] = R[n] + 4*BitCount(registers);
3951 if (wback)
3952 {
3953 offset = addr_byte_size * BitCount (registers);
3954 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003955 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003956 addr_t data = address + offset;
3957 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3958 return false;
3959 }
3960 }
3961 return true;
3962}
3963
Caroline Ticeaf556562011-02-15 18:42:15 +00003964// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3965// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3966// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003967bool
3968EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3969{
3970#if 0
3971 if ConditionPassed() then
3972 EncodingSpecificOperations();
3973 address = R[n] - 4*BitCount(registers) + 4;
3974
3975 for i = 0 to 14
3976 if registers<i> == ’1’ then
3977 if i == n && wback && i != LowestSetBit(registers) then
3978 MemA[address,4] = bits(32) UNKNOWN;
3979 else
3980 MemA[address,4] = R[i];
3981 address = address + 4;
3982
3983 if registers<15> == ’1’ then
3984 MemA[address,4] = PCStoreValue();
3985
3986 if wback then R[n] = R[n] - 4*BitCount(registers);
3987#endif
3988
3989 bool success = false;
3990 const uint32_t opcode = OpcodeAsUnsigned (&success);
3991 if (!success)
3992 return false;
3993
3994 if (ConditionPassed ())
3995 {
3996 uint32_t n;
3997 uint32_t registers = 0;
3998 bool wback;
3999 const uint32_t addr_byte_size = GetAddressByteSize();
4000
4001 // EncodingSpecificOperations();
4002 switch (encoding)
4003 {
4004 case eEncodingA1:
4005 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4006 n = Bits32 (opcode, 19, 16);
4007 registers = Bits32 (opcode, 15, 0);
4008 wback = BitIsSet (opcode, 21);
4009
4010 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4011 if ((n == 15) || (BitCount (registers) < 1))
4012 return false;
4013 break;
4014 default:
4015 return false;
4016 }
4017
4018 // address = R[n] - 4*BitCount(registers) + 4;
4019 int32_t offset = 0;
4020 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4021 if (!success)
4022 return false;
4023
4024 address = address - (addr_byte_size * BitCount (registers)) + 4;
4025
4026 EmulateInstruction::Context context;
4027 context.type = EmulateInstruction::eContextRegisterStore;
4028 Register base_reg;
4029 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4030
4031 // for i = 0 to 14
4032 for (int i = 0; i < 14; ++i)
4033 {
4034 int lowest_bit_set = 14;
4035 // if registers<i> == ’1’ then
4036 if (BitIsSet (registers, i))
4037 {
4038 if (i < lowest_bit_set)
4039 lowest_bit_set = i;
4040 //if i == n && wback && i != LowestSetBit(registers) then
4041 if ((i == n) && wback && (i != lowest_bit_set))
4042 // MemA[address,4] = bits(32) UNKNOWN;
4043 WriteBits32UnknownToMemory (address + offset);
4044 else
4045 {
4046 // MemA[address,4] = R[i];
4047 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4048 if (!success)
4049 return false;
4050
4051 Register data_reg;
4052 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4053 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004054 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004055 return false;
4056 }
4057
4058 // address = address + 4;
4059 offset += addr_byte_size;
4060 }
4061 }
4062
4063 // if registers<15> == ’1’ then
4064 // MemA[address,4] = PCStoreValue();
4065 if (BitIsSet (registers, 15))
4066 {
4067 Register pc_reg;
4068 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4069 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004070 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004071 if (!success)
4072 return false;
4073
Caroline Tice8d681f52011-03-17 23:50:16 +00004074 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004075 return false;
4076 }
4077
4078 // if wback then R[n] = R[n] - 4*BitCount(registers);
4079 if (wback)
4080 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004081 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004082 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4083 context.SetImmediateSigned (offset);
4084 addr_t data = address + offset;
4085 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4086 return false;
4087 }
4088 }
4089 return true;
4090}
4091
Caroline Ticeaf556562011-02-15 18:42:15 +00004092// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4093// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4094// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004095bool
4096EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
4097{
4098#if 0
4099 if ConditionPassed() then
4100 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4101 address = R[n] - 4*BitCount(registers);
4102
4103 for i = 0 to 14
4104 if registers<i> == ’1’ then
4105 if i == n && wback && i != LowestSetBit(registers) then
4106 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4107 else
4108 MemA[address,4] = R[i];
4109 address = address + 4;
4110
4111 if registers<15> == ’1’ then // Only possible for encoding A1
4112 MemA[address,4] = PCStoreValue();
4113
4114 if wback then R[n] = R[n] - 4*BitCount(registers);
4115#endif
4116
4117
4118 bool success = false;
4119 const uint32_t opcode = OpcodeAsUnsigned (&success);
4120 if (!success)
4121 return false;
4122
4123 if (ConditionPassed ())
4124 {
4125 uint32_t n;
4126 uint32_t registers = 0;
4127 bool wback;
4128 const uint32_t addr_byte_size = GetAddressByteSize();
4129
4130 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4131 switch (encoding)
4132 {
4133 case eEncodingT1:
4134 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
4135 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4136 {
4137 // See PUSH
4138 }
4139 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
4140 n = Bits32 (opcode, 19, 16);
4141 registers = Bits32 (opcode, 15, 0);
4142 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4143 wback = BitIsSet (opcode, 21);
4144 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4145 if ((n == 15) || BitCount (registers) < 2)
4146 return false;
4147 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
4148 if (wback && BitIsSet (registers, n))
4149 return false;
4150 break;
4151
4152 case eEncodingA1:
4153 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4154 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4155 {
4156 // See Push
4157 }
4158 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4159 n = Bits32 (opcode, 19, 16);
4160 registers = Bits32 (opcode, 15, 0);
4161 wback = BitIsSet (opcode, 21);
4162 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4163 if ((n == 15) || BitCount (registers) < 1)
4164 return false;
4165 break;
4166
4167 default:
4168 return false;
4169 }
4170
4171 // address = R[n] - 4*BitCount(registers);
4172
4173 int32_t offset = 0;
4174 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4175 if (!success)
4176 return false;
4177
4178 address = address - (addr_byte_size * BitCount (registers));
4179
4180 EmulateInstruction::Context context;
4181 context.type = EmulateInstruction::eContextRegisterStore;
4182 Register base_reg;
4183 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4184
4185 // for i = 0 to 14
4186 for (int i = 0; i < 14; ++i)
4187 {
4188 uint32_t lowest_set_bit = 14;
4189 // if registers<i> == ’1’ then
4190 if (BitIsSet (registers, i))
4191 {
4192 if (i < lowest_set_bit)
4193 lowest_set_bit = i;
4194 // if i == n && wback && i != LowestSetBit(registers) then
4195 if ((i == n) && wback && (i != lowest_set_bit))
4196 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4197 WriteBits32UnknownToMemory (address + offset);
4198 else
4199 {
4200 // MemA[address,4] = R[i];
4201 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4202 if (!success)
4203 return false;
4204
4205 Register data_reg;
4206 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4207 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004208 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004209 return false;
4210 }
4211
4212 // address = address + 4;
4213 offset += addr_byte_size;
4214 }
4215 }
4216
4217 // if registers<15> == ’1’ then // Only possible for encoding A1
4218 // MemA[address,4] = PCStoreValue();
4219 if (BitIsSet (registers, 15))
4220 {
4221 Register pc_reg;
4222 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4223 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004224 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004225 if (!success)
4226 return false;
4227
Caroline Tice8d681f52011-03-17 23:50:16 +00004228 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004229 return false;
4230 }
4231
4232 // if wback then R[n] = R[n] - 4*BitCount(registers);
4233 if (wback)
4234 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004235 offset = (addr_byte_size * BitCount (registers)) * -1;
4236 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4237 context.SetImmediateSigned (offset);
4238 addr_t data = address + offset;
4239 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4240 return false;
4241 }
4242 }
4243 return true;
4244}
4245
4246// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4247// from a base register. The consecutive memory locations start just above this address, and the address of the last
4248// of those locations can optionally be written back to the base register.
4249bool
4250EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
4251{
4252#if 0
4253 if ConditionPassed() then
4254 EncodingSpecificOperations();
4255 address = R[n] + 4;
4256
4257 for i = 0 to 14
4258 if registers<i> == ’1’ then
4259 if i == n && wback && i != LowestSetBit(registers) then
4260 MemA[address,4] = bits(32) UNKNOWN;
4261 else
4262 MemA[address,4] = R[i];
4263 address = address + 4;
4264
4265 if registers<15> == ’1’ then
4266 MemA[address,4] = PCStoreValue();
4267
4268 if wback then R[n] = R[n] + 4*BitCount(registers);
4269#endif
4270
4271 bool success = false;
4272 const uint32_t opcode = OpcodeAsUnsigned (&success);
4273 if (!success)
4274 return false;
4275
4276 if (ConditionPassed())
4277 {
4278 uint32_t n;
4279 uint32_t registers = 0;
4280 bool wback;
4281 const uint32_t addr_byte_size = GetAddressByteSize();
4282
4283 // EncodingSpecificOperations();
4284 switch (encoding)
4285 {
4286 case eEncodingA1:
4287 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4288 n = Bits32 (opcode, 19, 16);
4289 registers = Bits32 (opcode, 15, 0);
4290 wback = BitIsSet (opcode, 21);
4291
4292 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4293 if ((n == 15) && (BitCount (registers) < 1))
4294 return false;
4295 break;
4296 default:
4297 return false;
4298 }
4299 // address = R[n] + 4;
4300
4301 int32_t offset = 0;
4302 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4303 if (!success)
4304 return false;
4305
4306 address = address + addr_byte_size;
4307
4308 EmulateInstruction::Context context;
4309 context.type = EmulateInstruction::eContextRegisterStore;
4310 Register base_reg;
4311 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4312
4313 uint32_t lowest_set_bit = 14;
4314 // for i = 0 to 14
4315 for (int i = 0; i < 14; ++i)
4316 {
4317 // if registers<i> == ’1’ then
4318 if (BitIsSet (registers, i))
4319 {
4320 if (i < lowest_set_bit)
4321 lowest_set_bit = i;
4322 // if i == n && wback && i != LowestSetBit(registers) then
4323 if ((i == n) && wback && (i != lowest_set_bit))
4324 // MemA[address,4] = bits(32) UNKNOWN;
4325 WriteBits32UnknownToMemory (address + offset);
4326 // else
4327 else
4328 {
4329 // MemA[address,4] = R[i];
4330 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4331 if (!success)
4332 return false;
4333
4334 Register data_reg;
4335 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4336 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004337 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004338 return false;
4339 }
4340
4341 // address = address + 4;
4342 offset += addr_byte_size;
4343 }
4344 }
4345
4346 // if registers<15> == ’1’ then
4347 // MemA[address,4] = PCStoreValue();
4348 if (BitIsSet (registers, 15))
4349 {
4350 Register pc_reg;
4351 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4352 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004353 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004354 if (!success)
4355 return false;
4356
Caroline Tice8d681f52011-03-17 23:50:16 +00004357 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004358 return false;
4359 }
4360
4361 // if wback then R[n] = R[n] + 4*BitCount(registers);
4362 if (wback)
4363 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004364 offset = addr_byte_size * BitCount (registers);
4365 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4366 context.SetImmediateSigned (offset);
4367 addr_t data = address + offset;
4368 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4369 return false;
4370 }
4371 }
4372 return true;
4373}
Caroline Tice7fac8572011-02-15 22:53:54 +00004374
4375// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4376// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4377bool
4378EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4379{
4380#if 0
4381 if ConditionPassed() then
4382 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4383 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4384 address = if index then offset_addr else R[n];
4385 if UnalignedSupport() || address<1:0> == ’00’ then
4386 MemU[address,4] = R[t];
4387 else // Can only occur before ARMv7
4388 MemU[address,4] = bits(32) UNKNOWN;
4389 if wback then R[n] = offset_addr;
4390#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004391
Caroline Tice7fac8572011-02-15 22:53:54 +00004392 bool success = false;
4393 const uint32_t opcode = OpcodeAsUnsigned (&success);
4394 if (!success)
4395 return false;
4396
4397 if (ConditionPassed())
4398 {
4399 const uint32_t addr_byte_size = GetAddressByteSize();
4400
4401 uint32_t t;
4402 uint32_t n;
4403 uint32_t imm32;
4404 bool index;
4405 bool add;
4406 bool wback;
4407 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4408 switch (encoding)
4409 {
4410 case eEncodingT1:
4411 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4412 t = Bits32 (opcode, 2, 0);
4413 n = Bits32 (opcode, 5, 3);
4414 imm32 = Bits32 (opcode, 10, 6) << 2;
4415
4416 // index = TRUE; add = TRUE; wback = FALSE;
4417 index = true;
4418 add = false;
4419 wback = false;
4420 break;
4421
4422 case eEncodingT2:
4423 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4424 t = Bits32 (opcode, 10, 8);
4425 n = 13;
4426 imm32 = Bits32 (opcode, 7, 0) << 2;
4427
4428 // index = TRUE; add = TRUE; wback = FALSE;
4429 index = true;
4430 add = true;
4431 wback = false;
4432 break;
4433
4434 case eEncodingT3:
4435 // if Rn == ’1111’ then UNDEFINED;
4436 if (Bits32 (opcode, 19, 16) == 15)
4437 return false;
4438
4439 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4440 t = Bits32 (opcode, 15, 12);
4441 n = Bits32 (opcode, 19, 16);
4442 imm32 = Bits32 (opcode, 11, 0);
4443
4444 // index = TRUE; add = TRUE; wback = FALSE;
4445 index = true;
4446 add = true;
4447 wback = false;
4448
4449 // if t == 15 then UNPREDICTABLE;
4450 if (t == 15)
4451 return false;
4452 break;
4453
4454 case eEncodingT4:
4455 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4456 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4457 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4458 if ((Bits32 (opcode, 19, 16) == 15)
4459 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4460 return false;
4461
4462 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4463 t = Bits32 (opcode, 15, 12);
4464 n = Bits32 (opcode, 19, 16);
4465 imm32 = Bits32 (opcode, 7, 0);
4466
4467 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4468 index = BitIsSet (opcode, 10);
4469 add = BitIsSet (opcode, 9);
4470 wback = BitIsSet (opcode, 8);
4471
4472 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4473 if ((t == 15) || (wback && (n == t)))
4474 return false;
4475 break;
4476
4477 default:
4478 return false;
4479 }
4480
4481 addr_t offset_addr;
4482 addr_t address;
4483
4484 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4485 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4486 if (!success)
4487 return false;
4488
4489 if (add)
4490 offset_addr = base_address + imm32;
4491 else
4492 offset_addr = base_address - imm32;
4493
4494 // address = if index then offset_addr else R[n];
4495 if (index)
4496 address = offset_addr;
4497 else
4498 address = base_address;
4499
4500 EmulateInstruction::Context context;
4501 context.type = eContextRegisterStore;
4502 Register base_reg;
4503 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4504
4505 // if UnalignedSupport() || address<1:0> == ’00’ then
4506 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4507 {
4508 // MemU[address,4] = R[t];
4509 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4510 if (!success)
4511 return false;
4512
4513 Register data_reg;
4514 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4515 int32_t offset = address - base_address;
4516 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004517 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004518 return false;
4519 }
4520 else
4521 {
4522 // MemU[address,4] = bits(32) UNKNOWN;
4523 WriteBits32UnknownToMemory (address);
4524 }
4525
4526 // if wback then R[n] = offset_addr;
4527 if (wback)
4528 {
4529 context.type = eContextRegisterLoad;
4530 context.SetAddress (offset_addr);
4531 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4532 return false;
4533 }
4534 }
4535 return true;
4536}
Caroline Ticeaf556562011-02-15 18:42:15 +00004537
Caroline Tice3fd63e92011-02-16 00:33:43 +00004538// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4539// word from a register to memory. The offset register value can optionally be shifted.
4540bool
4541EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4542{
4543#if 0
4544 if ConditionPassed() then
4545 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4546 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4547 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4548 address = if index then offset_addr else R[n];
4549 if t == 15 then // Only possible for encoding A1
4550 data = PCStoreValue();
4551 else
4552 data = R[t];
4553 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4554 MemU[address,4] = data;
4555 else // Can only occur before ARMv7
4556 MemU[address,4] = bits(32) UNKNOWN;
4557 if wback then R[n] = offset_addr;
4558#endif
4559
4560 bool success = false;
4561 const uint32_t opcode = OpcodeAsUnsigned (&success);
4562 if (!success)
4563 return false;
4564
4565 if (ConditionPassed())
4566 {
4567 const uint32_t addr_byte_size = GetAddressByteSize();
4568
4569 uint32_t t;
4570 uint32_t n;
4571 uint32_t m;
4572 ARM_ShifterType shift_t;
4573 uint32_t shift_n;
4574 bool index;
4575 bool add;
4576 bool wback;
4577
4578 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4579 switch (encoding)
4580 {
4581 case eEncodingT1:
4582 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4583 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4584 t = Bits32 (opcode, 2, 0);
4585 n = Bits32 (opcode, 5, 3);
4586 m = Bits32 (opcode, 8, 6);
4587
4588 // index = TRUE; add = TRUE; wback = FALSE;
4589 index = true;
4590 add = true;
4591 wback = false;
4592
4593 // (shift_t, shift_n) = (SRType_LSL, 0);
4594 shift_t = SRType_LSL;
4595 shift_n = 0;
4596 break;
4597
4598 case eEncodingT2:
4599 // if Rn == ’1111’ then UNDEFINED;
4600 if (Bits32 (opcode, 19, 16) == 15)
4601 return false;
4602
4603 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4604 t = Bits32 (opcode, 15, 12);
4605 n = Bits32 (opcode, 19, 16);
4606 m = Bits32 (opcode, 3, 0);
4607
4608 // index = TRUE; add = TRUE; wback = FALSE;
4609 index = true;
4610 add = true;
4611 wback = false;
4612
4613 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4614 shift_t = SRType_LSL;
4615 shift_n = Bits32 (opcode, 5, 4);
4616
4617 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4618 if ((t == 15) || (BadReg (m)))
4619 return false;
4620 break;
4621
4622 case eEncodingA1:
4623 {
4624 // if P == ’0’ && W == ’1’ then SEE STRT;
4625 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4626 t = Bits32 (opcode, 15, 12);
4627 n = Bits32 (opcode, 19, 16);
4628 m = Bits32 (opcode, 3, 0);
4629
4630 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4631 index = BitIsSet (opcode, 24);
4632 add = BitIsSet (opcode, 23);
4633 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4634
4635 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4636 uint32_t typ = Bits32 (opcode, 6, 5);
4637 uint32_t imm5 = Bits32 (opcode, 11, 7);
4638 shift_n = DecodeImmShift(typ, imm5, shift_t);
4639
4640 // if m == 15 then UNPREDICTABLE;
4641 if (m == 15)
4642 return false;
4643
4644 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4645 if (wback && ((n == 15) || (n == t)))
4646 return false;
4647
4648 break;
4649 }
4650 default:
4651 return false;
4652 }
4653
4654 addr_t offset_addr;
4655 addr_t address;
4656 int32_t offset = 0;
4657
4658 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4659 if (!success)
4660 return false;
4661
4662 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4663 if (!success)
4664 return false;
4665
4666 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004667 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004668
4669 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4670 if (add)
4671 offset_addr = base_address + offset;
4672 else
4673 offset_addr = base_address - offset;
4674
4675 // address = if index then offset_addr else R[n];
4676 if (index)
4677 address = offset_addr;
4678 else
4679 address = base_address;
4680
4681 uint32_t data;
4682 // if t == 15 then // Only possible for encoding A1
4683 if (t == 15)
4684 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004685 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004686 else
4687 // data = R[t];
4688 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4689
4690 if (!success)
4691 return false;
4692
4693 EmulateInstruction::Context context;
4694 context.type = eContextRegisterStore;
4695
4696 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4697 if (UnalignedSupport ()
4698 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4699 || CurrentInstrSet() == eModeARM)
4700 {
4701 // MemU[address,4] = data;
4702
4703 Register base_reg;
4704 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4705
4706 Register data_reg;
4707 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4708
4709 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004710 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004711 return false;
4712
4713 }
4714 else
4715 // MemU[address,4] = bits(32) UNKNOWN;
4716 WriteBits32UnknownToMemory (address);
4717
4718 // if wback then R[n] = offset_addr;
4719 if (wback)
4720 {
4721 context.type = eContextRegisterLoad;
4722 context.SetAddress (offset_addr);
4723 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4724 return false;
4725 }
4726
4727 }
4728 return true;
4729}
Caroline Tice73a29de2011-02-16 20:22:22 +00004730
4731bool
4732EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4733{
4734#if 0
4735 if ConditionPassed() then
4736 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4737 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4738 address = if index then offset_addr else R[n];
4739 MemU[address,1] = R[t]<7:0>;
4740 if wback then R[n] = offset_addr;
4741#endif
4742
4743
4744 bool success = false;
4745 const uint32_t opcode = OpcodeAsUnsigned (&success);
4746 if (!success)
4747 return false;
4748
4749 if (ConditionPassed ())
4750 {
4751 uint32_t t;
4752 uint32_t n;
4753 uint32_t imm32;
4754 bool index;
4755 bool add;
4756 bool wback;
4757 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4758 switch (encoding)
4759 {
4760 case eEncodingT1:
4761 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4762 t = Bits32 (opcode, 2, 0);
4763 n = Bits32 (opcode, 5, 3);
4764 imm32 = Bits32 (opcode, 10, 6);
4765
4766 // index = TRUE; add = TRUE; wback = FALSE;
4767 index = true;
4768 add = true;
4769 wback = false;
4770 break;
4771
4772 case eEncodingT2:
4773 // if Rn == ’1111’ then UNDEFINED;
4774 if (Bits32 (opcode, 19, 16) == 15)
4775 return false;
4776
4777 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4778 t = Bits32 (opcode, 15, 12);
4779 n = Bits32 (opcode, 19, 16);
4780 imm32 = Bits32 (opcode, 11, 0);
4781
4782 // index = TRUE; add = TRUE; wback = FALSE;
4783 index = true;
4784 add = true;
4785 wback = false;
4786
4787 // if BadReg(t) then UNPREDICTABLE;
4788 if (BadReg (t))
4789 return false;
4790 break;
4791
4792 case eEncodingT3:
4793 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4794 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4795 if (Bits32 (opcode, 19, 16) == 15)
4796 return false;
4797
4798 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4799 t = Bits32 (opcode, 15, 12);
4800 n = Bits32 (opcode, 19, 16);
4801 imm32 = Bits32 (opcode, 7, 0);
4802
4803 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4804 index = BitIsSet (opcode, 10);
4805 add = BitIsSet (opcode, 9);
4806 wback = BitIsSet (opcode, 8);
4807
4808 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4809 if ((BadReg (t)) || (wback && (n == t)))
4810 return false;
4811 break;
4812
4813 default:
4814 return false;
4815 }
4816
4817 addr_t offset_addr;
4818 addr_t address;
4819 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4820 if (!success)
4821 return false;
4822
4823 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4824 if (add)
4825 offset_addr = base_address + imm32;
4826 else
4827 offset_addr = base_address - imm32;
4828
4829 // address = if index then offset_addr else R[n];
4830 if (index)
4831 address = offset_addr;
4832 else
4833 address = base_address;
4834
Caroline Ticecc96eb52011-02-17 19:20:40 +00004835 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004836 Register base_reg;
4837 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4838
4839 Register data_reg;
4840 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4841
4842 EmulateInstruction::Context context;
4843 context.type = eContextRegisterStore;
4844 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4845
4846 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4847 if (!success)
4848 return false;
4849
4850 data = Bits32 (data, 7, 0);
4851
Caroline Ticecc96eb52011-02-17 19:20:40 +00004852 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004853 return false;
4854
4855 // if wback then R[n] = offset_addr;
4856 if (wback)
4857 {
4858 context.type = eContextRegisterLoad;
4859 context.SetAddress (offset_addr);
4860 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4861 return false;
4862 }
4863
4864 }
4865
4866 return true;
4867}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004868
4869// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4870// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4871bool
4872EmulateInstructionARM::EmulateSTRHRegister (ARMEncoding encoding)
4873{
4874#if 0
4875 if ConditionPassed() then
4876 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4877 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4878 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4879 address = if index then offset_addr else R[n];
4880 if UnalignedSupport() || address<0> == ’0’ then
4881 MemU[address,2] = R[t]<15:0>;
4882 else // Can only occur before ARMv7
4883 MemU[address,2] = bits(16) UNKNOWN;
4884 if wback then R[n] = offset_addr;
4885#endif
4886
4887 bool success = false;
4888 const uint32_t opcode = OpcodeAsUnsigned (&success);
4889 if (!success)
4890 return false;
4891
4892 if (ConditionPassed ())
4893 {
4894 uint32_t t;
4895 uint32_t n;
4896 uint32_t m;
4897 bool index;
4898 bool add;
4899 bool wback;
4900 ARM_ShifterType shift_t;
4901 uint32_t shift_n;
4902
4903 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4904 switch (encoding)
4905 {
4906 case eEncodingT1:
4907 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4908 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4909 t = Bits32 (opcode, 2, 0);
4910 n = Bits32 (opcode, 5, 3);
4911 m = Bits32 (opcode, 8, 6);
4912
4913 // index = TRUE; add = TRUE; wback = FALSE;
4914 index = true;
4915 add = true;
4916 wback = false;
4917
4918 // (shift_t, shift_n) = (SRType_LSL, 0);
4919 shift_t = SRType_LSL;
4920 shift_n = 0;
4921
4922 break;
4923
4924 case eEncodingT2:
4925 // if Rn == ’1111’ then UNDEFINED;
4926 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4927 t = Bits32 (opcode, 15, 12);
4928 n = Bits32 (opcode, 19, 16);
4929 m = Bits32 (opcode, 3, 0);
4930 if (n == 15)
4931 return false;
4932
4933 // index = TRUE; add = TRUE; wback = FALSE;
4934 index = true;
4935 add = true;
4936 wback = false;
4937
4938 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4939 shift_t = SRType_LSL;
4940 shift_n = Bits32 (opcode, 5, 4);
4941
4942 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4943 if (BadReg (t) || BadReg (m))
4944 return false;
4945
4946 break;
4947
4948 case eEncodingA1:
4949 // if P == ’0’ && W == ’1’ then SEE STRHT;
4950 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4951 t = Bits32 (opcode, 15, 12);
4952 n = Bits32 (opcode, 19, 16);
4953 m = Bits32 (opcode, 3, 0);
4954
4955 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4956 index = BitIsSet (opcode, 24);
4957 add = BitIsSet (opcode, 23);
4958 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4959
4960 // (shift_t, shift_n) = (SRType_LSL, 0);
4961 shift_t = SRType_LSL;
4962 shift_n = 0;
4963
4964 // if t == 15 || m == 15 then UNPREDICTABLE;
4965 if ((t == 15) || (m == 15))
4966 return false;
4967
4968 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4969 if (wback && ((n == 15) || (n == t)))
4970 return false;
4971
4972 break;
4973
4974 default:
4975 return false;
4976 }
4977
4978 uint32_t Rm = ReadCoreReg (m, &success);
4979 if (!success)
4980 return false;
4981
4982 uint32_t Rn = ReadCoreReg (n, &success);
4983 if (!success)
4984 return false;
4985
4986 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4987 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
4988
4989 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4990 addr_t offset_addr;
4991 if (add)
4992 offset_addr = Rn + offset;
4993 else
4994 offset_addr = Rn - offset;
4995
4996 // address = if index then offset_addr else R[n];
4997 addr_t address;
4998 if (index)
4999 address = offset_addr;
5000 else
5001 address = Rn;
5002
5003 EmulateInstruction::Context context;
5004 context.type = eContextRegisterStore;
5005 Register base_reg;
5006 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5007 Register offset_reg;
5008 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5009
5010 // if UnalignedSupport() || address<0> == ’0’ then
5011 if (UnalignedSupport() || BitIsClear (address, 0))
5012 {
5013 // MemU[address,2] = R[t]<15:0>;
5014 uint32_t Rt = ReadCoreReg (t, &success);
5015 if (!success)
5016 return false;
5017
5018 EmulateInstruction::Context context;
5019 context.type = eContextRegisterStore;
5020 Register base_reg;
5021 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5022 Register offset_reg;
5023 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
5024 Register data_reg;
5025 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5026 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5027
5028 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5029 return false;
5030 }
5031 else // Can only occur before ARMv7
5032 {
5033 // MemU[address,2] = bits(16) UNKNOWN;
5034 }
5035
5036 // if wback then R[n] = offset_addr;
5037 if (wback)
5038 {
5039 context.type = eContextAdjustBaseRegister;
5040 context.SetAddress (offset_addr);
5041 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5042 return false;
5043 }
5044 }
5045
5046 return true;
5047}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005048
Johnny Chen157b9592011-02-18 21:13:05 +00005049// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5050// and writes the result to the destination register. It can optionally update the condition flags
5051// based on the result.
5052bool
5053EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
5054{
5055#if 0
5056 // ARM pseudo code...
5057 if ConditionPassed() then
5058 EncodingSpecificOperations();
5059 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5060 if d == 15 then // Can only occur for ARM encoding
5061 ALUWritePC(result); // setflags is always FALSE here
5062 else
5063 R[d] = result;
5064 if setflags then
5065 APSR.N = result<31>;
5066 APSR.Z = IsZeroBit(result);
5067 APSR.C = carry;
5068 APSR.V = overflow;
5069#endif
5070
5071 bool success = false;
5072 const uint32_t opcode = OpcodeAsUnsigned (&success);
5073 if (!success)
5074 return false;
5075
5076 if (ConditionPassed())
5077 {
5078 uint32_t Rd, Rn;
5079 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5080 bool setflags;
5081 switch (encoding)
5082 {
5083 case eEncodingT1:
5084 Rd = Bits32(opcode, 11, 8);
5085 Rn = Bits32(opcode, 19, 16);
5086 setflags = BitIsSet(opcode, 20);
5087 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5088 if (BadReg(Rd) || BadReg(Rn))
5089 return false;
5090 break;
5091 case eEncodingA1:
5092 Rd = Bits32(opcode, 15, 12);
5093 Rn = Bits32(opcode, 19, 16);
5094 setflags = BitIsSet(opcode, 20);
5095 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5096 // TODO: Emulate SUBS PC, LR and related instructions.
5097 if (Rd == 15 && setflags)
5098 return false;
5099 break;
5100 default:
5101 return false;
5102 }
5103
5104 // Read the first operand.
5105 int32_t val1 = ReadCoreReg(Rn, &success);
5106 if (!success)
5107 return false;
5108
5109 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5110
5111 EmulateInstruction::Context context;
5112 context.type = EmulateInstruction::eContextImmediate;
5113 context.SetNoArgs ();
5114
5115 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5116 return false;
5117 }
5118 return true;
5119}
5120
5121// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5122// register value, and writes the result to the destination register. It can optionally update the
5123// condition flags based on the result.
5124bool
5125EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
5126{
5127#if 0
5128 // ARM pseudo code...
5129 if ConditionPassed() then
5130 EncodingSpecificOperations();
5131 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5132 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5133 if d == 15 then // Can only occur for ARM encoding
5134 ALUWritePC(result); // setflags is always FALSE here
5135 else
5136 R[d] = result;
5137 if setflags then
5138 APSR.N = result<31>;
5139 APSR.Z = IsZeroBit(result);
5140 APSR.C = carry;
5141 APSR.V = overflow;
5142#endif
5143
5144 bool success = false;
5145 const uint32_t opcode = OpcodeAsUnsigned (&success);
5146 if (!success)
5147 return false;
5148
5149 if (ConditionPassed())
5150 {
5151 uint32_t Rd, Rn, Rm;
5152 ARM_ShifterType shift_t;
5153 uint32_t shift_n; // the shift applied to the value read from Rm
5154 bool setflags;
5155 switch (encoding)
5156 {
5157 case eEncodingT1:
5158 Rd = Rn = Bits32(opcode, 2, 0);
5159 Rm = Bits32(opcode, 5, 3);
5160 setflags = !InITBlock();
5161 shift_t = SRType_LSL;
5162 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005163 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005164 case eEncodingT2:
5165 Rd = Bits32(opcode, 11, 8);
5166 Rn = Bits32(opcode, 19, 16);
5167 Rm = Bits32(opcode, 3, 0);
5168 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005169 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005170 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5171 return false;
5172 break;
5173 case eEncodingA1:
5174 Rd = Bits32(opcode, 15, 12);
5175 Rn = Bits32(opcode, 19, 16);
5176 Rm = Bits32(opcode, 3, 0);
5177 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005178 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005179 // TODO: Emulate SUBS PC, LR and related instructions.
5180 if (Rd == 15 && setflags)
5181 return false;
5182 break;
5183 default:
5184 return false;
5185 }
5186
5187 // Read the first operand.
5188 int32_t val1 = ReadCoreReg(Rn, &success);
5189 if (!success)
5190 return false;
5191
5192 // Read the second operand.
5193 int32_t val2 = ReadCoreReg(Rm, &success);
5194 if (!success)
5195 return false;
5196
5197 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5198 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5199
5200 EmulateInstruction::Context context;
5201 context.type = EmulateInstruction::eContextImmediate;
5202 context.SetNoArgs ();
5203
5204 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5205 return false;
5206 }
5207 return true;
5208}
5209
Johnny Chena695f952011-02-23 21:24:25 +00005210// This instruction adds an immediate value to the PC value to form a PC-relative address,
5211// and writes the result to the destination register.
5212bool
5213EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
5214{
5215#if 0
5216 // ARM pseudo code...
5217 if ConditionPassed() then
5218 EncodingSpecificOperations();
5219 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5220 if d == 15 then // Can only occur for ARM encodings
5221 ALUWritePC(result);
5222 else
5223 R[d] = result;
5224#endif
5225
5226 bool success = false;
5227 const uint32_t opcode = OpcodeAsUnsigned (&success);
5228 if (!success)
5229 return false;
5230
5231 if (ConditionPassed())
5232 {
5233 uint32_t Rd;
5234 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5235 bool add;
5236 switch (encoding)
5237 {
5238 case eEncodingT1:
5239 Rd = Bits32(opcode, 10, 8);
5240 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5241 break;
5242 case eEncodingT2:
5243 case eEncodingT3:
5244 Rd = Bits32(opcode, 11, 8);
5245 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5246 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5247 if (BadReg(Rd))
5248 return false;
5249 break;
5250 case eEncodingA1:
5251 case eEncodingA2:
5252 Rd = Bits32(opcode, 15, 12);
5253 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5254 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5255 break;
5256 default:
5257 return false;
5258 }
5259
5260 // Read the PC value.
5261 uint32_t pc = ReadCoreReg(PC_REG, &success);
5262 if (!success)
5263 return false;
5264
5265 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5266
5267 EmulateInstruction::Context context;
5268 context.type = EmulateInstruction::eContextImmediate;
5269 context.SetNoArgs ();
5270
5271 if (!WriteCoreReg(context, result, Rd))
5272 return false;
5273 }
5274 return true;
5275}
5276
Johnny Chene97c0d52011-02-18 19:32:20 +00005277// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5278// to the destination register. It can optionally update the condition flags based on the result.
5279bool
5280EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
5281{
5282#if 0
5283 // ARM pseudo code...
5284 if ConditionPassed() then
5285 EncodingSpecificOperations();
5286 result = R[n] AND imm32;
5287 if d == 15 then // Can only occur for ARM encoding
5288 ALUWritePC(result); // setflags is always FALSE here
5289 else
5290 R[d] = result;
5291 if setflags then
5292 APSR.N = result<31>;
5293 APSR.Z = IsZeroBit(result);
5294 APSR.C = carry;
5295 // APSR.V unchanged
5296#endif
5297
5298 bool success = false;
5299 const uint32_t opcode = OpcodeAsUnsigned (&success);
5300 if (!success)
5301 return false;
5302
5303 if (ConditionPassed())
5304 {
5305 uint32_t Rd, Rn;
5306 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5307 bool setflags;
5308 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5309 switch (encoding)
5310 {
5311 case eEncodingT1:
5312 Rd = Bits32(opcode, 11, 8);
5313 Rn = Bits32(opcode, 19, 16);
5314 setflags = BitIsSet(opcode, 20);
5315 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005316 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005317 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005318 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005319 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5320 return false;
5321 break;
5322 case eEncodingA1:
5323 Rd = Bits32(opcode, 15, 12);
5324 Rn = Bits32(opcode, 19, 16);
5325 setflags = BitIsSet(opcode, 20);
5326 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5327 // TODO: Emulate SUBS PC, LR and related instructions.
5328 if (Rd == 15 && setflags)
5329 return false;
5330 break;
5331 default:
5332 return false;
5333 }
5334
Johnny Chene97c0d52011-02-18 19:32:20 +00005335 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005336 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005337 if (!success)
5338 return false;
5339
5340 uint32_t result = val1 & imm32;
5341
5342 EmulateInstruction::Context context;
5343 context.type = EmulateInstruction::eContextImmediate;
5344 context.SetNoArgs ();
5345
5346 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5347 return false;
5348 }
5349 return true;
5350}
5351
5352// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5353// and writes the result to the destination register. It can optionally update the condition flags
5354// based on the result.
5355bool
5356EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
5357{
5358#if 0
5359 // ARM pseudo code...
5360 if ConditionPassed() then
5361 EncodingSpecificOperations();
5362 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5363 result = R[n] AND shifted;
5364 if d == 15 then // Can only occur for ARM encoding
5365 ALUWritePC(result); // setflags is always FALSE here
5366 else
5367 R[d] = result;
5368 if setflags then
5369 APSR.N = result<31>;
5370 APSR.Z = IsZeroBit(result);
5371 APSR.C = carry;
5372 // APSR.V unchanged
5373#endif
5374
5375 bool success = false;
5376 const uint32_t opcode = OpcodeAsUnsigned (&success);
5377 if (!success)
5378 return false;
5379
5380 if (ConditionPassed())
5381 {
5382 uint32_t Rd, Rn, Rm;
5383 ARM_ShifterType shift_t;
5384 uint32_t shift_n; // the shift applied to the value read from Rm
5385 bool setflags;
5386 uint32_t carry;
5387 switch (encoding)
5388 {
5389 case eEncodingT1:
5390 Rd = Rn = Bits32(opcode, 2, 0);
5391 Rm = Bits32(opcode, 5, 3);
5392 setflags = !InITBlock();
5393 shift_t = SRType_LSL;
5394 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005395 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005396 case eEncodingT2:
5397 Rd = Bits32(opcode, 11, 8);
5398 Rn = Bits32(opcode, 19, 16);
5399 Rm = Bits32(opcode, 3, 0);
5400 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005401 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005402 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005403 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005404 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005405 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5406 return false;
5407 break;
5408 case eEncodingA1:
5409 Rd = Bits32(opcode, 15, 12);
5410 Rn = Bits32(opcode, 19, 16);
5411 Rm = Bits32(opcode, 3, 0);
5412 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005413 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005414 // TODO: Emulate SUBS PC, LR and related instructions.
5415 if (Rd == 15 && setflags)
5416 return false;
5417 break;
5418 default:
5419 return false;
5420 }
5421
Johnny Chene97c0d52011-02-18 19:32:20 +00005422 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005423 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005424 if (!success)
5425 return false;
5426
5427 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005428 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005429 if (!success)
5430 return false;
5431
5432 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5433 uint32_t result = val1 & shifted;
5434
5435 EmulateInstruction::Context context;
5436 context.type = EmulateInstruction::eContextImmediate;
5437 context.SetNoArgs ();
5438
5439 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5440 return false;
5441 }
5442 return true;
5443}
5444
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005445// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5446// immediate value, and writes the result to the destination register. It can optionally update the
5447// condition flags based on the result.
5448bool
5449EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
5450{
5451#if 0
5452 // ARM pseudo code...
5453 if ConditionPassed() then
5454 EncodingSpecificOperations();
5455 result = R[n] AND NOT(imm32);
5456 if d == 15 then // Can only occur for ARM encoding
5457 ALUWritePC(result); // setflags is always FALSE here
5458 else
5459 R[d] = result;
5460 if setflags then
5461 APSR.N = result<31>;
5462 APSR.Z = IsZeroBit(result);
5463 APSR.C = carry;
5464 // APSR.V unchanged
5465#endif
5466
5467 bool success = false;
5468 const uint32_t opcode = OpcodeAsUnsigned (&success);
5469 if (!success)
5470 return false;
5471
5472 if (ConditionPassed())
5473 {
5474 uint32_t Rd, Rn;
5475 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5476 bool setflags;
5477 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5478 switch (encoding)
5479 {
5480 case eEncodingT1:
5481 Rd = Bits32(opcode, 11, 8);
5482 Rn = Bits32(opcode, 19, 16);
5483 setflags = BitIsSet(opcode, 20);
5484 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5485 if (BadReg(Rd) || BadReg(Rn))
5486 return false;
5487 break;
5488 case eEncodingA1:
5489 Rd = Bits32(opcode, 15, 12);
5490 Rn = Bits32(opcode, 19, 16);
5491 setflags = BitIsSet(opcode, 20);
5492 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5493 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5494 // TODO: Emulate SUBS PC, LR and related instructions.
5495 if (Rd == 15 && setflags)
5496 return false;
5497 break;
5498 default:
5499 return false;
5500 }
5501
5502 // Read the first operand.
5503 uint32_t val1 = ReadCoreReg(Rn, &success);
5504 if (!success)
5505 return false;
5506
5507 uint32_t result = val1 & ~imm32;
5508
5509 EmulateInstruction::Context context;
5510 context.type = EmulateInstruction::eContextImmediate;
5511 context.SetNoArgs ();
5512
5513 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5514 return false;
5515 }
5516 return true;
5517}
5518
5519// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5520// optionally-shifted register value, and writes the result to the destination register.
5521// It can optionally update the condition flags based on the result.
5522bool
5523EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5524{
5525#if 0
5526 // ARM pseudo code...
5527 if ConditionPassed() then
5528 EncodingSpecificOperations();
5529 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5530 result = R[n] AND NOT(shifted);
5531 if d == 15 then // Can only occur for ARM encoding
5532 ALUWritePC(result); // setflags is always FALSE here
5533 else
5534 R[d] = result;
5535 if setflags then
5536 APSR.N = result<31>;
5537 APSR.Z = IsZeroBit(result);
5538 APSR.C = carry;
5539 // APSR.V unchanged
5540#endif
5541
5542 bool success = false;
5543 const uint32_t opcode = OpcodeAsUnsigned (&success);
5544 if (!success)
5545 return false;
5546
5547 if (ConditionPassed())
5548 {
5549 uint32_t Rd, Rn, Rm;
5550 ARM_ShifterType shift_t;
5551 uint32_t shift_n; // the shift applied to the value read from Rm
5552 bool setflags;
5553 uint32_t carry;
5554 switch (encoding)
5555 {
5556 case eEncodingT1:
5557 Rd = Rn = Bits32(opcode, 2, 0);
5558 Rm = Bits32(opcode, 5, 3);
5559 setflags = !InITBlock();
5560 shift_t = SRType_LSL;
5561 shift_n = 0;
5562 break;
5563 case eEncodingT2:
5564 Rd = Bits32(opcode, 11, 8);
5565 Rn = Bits32(opcode, 19, 16);
5566 Rm = Bits32(opcode, 3, 0);
5567 setflags = BitIsSet(opcode, 20);
5568 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5569 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5570 return false;
5571 break;
5572 case eEncodingA1:
5573 Rd = Bits32(opcode, 15, 12);
5574 Rn = Bits32(opcode, 19, 16);
5575 Rm = Bits32(opcode, 3, 0);
5576 setflags = BitIsSet(opcode, 20);
5577 shift_n = DecodeImmShiftARM(opcode, shift_t);
5578 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5579 // TODO: Emulate SUBS PC, LR and related instructions.
5580 if (Rd == 15 && setflags)
5581 return false;
5582 break;
5583 default:
5584 return false;
5585 }
5586
5587 // Read the first operand.
5588 uint32_t val1 = ReadCoreReg(Rn, &success);
5589 if (!success)
5590 return false;
5591
5592 // Read the second operand.
5593 uint32_t val2 = ReadCoreReg(Rm, &success);
5594 if (!success)
5595 return false;
5596
5597 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5598 uint32_t result = val1 & ~shifted;
5599
5600 EmulateInstruction::Context context;
5601 context.type = EmulateInstruction::eContextImmediate;
5602 context.SetNoArgs ();
5603
5604 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5605 return false;
5606 }
5607 return true;
5608}
5609
Caroline Tice4d729c52011-02-18 00:55:53 +00005610// 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 +00005611// 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 +00005612bool
5613EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5614{
5615#if 0
5616 if ConditionPassed() then
5617 EncodingSpecificOperations();
5618 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5619 address = if index then offset_addr else R[n];
5620 data = MemU[address,4];
5621 if wback then R[n] = offset_addr;
5622 if t == 15 then
5623 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5624 elsif UnalignedSupport() || address<1:0> = ’00’ then
5625 R[t] = data;
5626 else // Can only apply before ARMv7
5627 R[t] = ROR(data, 8*UInt(address<1:0>));
5628#endif
5629
5630 bool success = false;
5631 const uint32_t opcode = OpcodeAsUnsigned (&success);
5632 if (!success)
5633 return false;
5634
5635 if (ConditionPassed ())
5636 {
5637 const uint32_t addr_byte_size = GetAddressByteSize();
5638
5639 uint32_t t;
5640 uint32_t n;
5641 uint32_t imm32;
5642 bool index;
5643 bool add;
5644 bool wback;
5645
5646 switch (encoding)
5647 {
5648 case eEncodingA1:
5649 // if Rn == ’1111’ then SEE LDR (literal);
5650 // if P == ’0’ && W == ’1’ then SEE LDRT;
5651 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5652 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5653 t = Bits32 (opcode, 15, 12);
5654 n = Bits32 (opcode, 19, 16);
5655 imm32 = Bits32 (opcode, 11, 0);
5656
5657 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5658 index = BitIsSet (opcode, 24);
5659 add = BitIsSet (opcode, 23);
5660 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5661
5662 // if wback && n == t then UNPREDICTABLE;
5663 if (wback && (n == t))
5664 return false;
5665
5666 break;
5667
5668 default:
5669 return false;
5670 }
5671
5672 addr_t address;
5673 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005674 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005675 if (!success)
5676 return false;
5677
5678 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5679 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005680 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005681 else
5682 offset_addr = base_address - imm32;
5683
5684 // address = if index then offset_addr else R[n];
5685 if (index)
5686 address = offset_addr;
5687 else
5688 address = base_address;
5689
5690 // data = MemU[address,4];
5691
5692 Register base_reg;
5693 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5694
5695 EmulateInstruction::Context context;
5696 context.type = eContextRegisterLoad;
5697 context.SetRegisterPlusOffset (base_reg, address - base_address);
5698
5699 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5700 if (!success)
5701 return false;
5702
5703 // if wback then R[n] = offset_addr;
5704 if (wback)
5705 {
5706 context.type = eContextAdjustBaseRegister;
5707 context.SetAddress (offset_addr);
5708 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5709 return false;
5710 }
5711
5712 // if t == 15 then
5713 if (t == 15)
5714 {
5715 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5716 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5717 {
5718 // LoadWritePC (data);
5719 context.type = eContextRegisterLoad;
5720 context.SetRegisterPlusOffset (base_reg, address - base_address);
5721 LoadWritePC (context, data);
5722 }
5723 else
5724 return false;
5725 }
5726 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5727 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5728 {
5729 // R[t] = data;
5730 context.type = eContextRegisterLoad;
5731 context.SetRegisterPlusOffset (base_reg, address - base_address);
5732 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5733 return false;
5734 }
5735 // else // Can only apply before ARMv7
5736 else
5737 {
5738 // R[t] = ROR(data, 8*UInt(address<1:0>));
5739 data = ROR (data, Bits32 (address, 1, 0));
5740 context.type = eContextRegisterLoad;
5741 context.SetImmediate (data);
5742 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5743 return false;
5744 }
5745
5746 }
5747 return true;
5748}
5749
Caroline Ticefe479112011-02-18 18:52:37 +00005750// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5751// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5752bool
5753EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5754{
5755#if 0
5756 if ConditionPassed() then
5757 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5758 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5759 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5760 address = if index then offset_addr else R[n];
5761 data = MemU[address,4];
5762 if wback then R[n] = offset_addr;
5763 if t == 15 then
5764 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5765 elsif UnalignedSupport() || address<1:0> = ’00’ then
5766 R[t] = data;
5767 else // Can only apply before ARMv7
5768 if CurrentInstrSet() == InstrSet_ARM then
5769 R[t] = ROR(data, 8*UInt(address<1:0>));
5770 else
5771 R[t] = bits(32) UNKNOWN;
5772#endif
5773
5774 bool success = false;
5775 const uint32_t opcode = OpcodeAsUnsigned (&success);
5776 if (!success)
5777 return false;
5778
5779 if (ConditionPassed ())
5780 {
5781 const uint32_t addr_byte_size = GetAddressByteSize();
5782
5783 uint32_t t;
5784 uint32_t n;
5785 uint32_t m;
5786 bool index;
5787 bool add;
5788 bool wback;
5789 ARM_ShifterType shift_t;
5790 uint32_t shift_n;
5791
5792 switch (encoding)
5793 {
5794 case eEncodingT1:
5795 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5796 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5797 t = Bits32 (opcode, 2, 0);
5798 n = Bits32 (opcode, 5, 3);
5799 m = Bits32 (opcode, 8, 6);
5800
5801 // index = TRUE; add = TRUE; wback = FALSE;
5802 index = true;
5803 add = true;
5804 wback = false;
5805
5806 // (shift_t, shift_n) = (SRType_LSL, 0);
5807 shift_t = SRType_LSL;
5808 shift_n = 0;
5809
5810 break;
5811
5812 case eEncodingT2:
5813 // if Rn == ’1111’ then SEE LDR (literal);
5814 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5815 t = Bits32 (opcode, 15, 12);
5816 n = Bits32 (opcode, 19, 16);
5817 m = Bits32 (opcode, 3, 0);
5818
5819 // index = TRUE; add = TRUE; wback = FALSE;
5820 index = true;
5821 add = true;
5822 wback = false;
5823
5824 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5825 shift_t = SRType_LSL;
5826 shift_n = Bits32 (opcode, 5, 4);
5827
5828 // if BadReg(m) then UNPREDICTABLE;
5829 if (BadReg (m))
5830 return false;
5831
5832 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5833 if ((t == 15) && InITBlock() && !LastInITBlock())
5834 return false;
5835
5836 break;
5837
5838 case eEncodingA1:
5839 {
5840 // if P == ’0’ && W == ’1’ then SEE LDRT;
5841 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5842 t = Bits32 (opcode, 15, 12);
5843 n = Bits32 (opcode, 19, 16);
5844 m = Bits32 (opcode, 3, 0);
5845
5846 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5847 index = BitIsSet (opcode, 24);
5848 add = BitIsSet (opcode, 23);
5849 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5850
5851 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5852 uint32_t type = Bits32 (opcode, 6, 5);
5853 uint32_t imm5 = Bits32 (opcode, 11, 7);
5854 shift_n = DecodeImmShift (type, imm5, shift_t);
5855
5856 // if m == 15 then UNPREDICTABLE;
5857 if (m == 15)
5858 return false;
5859
5860 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5861 if (wback && ((n == 15) || (n == t)))
5862 return false;
5863 }
5864 break;
5865
5866
5867 default:
5868 return false;
5869 }
5870
5871 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5872 if (!success)
5873 return false;
5874
5875 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5876 if (!success)
5877 return false;
5878
5879 addr_t offset_addr;
5880 addr_t address;
5881
5882 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Johnny Chen90e607b2011-02-23 00:07:09 +00005883 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005884
5885 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5886 if (add)
5887 offset_addr = Rn + offset;
5888 else
5889 offset_addr = Rn - offset;
5890
5891 // address = if index then offset_addr else R[n];
5892 if (index)
5893 address = offset_addr;
5894 else
5895 address = Rn;
5896
5897 // data = MemU[address,4];
5898 Register base_reg;
5899 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5900
5901 EmulateInstruction::Context context;
5902 context.type = eContextRegisterLoad;
5903 context.SetRegisterPlusOffset (base_reg, address - Rn);
5904
5905 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5906 if (!success)
5907 return false;
5908
5909 // if wback then R[n] = offset_addr;
5910 if (wback)
5911 {
5912 context.type = eContextAdjustBaseRegister;
5913 context.SetAddress (offset_addr);
5914 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5915 return false;
5916 }
5917
5918 // if t == 15 then
5919 if (t == 15)
5920 {
5921 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5922 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5923 {
5924 context.type = eContextRegisterLoad;
5925 context.SetRegisterPlusOffset (base_reg, address - Rn);
5926 LoadWritePC (context, data);
5927 }
5928 else
5929 return false;
5930 }
5931 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5932 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5933 {
5934 // R[t] = data;
5935 context.type = eContextRegisterLoad;
5936 context.SetRegisterPlusOffset (base_reg, address - Rn);
5937 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5938 return false;
5939 }
5940 else // Can only apply before ARMv7
5941 {
5942 // if CurrentInstrSet() == InstrSet_ARM then
5943 if (CurrentInstrSet () == eModeARM)
5944 {
5945 // R[t] = ROR(data, 8*UInt(address<1:0>));
5946 data = ROR (data, Bits32 (address, 1, 0));
5947 context.type = eContextRegisterLoad;
5948 context.SetImmediate (data);
5949 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5950 return false;
5951 }
5952 else
5953 {
5954 // R[t] = bits(32) UNKNOWN;
5955 WriteBits32Unknown (t);
5956 }
5957 }
5958 }
5959 return true;
5960}
Caroline Tice21b604b2011-02-18 21:06:04 +00005961
5962// LDRB (immediate, Thumb)
5963bool
5964EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5965{
5966#if 0
5967 if ConditionPassed() then
5968 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5969 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5970 address = if index then offset_addr else R[n];
5971 R[t] = ZeroExtend(MemU[address,1], 32);
5972 if wback then R[n] = offset_addr;
5973#endif
5974
5975 bool success = false;
5976 const uint32_t opcode = OpcodeAsUnsigned (&success);
5977 if (!success)
5978 return false;
5979
5980 if (ConditionPassed ())
5981 {
5982 uint32_t t;
5983 uint32_t n;
5984 uint32_t imm32;
5985 bool index;
5986 bool add;
5987 bool wback;
5988
5989 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5990 switch (encoding)
5991 {
5992 case eEncodingT1:
5993 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5994 t = Bits32 (opcode, 2, 0);
5995 n = Bits32 (opcode, 5, 3);
5996 imm32 = Bits32 (opcode, 10, 6);
5997
5998 // index = TRUE; add = TRUE; wback = FALSE;
5999 index = true;
6000 add = true;
6001 wback= false;
6002
6003 break;
6004
6005 case eEncodingT2:
6006 // if Rt == ’1111’ then SEE PLD;
6007 // if Rn == ’1111’ then SEE LDRB (literal);
6008 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6009 t = Bits32 (opcode, 15, 12);
6010 n = Bits32 (opcode, 19, 16);
6011 imm32 = Bits32 (opcode, 11, 0);
6012
6013 // index = TRUE; add = TRUE; wback = FALSE;
6014 index = true;
6015 add = true;
6016 wback = false;
6017
6018 // if t == 13 then UNPREDICTABLE;
6019 if (t == 13)
6020 return false;
6021
6022 break;
6023
6024 case eEncodingT3:
6025 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
6026 // if Rn == ’1111’ then SEE LDRB (literal);
6027 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
6028 // if P == ’0’ && W == ’0’ then UNDEFINED;
6029 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6030 return false;
6031
6032 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6033 t = Bits32 (opcode, 15, 12);
6034 n = Bits32 (opcode, 19, 16);
6035 imm32 = Bits32 (opcode, 7, 0);
6036
6037 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6038 index = BitIsSet (opcode, 10);
6039 add = BitIsSet (opcode, 9);
6040 wback = BitIsSet (opcode, 8);
6041
6042 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6043 if (BadReg (t) || (wback && (n == t)))
6044 return false;
6045
6046 break;
6047
6048 default:
6049 return false;
6050 }
6051
6052 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6053 if (!success)
6054 return false;
6055
6056 addr_t address;
6057 addr_t offset_addr;
6058
6059 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6060 if (add)
6061 offset_addr = Rn + imm32;
6062 else
6063 offset_addr = Rn - imm32;
6064
6065 // address = if index then offset_addr else R[n];
6066 if (index)
6067 address = offset_addr;
6068 else
6069 address = Rn;
6070
6071 // R[t] = ZeroExtend(MemU[address,1], 32);
6072 Register base_reg;
6073 Register data_reg;
6074 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6075 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6076
6077 EmulateInstruction::Context context;
6078 context.type = eContextRegisterLoad;
6079 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6080
6081 uint64_t data = MemURead (context, address, 1, 0, &success);
6082 if (!success)
6083 return false;
6084
6085 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6086 return false;
6087
6088 // if wback then R[n] = offset_addr;
6089 if (wback)
6090 {
6091 context.type = eContextAdjustBaseRegister;
6092 context.SetAddress (offset_addr);
6093 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6094 return false;
6095 }
6096 }
6097 return true;
6098}
Caroline Ticef55261f2011-02-18 22:24:22 +00006099
6100// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6101// zero-extends it to form a 32-bit word and writes it to a register.
6102bool
6103EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
6104{
6105#if 0
6106 if ConditionPassed() then
6107 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6108 base = Align(PC,4);
6109 address = if add then (base + imm32) else (base - imm32);
6110 R[t] = ZeroExtend(MemU[address,1], 32);
6111#endif
6112
6113 bool success = false;
6114 const uint32_t opcode = OpcodeAsUnsigned (&success);
6115 if (!success)
6116 return false;
6117
6118 if (ConditionPassed ())
6119 {
6120 uint32_t t;
6121 uint32_t imm32;
6122 bool add;
6123 switch (encoding)
6124 {
6125 case eEncodingT1:
6126 // if Rt == ’1111’ then SEE PLD;
6127 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6128 t = Bits32 (opcode, 15, 12);
6129 imm32 = Bits32 (opcode, 11, 0);
6130 add = BitIsSet (opcode, 23);
6131
6132 // if t == 13 then UNPREDICTABLE;
6133 if (t == 13)
6134 return false;
6135
6136 break;
6137
6138 case eEncodingA1:
6139 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6140 t = Bits32 (opcode, 15, 12);
6141 imm32 = Bits32 (opcode, 11, 0);
6142 add = BitIsSet (opcode, 23);
6143
6144 // if t == 15 then UNPREDICTABLE;
6145 if (t == 15)
6146 return false;
6147 break;
6148
6149 default:
6150 return false;
6151 }
6152
6153 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006154 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006155 if (!success)
6156 return false;
6157
6158 uint32_t base = AlignPC (pc_val);
6159
6160 addr_t address;
6161 // address = if add then (base + imm32) else (base - imm32);
6162 if (add)
6163 address = base + imm32;
6164 else
6165 address = base - imm32;
6166
6167 // R[t] = ZeroExtend(MemU[address,1], 32);
6168 EmulateInstruction::Context context;
6169 context.type = eContextRelativeBranchImmediate;
6170 context.SetImmediate (address - base);
6171
6172 uint64_t data = MemURead (context, address, 1, 0, &success);
6173 if (!success)
6174 return false;
6175
6176 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6177 return false;
6178 }
6179 return true;
6180}
Caroline Tice30fec122011-02-18 23:52:21 +00006181
6182// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6183// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6184// optionally be shifted.
6185bool
6186EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
6187{
6188#if 0
6189 if ConditionPassed() then
6190 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6191 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6192 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6193 address = if index then offset_addr else R[n];
6194 R[t] = ZeroExtend(MemU[address,1],32);
6195 if wback then R[n] = offset_addr;
6196#endif
6197
6198 bool success = false;
6199 const uint32_t opcode = OpcodeAsUnsigned (&success);
6200 if (!success)
6201 return false;
6202
6203 if (ConditionPassed ())
6204 {
6205 uint32_t t;
6206 uint32_t n;
6207 uint32_t m;
6208 bool index;
6209 bool add;
6210 bool wback;
6211 ARM_ShifterType shift_t;
6212 uint32_t shift_n;
6213
6214 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6215 switch (encoding)
6216 {
6217 case eEncodingT1:
6218 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6219 t = Bits32 (opcode, 2, 0);
6220 n = Bits32 (opcode, 5, 3);
6221 m = Bits32 (opcode, 8, 6);
6222
6223 // index = TRUE; add = TRUE; wback = FALSE;
6224 index = true;
6225 add = true;
6226 wback = false;
6227
6228 // (shift_t, shift_n) = (SRType_LSL, 0);
6229 shift_t = SRType_LSL;
6230 shift_n = 0;
6231 break;
6232
6233 case eEncodingT2:
6234 // if Rt == ’1111’ then SEE PLD;
6235 // if Rn == ’1111’ then SEE LDRB (literal);
6236 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6237 t = Bits32 (opcode, 15, 12);
6238 n = Bits32 (opcode, 19, 16);
6239 m = Bits32 (opcode, 3, 0);
6240
6241 // index = TRUE; add = TRUE; wback = FALSE;
6242 index = true;
6243 add = true;
6244 wback = false;
6245
6246 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6247 shift_t = SRType_LSL;
6248 shift_n = Bits32 (opcode, 5, 4);
6249
6250 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6251 if ((t == 13) || BadReg (m))
6252 return false;
6253 break;
6254
6255 case eEncodingA1:
6256 {
6257 // if P == ’0’ && W == ’1’ then SEE LDRBT;
6258 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6259 t = Bits32 (opcode, 15, 12);
6260 n = Bits32 (opcode, 19, 16);
6261 m = Bits32 (opcode, 3, 0);
6262
6263 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6264 index = BitIsSet (opcode, 24);
6265 add = BitIsSet (opcode, 23);
6266 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6267
6268 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6269 uint32_t type = Bits32 (opcode, 6, 5);
6270 uint32_t imm5 = Bits32 (opcode, 11, 7);
6271 shift_n = DecodeImmShift (type, imm5, shift_t);
6272
6273 // if t == 15 || m == 15 then UNPREDICTABLE;
6274 if ((t == 15) || (m == 15))
6275 return false;
6276
6277 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6278 if (wback && ((n == 15) || (n == t)))
6279 return false;
6280 }
6281 break;
6282
6283 default:
6284 return false;
6285 }
6286
6287 addr_t offset_addr;
6288 addr_t address;
6289
6290 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6291 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6292 if (!success)
6293 return false;
6294
6295 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6296
6297 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6298 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6299 if (!success)
6300 return false;
6301
6302 if (add)
6303 offset_addr = Rn + offset;
6304 else
6305 offset_addr = Rn - offset;
6306
6307 // address = if index then offset_addr else R[n];
6308 if (index)
6309 address = offset_addr;
6310 else
6311 address = Rn;
6312
6313 // R[t] = ZeroExtend(MemU[address,1],32);
6314 Register base_reg;
6315 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6316
6317 EmulateInstruction::Context context;
6318 context.type = eContextRegisterLoad;
6319 context.SetRegisterPlusOffset (base_reg, address - Rn);
6320
6321 uint64_t data = MemURead (context, address, 1, 0, &success);
6322 if (!success)
6323 return false;
6324
6325 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6326 return false;
6327
6328 // if wback then R[n] = offset_addr;
6329 if (wback)
6330 {
6331 context.type = eContextAdjustBaseRegister;
6332 context.SetAddress (offset_addr);
6333 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6334 return false;
6335 }
6336 }
6337 return true;
6338}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006339
6340// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6341// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6342// post-indexed, or pre-indexed addressing.
6343bool
6344EmulateInstructionARM::EmulateLDRHImmediate (ARMEncoding encoding)
6345{
6346#if 0
6347 if ConditionPassed() then
6348 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6349 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6350 address = if index then offset_addr else R[n];
6351 data = MemU[address,2];
6352 if wback then R[n] = offset_addr;
6353 if UnalignedSupport() || address<0> = ’0’ then
6354 R[t] = ZeroExtend(data, 32);
6355 else // Can only apply before ARMv7
6356 R[t] = bits(32) UNKNOWN;
6357#endif
6358
6359
6360 bool success = false;
6361 const uint32_t opcode = OpcodeAsUnsigned (&success);
6362 if (!success)
6363 return false;
6364
6365 if (ConditionPassed())
6366 {
6367 uint32_t t;
6368 uint32_t n;
6369 uint32_t imm32;
6370 bool index;
6371 bool add;
6372 bool wback;
6373
6374 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6375 switch (encoding)
6376 {
6377 case eEncodingT1:
6378 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
6379 t = Bits32 (opcode, 2, 0);
6380 n = Bits32 (opcode, 5, 3);
6381 imm32 = Bits32 (opcode, 10, 6) << 1;
6382
6383 // index = TRUE; add = TRUE; wback = FALSE;
6384 index = true;
6385 add = true;
6386 wback = false;
6387
6388 break;
6389
6390 case eEncodingT2:
6391 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6392 // if Rn == ’1111’ then SEE LDRH (literal);
6393 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6394 t = Bits32 (opcode, 15, 12);
6395 n = Bits32 (opcode, 19, 16);
6396 imm32 = Bits32 (opcode, 11, 0);
6397
6398 // index = TRUE; add = TRUE; wback = FALSE;
6399 index = true;
6400 add = true;
6401 wback = false;
6402
6403 // if t == 13 then UNPREDICTABLE;
6404 if (t == 13)
6405 return false;
6406 break;
6407
6408 case eEncodingT3:
6409 // if Rn == ’1111’ then SEE LDRH (literal);
6410 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6411 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
6412 // if P == ’0’ && W == ’0’ then UNDEFINED;
6413 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6414 return false;
6415
6416 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6417 t = Bits32 (opcode, 15, 12);
6418 n = Bits32 (opcode, 19, 16);
6419 imm32 = Bits32 (opcode, 7, 0);
6420
6421 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6422 index = BitIsSet (opcode, 10);
6423 add = BitIsSet (opcode, 9);
6424 wback = BitIsSet (opcode, 8);
6425
6426 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6427 if (BadReg (t) || (wback && (n == t)))
6428 return false;
6429 break;
6430
6431 default:
6432 return false;
6433 }
6434
6435 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6436 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6437 if (!success)
6438 return false;
6439
6440 addr_t offset_addr;
6441 addr_t address;
6442
6443 if (add)
6444 offset_addr = Rn + imm32;
6445 else
6446 offset_addr = Rn - imm32;
6447
6448 // address = if index then offset_addr else R[n];
6449 if (index)
6450 address = offset_addr;
6451 else
6452 address = Rn;
6453
6454 // data = MemU[address,2];
6455 Register base_reg;
6456 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6457
6458 EmulateInstruction::Context context;
6459 context.type = eContextRegisterLoad;
6460 context.SetRegisterPlusOffset (base_reg, address - Rn);
6461
6462 uint64_t data = MemURead (context, address, 2, 0, &success);
6463 if (!success)
6464 return false;
6465
6466 // if wback then R[n] = offset_addr;
6467 if (wback)
6468 {
6469 context.type = eContextAdjustBaseRegister;
6470 context.SetAddress (offset_addr);
6471 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6472 return false;
6473 }
6474
6475 // if UnalignedSupport() || address<0> = ’0’ then
6476 if (UnalignedSupport () || BitIsClear (address, 0))
6477 {
6478 // R[t] = ZeroExtend(data, 32);
6479 context.type = eContextRegisterLoad;
6480 context.SetRegisterPlusOffset (base_reg, address - Rn);
6481 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6482 return false;
6483 }
6484 else // Can only apply before ARMv7
6485 {
6486 // R[t] = bits(32) UNKNOWN;
6487 WriteBits32Unknown (t);
6488 }
6489 }
6490 return true;
6491}
Caroline Ticefe479112011-02-18 18:52:37 +00006492
Caroline Tice952b5382011-02-28 23:15:24 +00006493// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6494// zero-extends it to form a 32-bit word, and writes it to a register.
6495bool
6496EmulateInstructionARM::EmulateLDRHLiteral (ARMEncoding encoding)
6497{
6498#if 0
6499 if ConditionPassed() then
6500 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6501 base = Align(PC,4);
6502 address = if add then (base + imm32) else (base - imm32);
6503 data = MemU[address,2];
6504 if UnalignedSupport() || address<0> = ’0’ then
6505 R[t] = ZeroExtend(data, 32);
6506 else // Can only apply before ARMv7
6507 R[t] = bits(32) UNKNOWN;
6508#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006509
Caroline Tice952b5382011-02-28 23:15:24 +00006510 bool success = false;
6511 const uint32_t opcode = OpcodeAsUnsigned (&success);
6512 if (!success)
6513 return false;
6514
6515 if (ConditionPassed())
6516 {
6517 uint32_t t;
6518 uint32_t imm32;
6519 bool add;
6520
6521 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6522 switch (encoding)
6523 {
6524 case eEncodingT1:
6525 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6526 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6527 t = Bits32 (opcode, 15, 12);
6528 imm32 = Bits32 (opcode, 11, 0);
6529 add = BitIsSet (opcode, 23);
6530
6531 // if t == 13 then UNPREDICTABLE;
6532 if (t == 13)
6533 return false;
6534
6535 break;
6536
6537 case eEncodingA1:
6538 {
6539 uint32_t imm4H = Bits32 (opcode, 11, 8);
6540 uint32_t imm4L = Bits32 (opcode, 3, 0);
6541
6542 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6543 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006544 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006545 add = BitIsSet (opcode, 23);
6546
6547 // if t == 15 then UNPREDICTABLE;
6548 if (t == 15)
6549 return false;
6550 break;
6551 }
6552
6553 default:
6554 return false;
6555 }
6556
6557 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006558 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006559 if (!success)
6560 return false;
6561
6562 addr_t base = AlignPC (pc_value);
6563 addr_t address;
6564
6565 // address = if add then (base + imm32) else (base - imm32);
6566 if (add)
6567 address = base + imm32;
6568 else
6569 address = base - imm32;
6570
6571 // data = MemU[address,2];
6572 Register base_reg;
6573 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6574
6575 EmulateInstruction::Context context;
6576 context.type = eContextRegisterLoad;
6577 context.SetRegisterPlusOffset (base_reg, address - base);
6578
6579 uint64_t data = MemURead (context, address, 2, 0, &success);
6580 if (!success)
6581 return false;
6582
6583
6584 // if UnalignedSupport() || address<0> = ’0’ then
6585 if (UnalignedSupport () || BitIsClear (address, 0))
6586 {
6587 // R[t] = ZeroExtend(data, 32);
6588 context.type = eContextRegisterLoad;
6589 context.SetRegisterPlusOffset (base_reg, address - base);
6590 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6591 return false;
6592
6593 }
6594 else // Can only apply before ARMv7
6595 {
6596 // R[t] = bits(32) UNKNOWN;
6597 WriteBits32Unknown (t);
6598 }
6599 }
6600 return true;
6601}
6602
Caroline Tice0e6bc952011-03-01 18:00:42 +00006603// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6604// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6605// be shifted left by 0, 1, 2, or 3 bits.
6606bool
6607EmulateInstructionARM::EmulateLDRHRegister (ARMEncoding encoding)
6608{
6609#if 0
6610 if ConditionPassed() then
6611 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6612 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6613 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6614 address = if index then offset_addr else R[n];
6615 data = MemU[address,2];
6616 if wback then R[n] = offset_addr;
6617 if UnalignedSupport() || address<0> = ’0’ then
6618 R[t] = ZeroExtend(data, 32);
6619 else // Can only apply before ARMv7
6620 R[t] = bits(32) UNKNOWN;
6621#endif
6622
6623 bool success = false;
6624 const uint32_t opcode = OpcodeAsUnsigned (&success);
6625 if (!success)
6626 return false;
6627
6628 if (ConditionPassed())
6629 {
6630 uint32_t t;
6631 uint32_t n;
6632 uint32_t m;
6633 bool index;
6634 bool add;
6635 bool wback;
6636 ARM_ShifterType shift_t;
6637 uint32_t shift_n;
6638
6639 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6640 switch (encoding)
6641 {
6642 case eEncodingT1:
6643 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6644 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6645 t = Bits32 (opcode, 2, 0);
6646 n = Bits32 (opcode, 5, 3);
6647 m = Bits32 (opcode, 8, 6);
6648
6649 // index = TRUE; add = TRUE; wback = FALSE;
6650 index = true;
6651 add = true;
6652 wback = false;
6653
6654 // (shift_t, shift_n) = (SRType_LSL, 0);
6655 shift_t = SRType_LSL;
6656 shift_n = 0;
6657
6658 break;
6659
6660 case eEncodingT2:
6661 // if Rn == ’1111’ then SEE LDRH (literal);
6662 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6663 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6664 t = Bits32 (opcode, 15, 12);
6665 n = Bits32 (opcode, 19, 16);
6666 m = Bits32 (opcode, 3, 0);
6667
6668 // index = TRUE; add = TRUE; wback = FALSE;
6669 index = true;
6670 add = true;
6671 wback = false;
6672
6673 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6674 shift_t = SRType_LSL;
6675 shift_n = Bits32 (opcode, 5, 4);
6676
6677 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6678 if ((t == 13) || BadReg (m))
6679 return false;
6680 break;
6681
6682 case eEncodingA1:
6683 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6684 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6685 t = Bits32 (opcode, 15, 12);
6686 n = Bits32 (opcode, 19, 16);
6687 m = Bits32 (opcode, 3, 0);
6688
6689 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6690 index = BitIsSet (opcode, 24);
6691 add = BitIsSet (opcode, 23);
6692 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6693
6694 // (shift_t, shift_n) = (SRType_LSL, 0);
6695 shift_t = SRType_LSL;
6696 shift_n = 0;
6697
6698 // if t == 15 || m == 15 then UNPREDICTABLE;
6699 if ((t == 15) || (m == 15))
6700 return false;
6701
6702 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6703 if (wback && ((n == 15) || (n == t)))
6704 return false;
6705
6706 break;
6707
6708 default:
6709 return false;
6710 }
6711
6712 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6713
6714 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6715 if (!success)
6716 return false;
6717
6718 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6719
6720 addr_t offset_addr;
6721 addr_t address;
6722
6723 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6724 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6725 if (!success)
6726 return false;
6727
6728 if (add)
6729 offset_addr = Rn + offset;
6730 else
6731 offset_addr = Rn - offset;
6732
6733 // address = if index then offset_addr else R[n];
6734 if (index)
6735 address = offset_addr;
6736 else
6737 address = Rn;
6738
6739 // data = MemU[address,2];
6740 Register base_reg;
6741 Register offset_reg;
6742 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6743 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6744
6745 EmulateInstruction::Context context;
6746 context.type = eContextRegisterLoad;
6747 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6748 uint64_t data = MemURead (context, address, 2, 0, &success);
6749 if (!success)
6750 return false;
6751
6752 // if wback then R[n] = offset_addr;
6753 if (wback)
6754 {
6755 context.type = eContextAdjustBaseRegister;
6756 context.SetAddress (offset_addr);
6757 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6758 return false;
6759 }
6760
6761 // if UnalignedSupport() || address<0> = ’0’ then
6762 if (UnalignedSupport() || BitIsClear (address, 0))
6763 {
6764 // R[t] = ZeroExtend(data, 32);
6765 context.type = eContextRegisterLoad;
6766 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6767 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6768 return false;
6769 }
6770 else // Can only apply before ARMv7
6771 {
6772 // R[t] = bits(32) UNKNOWN;
6773 WriteBits32Unknown (t);
6774 }
6775 }
6776 return true;
6777}
6778
Caroline Ticea5e28af2011-03-01 21:53:03 +00006779// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6780// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6781// or pre-indexed addressing.
6782bool
6783EmulateInstructionARM::EmulateLDRSBImmediate (ARMEncoding encoding)
6784{
6785#if 0
6786 if ConditionPassed() then
6787 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6788 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6789 address = if index then offset_addr else R[n];
6790 R[t] = SignExtend(MemU[address,1], 32);
6791 if wback then R[n] = offset_addr;
6792#endif
6793
6794 bool success = false;
6795 const uint32_t opcode = OpcodeAsUnsigned (&success);
6796 if (!success)
6797 return false;
6798
6799 if (ConditionPassed ())
6800 {
6801 uint32_t t;
6802 uint32_t n;
6803 uint32_t imm32;
6804 bool index;
6805 bool add;
6806 bool wback;
6807
6808 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6809 switch (encoding)
6810 {
6811 case eEncodingT1:
6812 // if Rt == ’1111’ then SEE PLI;
6813 // if Rn == ’1111’ then SEE LDRSB (literal);
6814 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6815 t = Bits32 (opcode, 15, 12);
6816 n = Bits32 (opcode, 19, 16);
6817 imm32 = Bits32 (opcode, 11, 0);
6818
6819 // index = TRUE; add = TRUE; wback = FALSE;
6820 index = true;
6821 add = true;
6822 wback = false;
6823
6824 // if t == 13 then UNPREDICTABLE;
6825 if (t == 13)
6826 return false;
6827
6828 break;
6829
6830 case eEncodingT2:
6831 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6832 // if Rn == ’1111’ then SEE LDRSB (literal);
6833 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6834 // if P == ’0’ && W == ’0’ then UNDEFINED;
6835 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6836 return false;
6837
6838 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6839 t = Bits32 (opcode, 15, 12);
6840 n = Bits32 (opcode, 19, 16);
6841 imm32 = Bits32 (opcode, 7, 0);
6842
6843 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6844 index = BitIsSet (opcode, 10);
6845 add = BitIsSet (opcode, 9);
6846 wback = BitIsSet (opcode, 8);
6847
6848 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6849 if (BadReg (t) || (wback && (n == t)))
6850 return false;
6851
6852 break;
6853
6854 case eEncodingA1:
6855 {
6856 // if Rn == ’1111’ then SEE LDRSB (literal);
6857 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6858 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6859 t = Bits32 (opcode, 15, 12);
6860 n = Bits32 (opcode, 19, 16);
6861
6862 uint32_t imm4H = Bits32 (opcode, 11, 8);
6863 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006864 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006865
6866 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6867 index = BitIsSet (opcode, 24);
6868 add = BitIsSet (opcode, 23);
6869 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6870
6871 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6872 if ((t == 15) || (wback && (n == t)))
6873 return false;
6874
6875 break;
6876 }
6877
6878 default:
6879 return false;
6880 }
6881
6882 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6883 if (!success)
6884 return false;
6885
6886 addr_t offset_addr;
6887 addr_t address;
6888
6889 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6890 if (add)
6891 offset_addr = Rn + imm32;
6892 else
6893 offset_addr = Rn - imm32;
6894
6895 // address = if index then offset_addr else R[n];
6896 if (index)
6897 address = offset_addr;
6898 else
6899 address = Rn;
6900
6901 // R[t] = SignExtend(MemU[address,1], 32);
6902 Register base_reg;
6903 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6904
6905 EmulateInstruction::Context context;
6906 context.type = eContextRegisterLoad;
6907 context.SetRegisterPlusOffset (base_reg, address - Rn);
6908
6909 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6910 if (!success)
6911 return false;
6912
6913 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6914 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6915 return false;
6916
6917 // if wback then R[n] = offset_addr;
6918 if (wback)
6919 {
6920 context.type = eContextAdjustBaseRegister;
6921 context.SetAddress (offset_addr);
6922 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6923 return false;
6924 }
6925 }
6926
6927 return true;
6928}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006929
Caroline Tice5f593912011-03-01 22:25:17 +00006930// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6931// sign-extends it to form a 32-bit word, and writes tit to a register.
6932bool
6933EmulateInstructionARM::EmulateLDRSBLiteral (ARMEncoding encoding)
6934{
6935#if 0
6936 if ConditionPassed() then
6937 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6938 base = Align(PC,4);
6939 address = if add then (base + imm32) else (base - imm32);
6940 R[t] = SignExtend(MemU[address,1], 32);
6941#endif
6942
6943 bool success = false;
6944 const uint32_t opcode = OpcodeAsUnsigned (&success);
6945 if (!success)
6946 return false;
6947
6948 if (ConditionPassed ())
6949 {
6950 uint32_t t;
6951 uint32_t imm32;
6952 bool add;
6953
6954 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6955 switch (encoding)
6956 {
6957 case eEncodingT1:
6958 // if Rt == ’1111’ then SEE PLI;
6959 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6960 t = Bits32 (opcode, 15, 12);
6961 imm32 = Bits32 (opcode, 11, 0);
6962 add = BitIsSet (opcode, 23);
6963
6964 // if t == 13 then UNPREDICTABLE;
6965 if (t == 13)
6966 return false;
6967
6968 break;
6969
6970 case eEncodingA1:
6971 {
6972 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6973 t = Bits32 (opcode, 15, 12);
6974 uint32_t imm4H = Bits32 (opcode, 11, 8);
6975 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006976 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006977 add = BitIsSet (opcode, 23);
6978
6979 // if t == 15 then UNPREDICTABLE;
6980 if (t == 15)
6981 return false;
6982
6983 break;
6984 }
6985
6986 default:
6987 return false;
6988 }
6989
6990 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006991 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006992 if (!success)
6993 return false;
6994 uint64_t base = AlignPC (pc_value);
6995
6996 // address = if add then (base + imm32) else (base - imm32);
6997 addr_t address;
6998 if (add)
6999 address = base + imm32;
7000 else
7001 address = base - imm32;
7002
7003 // R[t] = SignExtend(MemU[address,1], 32);
7004 Register base_reg;
7005 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7006
7007 EmulateInstruction::Context context;
7008 context.type = eContextRegisterLoad;
7009 context.SetRegisterPlusOffset (base_reg, address - base);
7010
7011 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7012 if (!success)
7013 return false;
7014
7015 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7016 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7017 return false;
7018 }
7019 return true;
7020}
7021
Caroline Tice672f3112011-03-01 23:55:59 +00007022// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
7023// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7024// shifted left by 0, 1, 2, or 3 bits.
7025bool
7026EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
7027{
7028#if 0
7029 if ConditionPassed() then
7030 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7031 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7032 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7033 address = if index then offset_addr else R[n];
7034 R[t] = SignExtend(MemU[address,1], 32);
7035 if wback then R[n] = offset_addr;
7036#endif
7037
7038 bool success = false;
7039 const uint32_t opcode = OpcodeAsUnsigned (&success);
7040 if (!success)
7041 return false;
7042
7043 if (ConditionPassed ())
7044 {
7045 uint32_t t;
7046 uint32_t n;
7047 uint32_t m;
7048 bool index;
7049 bool add;
7050 bool wback;
7051 ARM_ShifterType shift_t;
7052 uint32_t shift_n;
7053
7054 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7055 switch (encoding)
7056 {
7057 case eEncodingT1:
7058 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7059 t = Bits32 (opcode, 2, 0);
7060 n = Bits32 (opcode, 5, 3);
7061 m = Bits32 (opcode, 8, 6);
7062
7063 // index = TRUE; add = TRUE; wback = FALSE;
7064 index = true;
7065 add = true;
7066 wback = false;
7067
7068 // (shift_t, shift_n) = (SRType_LSL, 0);
7069 shift_t = SRType_LSL;
7070 shift_n = 0;
7071
7072 break;
7073
7074 case eEncodingT2:
7075 // if Rt == ’1111’ then SEE PLI;
7076 // if Rn == ’1111’ then SEE LDRSB (literal);
7077 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7078 t = Bits32 (opcode, 15, 12);
7079 n = Bits32 (opcode, 19, 16);
7080 m = Bits32 (opcode, 3, 0);
7081
7082 // index = TRUE; add = TRUE; wback = FALSE;
7083 index = true;
7084 add = true;
7085 wback = false;
7086
7087 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7088 shift_t = SRType_LSL;
7089 shift_n = Bits32 (opcode, 5, 4);
7090
7091 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7092 if ((t == 13) || BadReg (m))
7093 return false;
7094 break;
7095
7096 case eEncodingA1:
7097 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
7098 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7099 t = Bits32 (opcode, 15, 12);
7100 n = Bits32 (opcode, 19, 16);
7101 m = Bits32 (opcode, 3, 0);
7102
7103 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7104 index = BitIsSet (opcode, 24);
7105 add = BitIsSet (opcode, 23);
7106 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7107
7108 // (shift_t, shift_n) = (SRType_LSL, 0);
7109 shift_t = SRType_LSL;
7110 shift_n = 0;
7111
7112 // if t == 15 || m == 15 then UNPREDICTABLE;
7113 if ((t == 15) || (m == 15))
7114 return false;
7115
7116 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7117 if (wback && ((n == 15) || (n == t)))
7118 return false;
7119 break;
7120
7121 default:
7122 return false;
7123 }
7124
7125 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7126 if (!success)
7127 return false;
7128
7129 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7130 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7131
7132 addr_t offset_addr;
7133 addr_t address;
7134
7135 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7136 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7137 if (!success)
7138 return false;
7139
7140 if (add)
7141 offset_addr = Rn + offset;
7142 else
7143 offset_addr = Rn - offset;
7144
7145 // address = if index then offset_addr else R[n];
7146 if (index)
7147 address = offset_addr;
7148 else
7149 address = Rn;
7150
7151 // R[t] = SignExtend(MemU[address,1], 32);
7152 Register base_reg;
7153 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7154 Register offset_reg;
7155 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7156
7157 EmulateInstruction::Context context;
7158 context.type = eContextRegisterLoad;
7159 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7160
7161 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7162 if (!success)
7163 return false;
7164
7165 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7166 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7167 return false;
7168
7169 // if wback then R[n] = offset_addr;
7170 if (wback)
7171 {
7172 context.type = eContextAdjustBaseRegister;
7173 context.SetAddress (offset_addr);
7174 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7175 return false;
7176 }
7177 }
7178 return true;
7179}
7180
Caroline Tice78fb5632011-03-02 00:39:42 +00007181// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7182// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7183// pre-indexed addressing.
7184bool
7185EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
7186{
7187#if 0
7188 if ConditionPassed() then
7189 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7190 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7191 address = if index then offset_addr else R[n];
7192 data = MemU[address,2];
7193 if wback then R[n] = offset_addr;
7194 if UnalignedSupport() || address<0> = ’0’ then
7195 R[t] = SignExtend(data, 32);
7196 else // Can only apply before ARMv7
7197 R[t] = bits(32) UNKNOWN;
7198#endif
7199
7200 bool success = false;
7201 const uint32_t opcode = OpcodeAsUnsigned (&success);
7202 if (!success)
7203 return false;
7204
7205 if (ConditionPassed())
7206 {
7207 uint32_t t;
7208 uint32_t n;
7209 uint32_t imm32;
7210 bool index;
7211 bool add;
7212 bool wback;
7213
7214 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7215 switch (encoding)
7216 {
7217 case eEncodingT1:
7218 // if Rn == ’1111’ then SEE LDRSH (literal);
7219 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7220 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7221 t = Bits32 (opcode, 15, 12);
7222 n = Bits32 (opcode, 19, 16);
7223 imm32 = Bits32 (opcode, 11, 0);
7224
7225 // index = TRUE; add = TRUE; wback = FALSE;
7226 index = true;
7227 add = true;
7228 wback = false;
7229
7230 // if t == 13 then UNPREDICTABLE;
7231 if (t == 13)
7232 return false;
7233
7234 break;
7235
7236 case eEncodingT2:
7237 // if Rn == ’1111’ then SEE LDRSH (literal);
7238 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
7239 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
7240 // if P == ’0’ && W == ’0’ then UNDEFINED;
7241 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7242 return false;
7243
7244 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7245 t = Bits32 (opcode, 15, 12);
7246 n = Bits32 (opcode, 19, 16);
7247 imm32 = Bits32 (opcode, 7, 0);
7248
7249 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
7250 index = BitIsSet (opcode, 10);
7251 add = BitIsSet (opcode, 9);
7252 wback = BitIsSet (opcode, 8);
7253
7254 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7255 if (BadReg (t) || (wback && (n == t)))
7256 return false;
7257
7258 break;
7259
7260 case eEncodingA1:
7261 {
7262 // if Rn == ’1111’ then SEE LDRSH (literal);
7263 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7264 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7265 t = Bits32 (opcode, 15, 12);
7266 n = Bits32 (opcode, 19, 16);
7267 uint32_t imm4H = Bits32 (opcode, 11,8);
7268 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007269 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007270
7271 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7272 index = BitIsSet (opcode, 24);
7273 add = BitIsSet (opcode, 23);
7274 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7275
7276 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7277 if ((t == 15) || (wback && (n == t)))
7278 return false;
7279
7280 break;
7281 }
7282
7283 default:
7284 return false;
7285 }
7286
7287 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7288 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7289 if (!success)
7290 return false;
7291
7292 addr_t offset_addr;
7293 if (add)
7294 offset_addr = Rn + imm32;
7295 else
7296 offset_addr = Rn - imm32;
7297
7298 // address = if index then offset_addr else R[n];
7299 addr_t address;
7300 if (index)
7301 address = offset_addr;
7302 else
7303 address = Rn;
7304
7305 // data = MemU[address,2];
7306 Register base_reg;
7307 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7308
7309 EmulateInstruction::Context context;
7310 context.type = eContextRegisterLoad;
7311 context.SetRegisterPlusOffset (base_reg, address - Rn);
7312
7313 uint64_t data = MemURead (context, address, 2, 0, &success);
7314 if (!success)
7315 return false;
7316
7317 // if wback then R[n] = offset_addr;
7318 if (wback)
7319 {
7320 context.type = eContextAdjustBaseRegister;
7321 context.SetAddress (offset_addr);
7322 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7323 return false;
7324 }
7325
7326 // if UnalignedSupport() || address<0> = ’0’ then
7327 if (UnalignedSupport() || BitIsClear (address, 0))
7328 {
7329 // R[t] = SignExtend(data, 32);
7330 int64_t signed_data = llvm::SignExtend64<16>(data);
7331 context.type = eContextRegisterLoad;
7332 context.SetRegisterPlusOffset (base_reg, address - Rn);
7333 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7334 return false;
7335 }
7336 else // Can only apply before ARMv7
7337 {
7338 // R[t] = bits(32) UNKNOWN;
7339 WriteBits32Unknown (t);
7340 }
7341 }
7342 return true;
7343}
7344
Caroline Ticed2fac092011-03-02 19:45:34 +00007345// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7346// sign-extends it to from a 32-bit word, and writes it to a register.
7347bool
7348EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
7349{
7350#if 0
7351 if ConditionPassed() then
7352 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7353 base = Align(PC,4);
7354 address = if add then (base + imm32) else (base - imm32);
7355 data = MemU[address,2];
7356 if UnalignedSupport() || address<0> = ’0’ then
7357 R[t] = SignExtend(data, 32);
7358 else // Can only apply before ARMv7
7359 R[t] = bits(32) UNKNOWN;
7360#endif
7361
7362 bool success = false;
7363 const uint32_t opcode = OpcodeAsUnsigned (&success);
7364 if (!success)
7365 return false;
7366
7367 if (ConditionPassed())
7368 {
7369 uint32_t t;
7370 uint32_t imm32;
7371 bool add;
7372
7373 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7374 switch (encoding)
7375 {
7376 case eEncodingT1:
7377 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7378 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7379 t = Bits32 (opcode, 15, 12);
7380 imm32 = Bits32 (opcode, 11, 0);
7381 add = BitIsSet (opcode, 23);
7382
7383 // if t == 13 then UNPREDICTABLE;
7384 if (t == 13)
7385 return false;
7386
7387 break;
7388
7389 case eEncodingA1:
7390 {
7391 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7392 t = Bits32 (opcode, 15, 12);
7393 uint32_t imm4H = Bits32 (opcode, 11, 8);
7394 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007395 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007396 add = BitIsSet (opcode, 23);
7397
7398 // if t == 15 then UNPREDICTABLE;
7399 if (t == 15)
7400 return false;
7401
7402 break;
7403 }
7404 default:
7405 return false;
7406 }
7407
7408 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007409 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007410 if (!success)
7411 return false;
7412
7413 uint64_t base = AlignPC (pc_value);
7414
7415 addr_t address;
7416 // address = if add then (base + imm32) else (base - imm32);
7417 if (add)
7418 address = base + imm32;
7419 else
7420 address = base - imm32;
7421
7422 // data = MemU[address,2];
7423 Register base_reg;
7424 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7425
7426 EmulateInstruction::Context context;
7427 context.type = eContextRegisterLoad;
7428 context.SetRegisterPlusOffset (base_reg, imm32);
7429
7430 uint64_t data = MemURead (context, address, 2, 0, &success);
7431 if (!success)
7432 return false;
7433
7434 // if UnalignedSupport() || address<0> = ’0’ then
7435 if (UnalignedSupport() || BitIsClear (address, 0))
7436 {
7437 // R[t] = SignExtend(data, 32);
7438 int64_t signed_data = llvm::SignExtend64<16>(data);
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 Tice291a3e92011-03-02 21:13:44 +00007451// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7452// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7453// shifted left by 0, 1, 2, or 3 bits.
7454bool
7455EmulateInstructionARM::EmulateLDRSHRegister (ARMEncoding encoding)
7456{
7457#if 0
7458 if ConditionPassed() then
7459 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7460 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7461 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7462 address = if index then offset_addr else R[n];
7463 data = MemU[address,2];
7464 if wback then R[n] = offset_addr;
7465 if UnalignedSupport() || address<0> = ’0’ then
7466 R[t] = SignExtend(data, 32);
7467 else // Can only apply before ARMv7
7468 R[t] = bits(32) UNKNOWN;
7469#endif
7470
7471 bool success = false;
7472 const uint32_t opcode = OpcodeAsUnsigned (&success);
7473 if (!success)
7474 return false;
7475
7476 if (ConditionPassed())
7477 {
7478 uint32_t t;
7479 uint32_t n;
7480 uint32_t m;
7481 bool index;
7482 bool add;
7483 bool wback;
7484 ARM_ShifterType shift_t;
7485 uint32_t shift_n;
7486
7487 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7488 switch (encoding)
7489 {
7490 case eEncodingT1:
7491 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7492 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7493 t = Bits32 (opcode, 2, 0);
7494 n = Bits32 (opcode, 5, 3);
7495 m = Bits32 (opcode, 8, 6);
7496
7497 // index = TRUE; add = TRUE; wback = FALSE;
7498 index = true;
7499 add = true;
7500 wback = false;
7501
7502 // (shift_t, shift_n) = (SRType_LSL, 0);
7503 shift_t = SRType_LSL;
7504 shift_n = 0;
7505
7506 break;
7507
7508 case eEncodingT2:
7509 // if Rn == ’1111’ then SEE LDRSH (literal);
7510 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7511 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7512 t = Bits32 (opcode, 15, 12);
7513 n = Bits32 (opcode, 19, 16);
7514 m = Bits32 (opcode, 3, 0);
7515
7516 // index = TRUE; add = TRUE; wback = FALSE;
7517 index = true;
7518 add = true;
7519 wback = false;
7520
7521 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7522 shift_t = SRType_LSL;
7523 shift_n = Bits32 (opcode, 5, 4);
7524
7525 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7526 if ((t == 13) || BadReg (m))
7527 return false;
7528
7529 break;
7530
7531 case eEncodingA1:
7532 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7533 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7534 t = Bits32 (opcode, 15, 12);
7535 n = Bits32 (opcode, 19, 16);
7536 m = Bits32 (opcode, 3, 0);
7537
7538 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7539 index = BitIsSet (opcode, 24);
7540 add = BitIsSet (opcode, 23);
7541 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7542
7543 // (shift_t, shift_n) = (SRType_LSL, 0);
7544 shift_t = SRType_LSL;
7545 shift_n = 0;
7546
7547 // if t == 15 || m == 15 then UNPREDICTABLE;
7548 if ((t == 15) || (m == 15))
7549 return false;
7550
7551 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7552 if (wback && ((n == 15) || (n == t)))
7553 return false;
7554
7555 break;
7556
7557 default:
7558 break;
7559 }
7560
7561 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7562 if (!success)
7563 return false;
7564
7565 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7566 if (!success)
7567 return false;
7568
7569 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7570 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7571
7572 addr_t offset_addr;
7573 addr_t address;
7574
7575 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7576 if (add)
7577 offset_addr = Rn + offset;
7578 else
7579 offset_addr = Rn - offset;
7580
7581 // address = if index then offset_addr else R[n];
7582 if (index)
7583 address = offset_addr;
7584 else
7585 address = Rn;
7586
7587 // data = MemU[address,2];
7588 Register base_reg;
7589 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7590
7591 Register offset_reg;
7592 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7593
7594 EmulateInstruction::Context context;
7595 context.type = eContextRegisterLoad;
7596 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7597
7598 uint64_t data = MemURead (context, address, 2, 0, &success);
7599 if (!success)
7600 return false;
7601
7602 // if wback then R[n] = offset_addr;
7603 if (wback)
7604 {
7605 context.type = eContextAdjustBaseRegister;
7606 context.SetAddress (offset_addr);
7607 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7608 return false;
7609 }
7610
7611 // if UnalignedSupport() || address<0> = ’0’ then
7612 if (UnalignedSupport() || BitIsClear (address, 0))
7613 {
7614 // R[t] = SignExtend(data, 32);
7615 context.type = eContextRegisterLoad;
7616 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7617
7618 int64_t signed_data = llvm::SignExtend64<16>(data);
7619 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7620 return false;
7621 }
7622 else // Can only apply before ARMv7
7623 {
7624 // R[t] = bits(32) UNKNOWN;
7625 WriteBits32Unknown (t);
7626 }
7627 }
7628 return true;
7629}
Caroline Tice6bf65162011-03-03 17:42:58 +00007630
7631// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7632// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7633bool
7634EmulateInstructionARM::EmulateSXTB (ARMEncoding encoding)
7635{
7636#if 0
7637 if ConditionPassed() then
7638 EncodingSpecificOperations();
7639 rotated = ROR(R[m], rotation);
7640 R[d] = SignExtend(rotated<7:0>, 32);
7641#endif
7642
7643 bool success = false;
7644 const uint32_t opcode = OpcodeAsUnsigned (&success);
7645 if (!success)
7646 return false;
7647
7648 if (ConditionPassed())
7649 {
7650 uint32_t d;
7651 uint32_t m;
7652 uint32_t rotation;
7653
7654 // EncodingSpecificOperations();
7655 switch (encoding)
7656 {
7657 case eEncodingT1:
7658 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7659 d = Bits32 (opcode, 2, 0);
7660 m = Bits32 (opcode, 5, 3);
7661 rotation = 0;
7662
7663 break;
7664
7665 case eEncodingT2:
7666 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7667 d = Bits32 (opcode, 11, 8);
7668 m = Bits32 (opcode, 3, 0);
7669 rotation = Bits32 (opcode, 5, 4) << 3;
7670
7671 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7672 if (BadReg (d) || BadReg (m))
7673 return false;
7674
7675 break;
7676
7677 case eEncodingA1:
7678 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7679 d = Bits32 (opcode, 15, 12);
7680 m = Bits32 (opcode, 3, 0);
7681 rotation = Bits32 (opcode, 11, 10) << 3;
7682
7683 // if d == 15 || m == 15 then UNPREDICTABLE;
7684 if ((d == 15) || (m == 15))
7685 return false;
7686
7687 break;
7688
7689 default:
7690 return false;
7691 }
7692
Caroline Tice868198b2011-03-03 18:04:49 +00007693 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7694 if (!success)
7695 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007696
7697 // rotated = ROR(R[m], rotation);
7698 uint64_t rotated = ROR (Rm, rotation);
7699
7700 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007701 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007702
7703 Register source_reg;
7704 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7705
7706 EmulateInstruction::Context context;
7707 context.type = eContextRegisterLoad;
7708 context.SetRegister (source_reg);
7709
Caroline Tice8ce96d92011-03-03 18:27:17 +00007710 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007711 return false;
7712 }
7713 return true;
7714}
Caroline Tice291a3e92011-03-02 21:13:44 +00007715
Caroline Tice868198b2011-03-03 18:04:49 +00007716// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7717// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7718bool
7719EmulateInstructionARM::EmulateSXTH (ARMEncoding encoding)
7720{
7721#if 0
7722 if ConditionPassed() then
7723 EncodingSpecificOperations();
7724 rotated = ROR(R[m], rotation);
7725 R[d] = SignExtend(rotated<15:0>, 32);
7726#endif
7727
7728 bool success = false;
7729 const uint32_t opcode = OpcodeAsUnsigned (&success);
7730 if (!success)
7731 return false;
7732
7733 if (ConditionPassed())
7734 {
7735 uint32_t d;
7736 uint32_t m;
7737 uint32_t rotation;
7738
7739 // EncodingSpecificOperations();
7740 switch (encoding)
7741 {
7742 case eEncodingT1:
7743 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7744 d = Bits32 (opcode, 2, 0);
7745 m = Bits32 (opcode, 5, 3);
7746 rotation = 0;
7747
7748 break;
7749
7750 case eEncodingT2:
7751 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7752 d = Bits32 (opcode, 11, 8);
7753 m = Bits32 (opcode, 3, 0);
7754 rotation = Bits32 (opcode, 5, 4) << 3;
7755
7756 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7757 if (BadReg (d) || BadReg (m))
7758 return false;
7759
7760 break;
7761
7762 case eEncodingA1:
7763 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7764 d = Bits32 (opcode, 15, 12);
7765 m = Bits32 (opcode, 3, 0);
7766 rotation = Bits32 (opcode, 11, 10) << 3;
7767
7768 // if d == 15 || m == 15 then UNPREDICTABLE;
7769 if ((d == 15) || (m == 15))
7770 return false;
7771
7772 break;
7773
7774 default:
7775 return false;
7776 }
7777
7778 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7779 if (!success)
7780 return false;
7781
7782 // rotated = ROR(R[m], rotation);
7783 uint64_t rotated = ROR (Rm, rotation);
7784
7785 // R[d] = SignExtend(rotated<15:0>, 32);
7786 Register source_reg;
7787 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7788
7789 EmulateInstruction::Context context;
7790 context.type = eContextRegisterLoad;
7791 context.SetRegister (source_reg);
7792
Caroline Tice8ce96d92011-03-03 18:27:17 +00007793 int64_t data = llvm::SignExtend64<16> (rotated);
7794 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007795 return false;
7796 }
7797
7798 return true;
7799}
7800
Caroline Tice8ce96d92011-03-03 18:27:17 +00007801// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7802// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7803bool
7804EmulateInstructionARM::EmulateUXTB (ARMEncoding encoding)
7805{
7806#if 0
7807 if ConditionPassed() then
7808 EncodingSpecificOperations();
7809 rotated = ROR(R[m], rotation);
7810 R[d] = ZeroExtend(rotated<7:0>, 32);
7811#endif
7812
7813 bool success = false;
7814 const uint32_t opcode = OpcodeAsUnsigned (&success);
7815 if (!success)
7816 return false;
7817
7818 if (ConditionPassed())
7819 {
7820 uint32_t d;
7821 uint32_t m;
7822 uint32_t rotation;
7823
7824 // EncodingSpecificOperations();
7825 switch (encoding)
7826 {
7827 case eEncodingT1:
7828 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7829 d = Bits32 (opcode, 2, 0);
7830 m = Bits32 (opcode, 5, 3);
7831 rotation = 0;
7832
7833 break;
7834
7835 case eEncodingT2:
7836 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7837 d = Bits32 (opcode, 11, 8);
7838 m = Bits32 (opcode, 3, 0);
7839 rotation = Bits32 (opcode, 5, 4) << 3;
7840
7841 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7842 if (BadReg (d) || BadReg (m))
7843 return false;
7844
7845 break;
7846
7847 case eEncodingA1:
7848 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7849 d = Bits32 (opcode, 15, 12);
7850 m = Bits32 (opcode, 3, 0);
7851 rotation = Bits32 (opcode, 11, 10) << 3;
7852
7853 // if d == 15 || m == 15 then UNPREDICTABLE;
7854 if ((d == 15) || (m == 15))
7855 return false;
7856
7857 break;
7858
7859 default:
7860 return false;
7861 }
7862
7863 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7864 if (!success)
7865 return false;
7866
7867 // rotated = ROR(R[m], rotation);
7868 uint64_t rotated = ROR (Rm, rotation);
7869
7870 // R[d] = ZeroExtend(rotated<7:0>, 32);
7871 Register source_reg;
7872 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7873
7874 EmulateInstruction::Context context;
7875 context.type = eContextRegisterLoad;
7876 context.SetRegister (source_reg);
7877
7878 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7879 return false;
7880 }
7881 return true;
7882}
7883
Caroline Tice11555f22011-03-03 18:48:58 +00007884// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7885// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7886bool
7887EmulateInstructionARM::EmulateUXTH (ARMEncoding encoding)
7888{
7889#if 0
7890 if ConditionPassed() then
7891 EncodingSpecificOperations();
7892 rotated = ROR(R[m], rotation);
7893 R[d] = ZeroExtend(rotated<15:0>, 32);
7894#endif
7895
7896 bool success = false;
7897 const uint32_t opcode = OpcodeAsUnsigned (&success);
7898 if (!success)
7899 return false;
7900
7901 if (ConditionPassed ())
7902 {
7903 uint32_t d;
7904 uint32_t m;
7905 uint32_t rotation;
7906
7907 switch (encoding)
7908 {
7909 case eEncodingT1:
7910 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7911 d = Bits32 (opcode, 2, 0);
7912 m = Bits32 (opcode, 5, 3);
7913 rotation = 0;
7914
7915 break;
7916
7917 case eEncodingT2:
7918 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7919 d = Bits32 (opcode, 11, 8);
7920 m = Bits32 (opcode, 3, 0);
7921 rotation = Bits32 (opcode, 5, 4) << 3;
7922
7923 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7924 if (BadReg (d) || BadReg (m))
7925 return false;
7926
7927 break;
7928
7929 case eEncodingA1:
7930 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7931 d = Bits32 (opcode, 15, 12);
7932 m = Bits32 (opcode, 3, 0);
7933 rotation = Bits32 (opcode, 11, 10) << 3;
7934
7935 // if d == 15 || m == 15 then UNPREDICTABLE;
7936 if ((d == 15) || (m == 15))
7937 return false;
7938
7939 break;
7940
7941 default:
7942 return false;
7943 }
7944
7945 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7946 if (!success)
7947 return false;
7948
7949 // rotated = ROR(R[m], rotation);
7950 uint64_t rotated = ROR (Rm, rotation);
7951
7952 // R[d] = ZeroExtend(rotated<15:0>, 32);
7953 Register source_reg;
7954 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7955
7956 EmulateInstruction::Context context;
7957 context.type = eContextRegisterLoad;
7958 context.SetRegister (source_reg);
7959
7960 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7961 return false;
7962 }
7963 return true;
7964}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007965
7966// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7967// word respectively.
7968bool
7969EmulateInstructionARM::EmulateRFE (ARMEncoding encoding)
7970{
7971#if 0
7972 if ConditionPassed() then
7973 EncodingSpecificOperations();
7974 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7975 UNPREDICTABLE;
7976 else
7977 address = if increment then R[n] else R[n]-8;
7978 if wordhigher then address = address+4;
7979 CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
7980 BranchWritePC(MemA[address,4]);
7981 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7982#endif
7983
7984 bool success = false;
7985 const uint32_t opcode = OpcodeAsUnsigned (&success);
7986 if (!success)
7987 return false;
7988
7989 if (ConditionPassed())
7990 {
7991 uint32_t n;
7992 bool wback;
7993 bool increment;
7994 bool wordhigher;
7995
7996 // EncodingSpecificOperations();
7997 switch (encoding)
7998 {
7999 case eEncodingT1:
8000 // n = UInt(Rn); wback = (W == ’1’); increment = FALSE; wordhigher = FALSE;
8001 n = Bits32 (opcode, 19, 16);
8002 wback = BitIsSet (opcode, 21);
8003 increment = false;
8004 wordhigher = false;
8005
8006 // if n == 15 then UNPREDICTABLE;
8007 if (n == 15)
8008 return false;
8009
8010 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8011 if (InITBlock() && !LastInITBlock())
8012 return false;
8013
8014 break;
8015
8016 case eEncodingT2:
8017 // n = UInt(Rn); wback = (W == ’1’); increment = TRUE; wordhigher = FALSE;
8018 n = Bits32 (opcode, 19, 16);
8019 wback = BitIsSet (opcode, 21);
8020 increment = true;
8021 wordhigher = false;
8022
8023 // if n == 15 then UNPREDICTABLE;
8024 if (n == 15)
8025 return false;
8026
8027 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8028 if (InITBlock() && !LastInITBlock())
8029 return false;
8030
8031 break;
8032
8033 case eEncodingA1:
8034 // n = UInt(Rn);
8035 n = Bits32 (opcode, 19, 16);
8036
8037 // wback = (W == ’1’); inc = (U == ’1’); wordhigher = (P == U);
8038 wback = BitIsSet (opcode, 21);
8039 increment = BitIsSet (opcode, 23);
8040 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8041
8042 // if n == 15 then UNPREDICTABLE;
8043 if (n == 15)
8044 return false;
8045
8046 break;
8047
8048 default:
8049 return false;
8050 }
8051
8052 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8053 if (!CurrentModeIsPrivileged ())
8054 // UNPREDICTABLE;
8055 return false;
8056 else
8057 {
8058 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8059 if (!success)
8060 return false;
8061
8062 addr_t address;
8063 // address = if increment then R[n] else R[n]-8;
8064 if (increment)
8065 address = Rn;
8066 else
8067 address = Rn - 8;
8068
8069 // if wordhigher then address = address+4;
8070 if (wordhigher)
8071 address = address + 4;
8072
8073 // CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
8074 Register base_reg;
8075 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8076
8077 EmulateInstruction::Context context;
8078 context.type = eContextReturnFromException;
8079 context.SetRegisterPlusOffset (base_reg, address - Rn);
8080
8081 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8082 if (!success)
8083 return false;
8084
8085 CPSRWriteByInstr (data, 15, true);
8086
8087 // BranchWritePC(MemA[address,4]);
8088 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8089 if (!success)
8090 return false;
8091
8092 BranchWritePC (context, data2);
8093
8094 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8095 if (wback)
8096 {
8097 context.type = eContextAdjustBaseRegister;
8098 if (increment)
8099 {
8100 context.SetOffset (8);
8101 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8102 return false;
8103 }
8104 else
8105 {
8106 context.SetOffset (-8);
8107 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8108 return false;
8109 }
8110 } // if wback
8111 }
8112 } // if ConditionPassed()
8113 return true;
8114}
Caroline Tice11555f22011-03-03 18:48:58 +00008115
Johnny Chen2115b412011-02-21 23:42:44 +00008116// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8117// and writes the result to the destination register. It can optionally update the condition flags based on
8118// the result.
8119bool
8120EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
8121{
8122#if 0
8123 // ARM pseudo code...
8124 if ConditionPassed() then
8125 EncodingSpecificOperations();
8126 result = R[n] EOR imm32;
8127 if d == 15 then // Can only occur for ARM encoding
8128 ALUWritePC(result); // setflags is always FALSE here
8129 else
8130 R[d] = result;
8131 if setflags then
8132 APSR.N = result<31>;
8133 APSR.Z = IsZeroBit(result);
8134 APSR.C = carry;
8135 // APSR.V unchanged
8136#endif
8137
8138 bool success = false;
8139 const uint32_t opcode = OpcodeAsUnsigned (&success);
8140 if (!success)
8141 return false;
8142
8143 if (ConditionPassed())
8144 {
8145 uint32_t Rd, Rn;
8146 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8147 bool setflags;
8148 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8149 switch (encoding)
8150 {
8151 case eEncodingT1:
8152 Rd = Bits32(opcode, 11, 8);
8153 Rn = Bits32(opcode, 19, 16);
8154 setflags = BitIsSet(opcode, 20);
8155 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8156 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8157 if (Rd == 15 && setflags)
8158 return EmulateTEQImm(eEncodingT1);
8159 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8160 return false;
8161 break;
8162 case eEncodingA1:
8163 Rd = Bits32(opcode, 15, 12);
8164 Rn = Bits32(opcode, 19, 16);
8165 setflags = BitIsSet(opcode, 20);
8166 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8167 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8168 // TODO: Emulate SUBS PC, LR and related instructions.
8169 if (Rd == 15 && setflags)
8170 return false;
8171 break;
8172 default:
8173 return false;
8174 }
8175
8176 // Read the first operand.
8177 uint32_t val1 = ReadCoreReg(Rn, &success);
8178 if (!success)
8179 return false;
8180
8181 uint32_t result = val1 ^ imm32;
8182
8183 EmulateInstruction::Context context;
8184 context.type = EmulateInstruction::eContextImmediate;
8185 context.SetNoArgs ();
8186
8187 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8188 return false;
8189 }
8190 return true;
8191}
8192
8193// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8194// optionally-shifted register value, and writes the result to the destination register.
8195// It can optionally update the condition flags based on the result.
8196bool
8197EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
8198{
8199#if 0
8200 // ARM pseudo code...
8201 if ConditionPassed() then
8202 EncodingSpecificOperations();
8203 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8204 result = R[n] EOR shifted;
8205 if d == 15 then // Can only occur for ARM encoding
8206 ALUWritePC(result); // setflags is always FALSE here
8207 else
8208 R[d] = result;
8209 if setflags then
8210 APSR.N = result<31>;
8211 APSR.Z = IsZeroBit(result);
8212 APSR.C = carry;
8213 // APSR.V unchanged
8214#endif
8215
8216 bool success = false;
8217 const uint32_t opcode = OpcodeAsUnsigned (&success);
8218 if (!success)
8219 return false;
8220
8221 if (ConditionPassed())
8222 {
8223 uint32_t Rd, Rn, Rm;
8224 ARM_ShifterType shift_t;
8225 uint32_t shift_n; // the shift applied to the value read from Rm
8226 bool setflags;
8227 uint32_t carry;
8228 switch (encoding)
8229 {
8230 case eEncodingT1:
8231 Rd = Rn = Bits32(opcode, 2, 0);
8232 Rm = Bits32(opcode, 5, 3);
8233 setflags = !InITBlock();
8234 shift_t = SRType_LSL;
8235 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008236 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008237 case eEncodingT2:
8238 Rd = Bits32(opcode, 11, 8);
8239 Rn = Bits32(opcode, 19, 16);
8240 Rm = Bits32(opcode, 3, 0);
8241 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008242 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8243 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008244 if (Rd == 15 && setflags)
8245 return EmulateTEQReg(eEncodingT1);
8246 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8247 return false;
8248 break;
8249 case eEncodingA1:
8250 Rd = Bits32(opcode, 15, 12);
8251 Rn = Bits32(opcode, 19, 16);
8252 Rm = Bits32(opcode, 3, 0);
8253 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008254 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008255 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8256 // TODO: Emulate SUBS PC, LR and related instructions.
8257 if (Rd == 15 && setflags)
8258 return false;
8259 break;
8260 default:
8261 return false;
8262 }
8263
8264 // Read the first operand.
8265 uint32_t val1 = ReadCoreReg(Rn, &success);
8266 if (!success)
8267 return false;
8268
8269 // Read the second operand.
8270 uint32_t val2 = ReadCoreReg(Rm, &success);
8271 if (!success)
8272 return false;
8273
8274 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8275 uint32_t result = val1 ^ shifted;
8276
8277 EmulateInstruction::Context context;
8278 context.type = EmulateInstruction::eContextImmediate;
8279 context.SetNoArgs ();
8280
8281 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8282 return false;
8283 }
8284 return true;
8285}
8286
Johnny Chen7c5234d2011-02-18 23:41:11 +00008287// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8288// writes the result to the destination register. It can optionally update the condition flags based
8289// on the result.
8290bool
8291EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
8292{
8293#if 0
8294 // ARM pseudo code...
8295 if ConditionPassed() then
8296 EncodingSpecificOperations();
8297 result = R[n] OR imm32;
8298 if d == 15 then // Can only occur for ARM encoding
8299 ALUWritePC(result); // setflags is always FALSE here
8300 else
8301 R[d] = result;
8302 if setflags then
8303 APSR.N = result<31>;
8304 APSR.Z = IsZeroBit(result);
8305 APSR.C = carry;
8306 // APSR.V unchanged
8307#endif
8308
8309 bool success = false;
8310 const uint32_t opcode = OpcodeAsUnsigned (&success);
8311 if (!success)
8312 return false;
8313
8314 if (ConditionPassed())
8315 {
8316 uint32_t Rd, Rn;
8317 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8318 bool setflags;
8319 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8320 switch (encoding)
8321 {
8322 case eEncodingT1:
8323 Rd = Bits32(opcode, 11, 8);
8324 Rn = Bits32(opcode, 19, 16);
8325 setflags = BitIsSet(opcode, 20);
8326 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8327 // if Rn == ‘1111’ then SEE MOV (immediate);
8328 if (Rn == 15)
8329 return EmulateMOVRdImm(eEncodingT2);
8330 if (BadReg(Rd) || Rn == 13)
8331 return false;
8332 break;
8333 case eEncodingA1:
8334 Rd = Bits32(opcode, 15, 12);
8335 Rn = Bits32(opcode, 19, 16);
8336 setflags = BitIsSet(opcode, 20);
8337 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8338 // TODO: Emulate SUBS PC, LR and related instructions.
8339 if (Rd == 15 && setflags)
8340 return false;
8341 break;
8342 default:
8343 return false;
8344 }
8345
8346 // Read the first operand.
8347 uint32_t val1 = ReadCoreReg(Rn, &success);
8348 if (!success)
8349 return false;
8350
8351 uint32_t result = val1 | imm32;
8352
8353 EmulateInstruction::Context context;
8354 context.type = EmulateInstruction::eContextImmediate;
8355 context.SetNoArgs ();
8356
8357 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8358 return false;
8359 }
8360 return true;
8361}
8362
8363// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8364// value, and writes the result to the destination register. It can optionally update the condition flags based
8365// on the result.
8366bool
8367EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
8368{
8369#if 0
8370 // ARM pseudo code...
8371 if ConditionPassed() then
8372 EncodingSpecificOperations();
8373 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8374 result = R[n] OR shifted;
8375 if d == 15 then // Can only occur for ARM encoding
8376 ALUWritePC(result); // setflags is always FALSE here
8377 else
8378 R[d] = result;
8379 if setflags then
8380 APSR.N = result<31>;
8381 APSR.Z = IsZeroBit(result);
8382 APSR.C = carry;
8383 // APSR.V unchanged
8384#endif
8385
8386 bool success = false;
8387 const uint32_t opcode = OpcodeAsUnsigned (&success);
8388 if (!success)
8389 return false;
8390
8391 if (ConditionPassed())
8392 {
8393 uint32_t Rd, Rn, Rm;
8394 ARM_ShifterType shift_t;
8395 uint32_t shift_n; // the shift applied to the value read from Rm
8396 bool setflags;
8397 uint32_t carry;
8398 switch (encoding)
8399 {
8400 case eEncodingT1:
8401 Rd = Rn = Bits32(opcode, 2, 0);
8402 Rm = Bits32(opcode, 5, 3);
8403 setflags = !InITBlock();
8404 shift_t = SRType_LSL;
8405 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008406 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008407 case eEncodingT2:
8408 Rd = Bits32(opcode, 11, 8);
8409 Rn = Bits32(opcode, 19, 16);
8410 Rm = Bits32(opcode, 3, 0);
8411 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008412 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8413 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008414 if (Rn == 15)
8415 return EmulateMOVRdRm(eEncodingT3);
8416 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8417 return false;
8418 break;
8419 case eEncodingA1:
8420 Rd = Bits32(opcode, 15, 12);
8421 Rn = Bits32(opcode, 19, 16);
8422 Rm = Bits32(opcode, 3, 0);
8423 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008424 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008425 // TODO: Emulate SUBS PC, LR and related instructions.
8426 if (Rd == 15 && setflags)
8427 return false;
8428 break;
8429 default:
8430 return false;
8431 }
8432
8433 // Read the first operand.
8434 uint32_t val1 = ReadCoreReg(Rn, &success);
8435 if (!success)
8436 return false;
8437
8438 // Read the second operand.
8439 uint32_t val2 = ReadCoreReg(Rm, &success);
8440 if (!success)
8441 return false;
8442
8443 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008444 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008445
8446 EmulateInstruction::Context context;
8447 context.type = EmulateInstruction::eContextImmediate;
8448 context.SetNoArgs ();
8449
8450 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8451 return false;
8452 }
8453 return true;
8454}
8455
Johnny Chened32e7c2011-02-22 23:42:58 +00008456// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8457// the destination register. It can optionally update the condition flags based on the result.
8458bool
8459EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
8460{
8461#if 0
8462 // ARM pseudo code...
8463 if ConditionPassed() then
8464 EncodingSpecificOperations();
8465 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8466 if d == 15 then // Can only occur for ARM encoding
8467 ALUWritePC(result); // setflags is always FALSE here
8468 else
8469 R[d] = result;
8470 if setflags then
8471 APSR.N = result<31>;
8472 APSR.Z = IsZeroBit(result);
8473 APSR.C = carry;
8474 APSR.V = overflow;
8475#endif
8476
8477 bool success = false;
8478 const uint32_t opcode = OpcodeAsUnsigned (&success);
8479 if (!success)
8480 return false;
8481
8482 uint32_t Rd; // the destination register
8483 uint32_t Rn; // the first operand
8484 bool setflags;
8485 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8486 switch (encoding) {
8487 case eEncodingT1:
8488 Rd = Bits32(opcode, 2, 0);
8489 Rn = Bits32(opcode, 5, 3);
8490 setflags = !InITBlock();
8491 imm32 = 0;
8492 break;
8493 case eEncodingT2:
8494 Rd = Bits32(opcode, 11, 8);
8495 Rn = Bits32(opcode, 19, 16);
8496 setflags = BitIsSet(opcode, 20);
8497 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8498 if (BadReg(Rd) || BadReg(Rn))
8499 return false;
8500 break;
8501 case eEncodingA1:
8502 Rd = Bits32(opcode, 15, 12);
8503 Rn = Bits32(opcode, 19, 16);
8504 setflags = BitIsSet(opcode, 20);
8505 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8506 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8507 // TODO: Emulate SUBS PC, LR and related instructions.
8508 if (Rd == 15 && setflags)
8509 return false;
8510 break;
8511 default:
8512 return false;
8513 }
8514 // Read the register value from the operand register Rn.
8515 uint32_t reg_val = ReadCoreReg(Rn, &success);
8516 if (!success)
8517 return false;
8518
8519 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8520
8521 EmulateInstruction::Context context;
8522 context.type = EmulateInstruction::eContextImmediate;
8523 context.SetNoArgs ();
8524
8525 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8526 return false;
8527
8528 return true;
8529}
8530
8531// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8532// result to the destination register. It can optionally update the condition flags based on the result.
8533bool
8534EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
8535{
8536#if 0
8537 // ARM pseudo code...
8538 if ConditionPassed() then
8539 EncodingSpecificOperations();
8540 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8541 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8542 if d == 15 then // Can only occur for ARM encoding
8543 ALUWritePC(result); // setflags is always FALSE here
8544 else
8545 R[d] = result;
8546 if setflags then
8547 APSR.N = result<31>;
8548 APSR.Z = IsZeroBit(result);
8549 APSR.C = carry;
8550 APSR.V = overflow;
8551#endif
8552
8553 bool success = false;
8554 const uint32_t opcode = OpcodeAsUnsigned (&success);
8555 if (!success)
8556 return false;
8557
8558 uint32_t Rd; // the destination register
8559 uint32_t Rn; // the first operand
8560 uint32_t Rm; // the second operand
8561 bool setflags;
8562 ARM_ShifterType shift_t;
8563 uint32_t shift_n; // the shift applied to the value read from Rm
8564 switch (encoding) {
8565 case eEncodingT1:
8566 Rd = Bits32(opcode, 11, 8);
8567 Rn = Bits32(opcode, 19, 16);
8568 Rm = Bits32(opcode, 3, 0);
8569 setflags = BitIsSet(opcode, 20);
8570 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8571 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8572 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8573 return false;
8574 break;
8575 case eEncodingA1:
8576 Rd = Bits32(opcode, 15, 12);
8577 Rn = Bits32(opcode, 19, 16);
8578 Rm = Bits32(opcode, 3, 0);
8579 setflags = BitIsSet(opcode, 20);
8580 shift_n = DecodeImmShiftARM(opcode, shift_t);
8581 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8582 // TODO: Emulate SUBS PC, LR and related instructions.
8583 if (Rd == 15 && setflags)
8584 return false;
8585 break;
8586 default:
8587 return false;
8588 }
8589 // Read the register value from register Rn.
8590 uint32_t val1 = ReadCoreReg(Rn, &success);
8591 if (!success)
8592 return false;
8593
8594 // Read the register value from register Rm.
8595 uint32_t val2 = ReadCoreReg(Rm, &success);
8596 if (!success)
8597 return false;
8598
8599 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8600 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8601
8602 EmulateInstruction::Context context;
8603 context.type = EmulateInstruction::eContextImmediate;
8604 context.SetNoArgs();
8605 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8606 return false;
8607
8608 return true;
8609}
8610
Johnny Chen90e607b2011-02-23 00:07:09 +00008611// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8612// an immediate value, and writes the result to the destination register. It can optionally update the condition
8613// flags based on the result.
8614bool
8615EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
8616{
8617#if 0
8618 // ARM pseudo code...
8619 if ConditionPassed() then
8620 EncodingSpecificOperations();
8621 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8622 if d == 15 then
8623 ALUWritePC(result); // setflags is always FALSE here
8624 else
8625 R[d] = result;
8626 if setflags then
8627 APSR.N = result<31>;
8628 APSR.Z = IsZeroBit(result);
8629 APSR.C = carry;
8630 APSR.V = overflow;
8631#endif
8632
8633 bool success = false;
8634 const uint32_t opcode = OpcodeAsUnsigned (&success);
8635 if (!success)
8636 return false;
8637
8638 uint32_t Rd; // the destination register
8639 uint32_t Rn; // the first operand
8640 bool setflags;
8641 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8642 switch (encoding) {
8643 case eEncodingA1:
8644 Rd = Bits32(opcode, 15, 12);
8645 Rn = Bits32(opcode, 19, 16);
8646 setflags = BitIsSet(opcode, 20);
8647 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8648 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8649 // TODO: Emulate SUBS PC, LR and related instructions.
8650 if (Rd == 15 && setflags)
8651 return false;
8652 break;
8653 default:
8654 return false;
8655 }
8656 // Read the register value from the operand register Rn.
8657 uint32_t reg_val = ReadCoreReg(Rn, &success);
8658 if (!success)
8659 return false;
8660
8661 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8662
8663 EmulateInstruction::Context context;
8664 context.type = EmulateInstruction::eContextImmediate;
8665 context.SetNoArgs ();
8666
8667 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8668 return false;
8669
8670 return true;
8671}
8672
8673// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8674// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8675// condition flags based on the result.
8676bool
8677EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
8678{
8679#if 0
8680 // ARM pseudo code...
8681 if ConditionPassed() then
8682 EncodingSpecificOperations();
8683 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8684 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8685 if d == 15 then
8686 ALUWritePC(result); // setflags is always FALSE here
8687 else
8688 R[d] = result;
8689 if setflags then
8690 APSR.N = result<31>;
8691 APSR.Z = IsZeroBit(result);
8692 APSR.C = carry;
8693 APSR.V = overflow;
8694#endif
8695
8696 bool success = false;
8697 const uint32_t opcode = OpcodeAsUnsigned (&success);
8698 if (!success)
8699 return false;
8700
8701 uint32_t Rd; // the destination register
8702 uint32_t Rn; // the first operand
8703 uint32_t Rm; // the second operand
8704 bool setflags;
8705 ARM_ShifterType shift_t;
8706 uint32_t shift_n; // the shift applied to the value read from Rm
8707 switch (encoding) {
8708 case eEncodingA1:
8709 Rd = Bits32(opcode, 15, 12);
8710 Rn = Bits32(opcode, 19, 16);
8711 Rm = Bits32(opcode, 3, 0);
8712 setflags = BitIsSet(opcode, 20);
8713 shift_n = DecodeImmShiftARM(opcode, shift_t);
8714 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8715 // TODO: Emulate SUBS PC, LR and related instructions.
8716 if (Rd == 15 && setflags)
8717 return false;
8718 break;
8719 default:
8720 return false;
8721 }
8722 // Read the register value from register Rn.
8723 uint32_t val1 = ReadCoreReg(Rn, &success);
8724 if (!success)
8725 return false;
8726
8727 // Read the register value from register Rm.
8728 uint32_t val2 = ReadCoreReg(Rm, &success);
8729 if (!success)
8730 return false;
8731
8732 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8733 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8734
8735 EmulateInstruction::Context context;
8736 context.type = EmulateInstruction::eContextImmediate;
8737 context.SetNoArgs();
8738 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8739 return false;
8740
8741 return true;
8742}
8743
Johnny Chen9b381772011-02-23 01:01:21 +00008744// Subtract with Carry (immediate) subtracts an immediate value and the value of
8745// NOT (Carry flag) from a register value, and writes the result to the destination register.
8746// It can optionally update the condition flags based on the result.
8747bool
8748EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
8749{
8750#if 0
8751 // ARM pseudo code...
8752 if ConditionPassed() then
8753 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008754 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008755 if d == 15 then // Can only occur for ARM encoding
8756 ALUWritePC(result); // setflags is always FALSE here
8757 else
8758 R[d] = result;
8759 if setflags then
8760 APSR.N = result<31>;
8761 APSR.Z = IsZeroBit(result);
8762 APSR.C = carry;
8763 APSR.V = overflow;
8764#endif
8765
8766 bool success = false;
8767 const uint32_t opcode = OpcodeAsUnsigned (&success);
8768 if (!success)
8769 return false;
8770
8771 uint32_t Rd; // the destination register
8772 uint32_t Rn; // the first operand
8773 bool setflags;
8774 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8775 switch (encoding) {
8776 case eEncodingT1:
8777 Rd = Bits32(opcode, 11, 8);
8778 Rn = Bits32(opcode, 19, 16);
8779 setflags = BitIsSet(opcode, 20);
8780 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8781 if (BadReg(Rd) || BadReg(Rn))
8782 return false;
8783 break;
8784 case eEncodingA1:
8785 Rd = Bits32(opcode, 15, 12);
8786 Rn = Bits32(opcode, 19, 16);
8787 setflags = BitIsSet(opcode, 20);
8788 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8789 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8790 // TODO: Emulate SUBS PC, LR and related instructions.
8791 if (Rd == 15 && setflags)
8792 return false;
8793 break;
8794 default:
8795 return false;
8796 }
8797 // Read the register value from the operand register Rn.
8798 uint32_t reg_val = ReadCoreReg(Rn, &success);
8799 if (!success)
8800 return false;
8801
8802 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8803
8804 EmulateInstruction::Context context;
8805 context.type = EmulateInstruction::eContextImmediate;
8806 context.SetNoArgs ();
8807
8808 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8809 return false;
8810
8811 return true;
8812}
8813
8814// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8815// NOT (Carry flag) from a register value, and writes the result to the destination register.
8816// It can optionally update the condition flags based on the result.
8817bool
8818EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8819{
8820#if 0
8821 // ARM pseudo code...
8822 if ConditionPassed() then
8823 EncodingSpecificOperations();
8824 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8825 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8826 if d == 15 then // Can only occur for ARM encoding
8827 ALUWritePC(result); // setflags is always FALSE here
8828 else
8829 R[d] = result;
8830 if setflags then
8831 APSR.N = result<31>;
8832 APSR.Z = IsZeroBit(result);
8833 APSR.C = carry;
8834 APSR.V = overflow;
8835#endif
8836
8837 bool success = false;
8838 const uint32_t opcode = OpcodeAsUnsigned (&success);
8839 if (!success)
8840 return false;
8841
8842 uint32_t Rd; // the destination register
8843 uint32_t Rn; // the first operand
8844 uint32_t Rm; // the second operand
8845 bool setflags;
8846 ARM_ShifterType shift_t;
8847 uint32_t shift_n; // the shift applied to the value read from Rm
8848 switch (encoding) {
8849 case eEncodingT1:
8850 Rd = Rn = Bits32(opcode, 2, 0);
8851 Rm = Bits32(opcode, 5, 3);
8852 setflags = !InITBlock();
8853 shift_t = SRType_LSL;
8854 shift_n = 0;
8855 break;
8856 case eEncodingT2:
8857 Rd = Bits32(opcode, 11, 8);
8858 Rn = Bits32(opcode, 19, 16);
8859 Rm = Bits32(opcode, 3, 0);
8860 setflags = BitIsSet(opcode, 20);
8861 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8862 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8863 return false;
8864 break;
8865 case eEncodingA1:
8866 Rd = Bits32(opcode, 15, 12);
8867 Rn = Bits32(opcode, 19, 16);
8868 Rm = Bits32(opcode, 3, 0);
8869 setflags = BitIsSet(opcode, 20);
8870 shift_n = DecodeImmShiftARM(opcode, shift_t);
8871 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8872 // TODO: Emulate SUBS PC, LR and related instructions.
8873 if (Rd == 15 && setflags)
8874 return false;
8875 break;
8876 default:
8877 return false;
8878 }
8879 // Read the register value from register Rn.
8880 uint32_t val1 = ReadCoreReg(Rn, &success);
8881 if (!success)
8882 return false;
8883
8884 // Read the register value from register Rm.
8885 uint32_t val2 = ReadCoreReg(Rm, &success);
8886 if (!success)
8887 return false;
8888
8889 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8890 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8891
8892 EmulateInstruction::Context context;
8893 context.type = EmulateInstruction::eContextImmediate;
8894 context.SetNoArgs();
8895 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8896 return false;
8897
8898 return true;
8899}
8900
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008901// This instruction subtracts an immediate value from a register value, and writes the result
8902// to the destination register. It can optionally update the condition flags based on the result.
8903bool
8904EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8905{
8906#if 0
8907 // ARM pseudo code...
8908 if ConditionPassed() then
8909 EncodingSpecificOperations();
8910 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8911 R[d] = result;
8912 if setflags then
8913 APSR.N = result<31>;
8914 APSR.Z = IsZeroBit(result);
8915 APSR.C = carry;
8916 APSR.V = overflow;
8917#endif
8918
8919 bool success = false;
8920 const uint32_t opcode = OpcodeAsUnsigned (&success);
8921 if (!success)
8922 return false;
8923
8924 uint32_t Rd; // the destination register
8925 uint32_t Rn; // the first operand
8926 bool setflags;
8927 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8928 switch (encoding) {
8929 case eEncodingT1:
8930 Rd = Bits32(opcode, 2, 0);
8931 Rn = Bits32(opcode, 5, 3);
8932 setflags = !InITBlock();
8933 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8934 break;
8935 case eEncodingT2:
8936 Rd = Rn = Bits32(opcode, 10, 8);
8937 setflags = !InITBlock();
8938 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8939 break;
8940 case eEncodingT3:
8941 Rd = Bits32(opcode, 11, 8);
8942 Rn = Bits32(opcode, 19, 16);
8943 setflags = BitIsSet(opcode, 20);
8944 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8945
8946 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8947 if (Rd == 15 && setflags)
8948 return EmulateCMPImm(eEncodingT2);
8949
8950 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8951 if (Rn == 13)
8952 return EmulateSUBSPImm(eEncodingT2);
8953
8954 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8955 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8956 return false;
8957 break;
8958 case eEncodingT4:
8959 Rd = Bits32(opcode, 11, 8);
8960 Rn = Bits32(opcode, 19, 16);
8961 setflags = BitIsSet(opcode, 20);
8962 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8963
8964 // if Rn == '1111' then SEE ADR;
8965 if (Rn == 15)
8966 return EmulateADR(eEncodingT2);
8967
8968 // if Rn == '1101' then SEE SUB (SP minus immediate);
8969 if (Rn == 13)
8970 return EmulateSUBSPImm(eEncodingT3);
8971
8972 if (BadReg(Rd))
8973 return false;
8974 break;
8975 default:
8976 return false;
8977 }
8978 // Read the register value from the operand register Rn.
8979 uint32_t reg_val = ReadCoreReg(Rn, &success);
8980 if (!success)
8981 return false;
8982
8983 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8984
8985 EmulateInstruction::Context context;
8986 context.type = EmulateInstruction::eContextImmediate;
8987 context.SetNoArgs ();
8988
8989 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8990 return false;
8991
8992 return true;
8993}
8994
8995// This instruction subtracts an immediate value from a register value, and writes the result
8996// to the destination register. It can optionally update the condition flags based on the result.
8997bool
8998EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
8999{
9000#if 0
9001 // ARM pseudo code...
9002 if ConditionPassed() then
9003 EncodingSpecificOperations();
9004 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9005 if d == 15 then
9006 ALUWritePC(result); // setflags is always FALSE here
9007 else
9008 R[d] = result;
9009 if setflags then
9010 APSR.N = result<31>;
9011 APSR.Z = IsZeroBit(result);
9012 APSR.C = carry;
9013 APSR.V = overflow;
9014#endif
9015
9016 bool success = false;
9017 const uint32_t opcode = OpcodeAsUnsigned (&success);
9018 if (!success)
9019 return false;
9020
9021 uint32_t Rd; // the destination register
9022 uint32_t Rn; // the first operand
9023 bool setflags;
9024 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9025 switch (encoding) {
9026 case eEncodingA1:
9027 Rd = Bits32(opcode, 15, 12);
9028 Rn = Bits32(opcode, 19, 16);
9029 setflags = BitIsSet(opcode, 20);
9030 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9031
9032 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
9033 if (Rn == 15 && !setflags)
9034 return EmulateADR(eEncodingA2);
9035
9036 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
9037 if (Rn == 13)
9038 return EmulateSUBSPImm(eEncodingA1);
9039
9040 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
9041 // TODO: Emulate SUBS PC, LR and related instructions.
9042 if (Rd == 15 && setflags)
9043 return false;
9044 break;
9045 default:
9046 return false;
9047 }
9048 // Read the register value from the operand register Rn.
9049 uint32_t reg_val = ReadCoreReg(Rn, &success);
9050 if (!success)
9051 return false;
9052
9053 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9054
9055 EmulateInstruction::Context context;
9056 context.type = EmulateInstruction::eContextImmediate;
9057 context.SetNoArgs ();
9058
9059 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9060 return false;
9061
9062 return true;
9063}
9064
Johnny Chen2115b412011-02-21 23:42:44 +00009065// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9066// immediate value. It updates the condition flags based on the result, and discards the result.
9067bool
9068EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
9069{
9070#if 0
9071 // ARM pseudo code...
9072 if ConditionPassed() then
9073 EncodingSpecificOperations();
9074 result = R[n] EOR imm32;
9075 APSR.N = result<31>;
9076 APSR.Z = IsZeroBit(result);
9077 APSR.C = carry;
9078 // APSR.V unchanged
9079#endif
9080
9081 bool success = false;
9082 const uint32_t opcode = OpcodeAsUnsigned (&success);
9083 if (!success)
9084 return false;
9085
9086 if (ConditionPassed())
9087 {
9088 uint32_t Rn;
9089 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9090 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9091 switch (encoding)
9092 {
9093 case eEncodingT1:
9094 Rn = Bits32(opcode, 19, 16);
9095 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9096 if (BadReg(Rn))
9097 return false;
9098 break;
9099 case eEncodingA1:
9100 Rn = Bits32(opcode, 19, 16);
9101 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9102 break;
9103 default:
9104 return false;
9105 }
9106
9107 // Read the first operand.
9108 uint32_t val1 = ReadCoreReg(Rn, &success);
9109 if (!success)
9110 return false;
9111
9112 uint32_t result = val1 ^ imm32;
9113
9114 EmulateInstruction::Context context;
9115 context.type = EmulateInstruction::eContextImmediate;
9116 context.SetNoArgs ();
9117
9118 if (!WriteFlags(context, result, carry))
9119 return false;
9120 }
9121 return true;
9122}
9123
9124// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9125// optionally-shifted register value. It updates the condition flags based on the result, and discards
9126// the result.
9127bool
9128EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
9129{
9130#if 0
9131 // ARM pseudo code...
9132 if ConditionPassed() then
9133 EncodingSpecificOperations();
9134 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9135 result = R[n] EOR shifted;
9136 APSR.N = result<31>;
9137 APSR.Z = IsZeroBit(result);
9138 APSR.C = carry;
9139 // APSR.V unchanged
9140#endif
9141
9142 bool success = false;
9143 const uint32_t opcode = OpcodeAsUnsigned (&success);
9144 if (!success)
9145 return false;
9146
9147 if (ConditionPassed())
9148 {
9149 uint32_t Rn, Rm;
9150 ARM_ShifterType shift_t;
9151 uint32_t shift_n; // the shift applied to the value read from Rm
9152 uint32_t carry;
9153 switch (encoding)
9154 {
9155 case eEncodingT1:
9156 Rn = Bits32(opcode, 19, 16);
9157 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009158 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009159 if (BadReg(Rn) || BadReg(Rm))
9160 return false;
9161 break;
9162 case eEncodingA1:
9163 Rn = Bits32(opcode, 19, 16);
9164 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009165 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009166 break;
9167 default:
9168 return false;
9169 }
9170
9171 // Read the first operand.
9172 uint32_t val1 = ReadCoreReg(Rn, &success);
9173 if (!success)
9174 return false;
9175
9176 // Read the second operand.
9177 uint32_t val2 = ReadCoreReg(Rm, &success);
9178 if (!success)
9179 return false;
9180
9181 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9182 uint32_t result = val1 ^ shifted;
9183
9184 EmulateInstruction::Context context;
9185 context.type = EmulateInstruction::eContextImmediate;
9186 context.SetNoArgs ();
9187
9188 if (!WriteFlags(context, result, carry))
9189 return false;
9190 }
9191 return true;
9192}
9193
Johnny Chende3cce32011-02-21 21:24:49 +00009194// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9195// It updates the condition flags based on the result, and discards the result.
9196bool
9197EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
9198{
9199#if 0
9200 // ARM pseudo code...
9201 if ConditionPassed() then
9202 EncodingSpecificOperations();
9203 result = R[n] AND imm32;
9204 APSR.N = result<31>;
9205 APSR.Z = IsZeroBit(result);
9206 APSR.C = carry;
9207 // APSR.V unchanged
9208#endif
9209
9210 bool success = false;
9211 const uint32_t opcode = OpcodeAsUnsigned (&success);
9212 if (!success)
9213 return false;
9214
9215 if (ConditionPassed())
9216 {
9217 uint32_t Rn;
9218 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9219 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9220 switch (encoding)
9221 {
9222 case eEncodingT1:
9223 Rn = Bits32(opcode, 19, 16);
9224 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9225 if (BadReg(Rn))
9226 return false;
9227 break;
9228 case eEncodingA1:
9229 Rn = Bits32(opcode, 19, 16);
9230 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9231 break;
9232 default:
9233 return false;
9234 }
9235
9236 // Read the first operand.
9237 uint32_t val1 = ReadCoreReg(Rn, &success);
9238 if (!success)
9239 return false;
9240
9241 uint32_t result = val1 & imm32;
9242
9243 EmulateInstruction::Context context;
9244 context.type = EmulateInstruction::eContextImmediate;
9245 context.SetNoArgs ();
9246
9247 if (!WriteFlags(context, result, carry))
9248 return false;
9249 }
9250 return true;
9251}
9252
9253// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9254// It updates the condition flags based on the result, and discards the result.
9255bool
9256EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
9257{
9258#if 0
9259 // ARM pseudo code...
9260 if ConditionPassed() then
9261 EncodingSpecificOperations();
9262 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9263 result = R[n] AND shifted;
9264 APSR.N = result<31>;
9265 APSR.Z = IsZeroBit(result);
9266 APSR.C = carry;
9267 // APSR.V unchanged
9268#endif
9269
9270 bool success = false;
9271 const uint32_t opcode = OpcodeAsUnsigned (&success);
9272 if (!success)
9273 return false;
9274
9275 if (ConditionPassed())
9276 {
9277 uint32_t Rn, Rm;
9278 ARM_ShifterType shift_t;
9279 uint32_t shift_n; // the shift applied to the value read from Rm
9280 uint32_t carry;
9281 switch (encoding)
9282 {
9283 case eEncodingT1:
9284 Rn = Bits32(opcode, 2, 0);
9285 Rm = Bits32(opcode, 5, 3);
9286 shift_t = SRType_LSL;
9287 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009288 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009289 case eEncodingT2:
9290 Rn = Bits32(opcode, 19, 16);
9291 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009292 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009293 if (BadReg(Rn) || BadReg(Rm))
9294 return false;
9295 break;
9296 case eEncodingA1:
9297 Rn = Bits32(opcode, 19, 16);
9298 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009299 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009300 break;
9301 default:
9302 return false;
9303 }
9304
9305 // Read the first operand.
9306 uint32_t val1 = ReadCoreReg(Rn, &success);
9307 if (!success)
9308 return false;
9309
9310 // Read the second operand.
9311 uint32_t val2 = ReadCoreReg(Rm, &success);
9312 if (!success)
9313 return false;
9314
9315 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9316 uint32_t result = val1 & shifted;
9317
9318 EmulateInstruction::Context context;
9319 context.type = EmulateInstruction::eContextImmediate;
9320 context.SetNoArgs ();
9321
9322 if (!WriteFlags(context, result, carry))
9323 return false;
9324 }
9325 return true;
9326}
9327
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009328EmulateInstructionARM::ARMOpcode*
9329EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009330{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009331 static ARMOpcode
9332 g_arm_opcodes[] =
9333 {
9334 //----------------------------------------------------------------------
9335 // Prologue instructions
9336 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009337
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009338 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009339 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9340 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009341
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009342 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009343 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009344 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009345 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009346 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9347 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009348 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009349
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009350 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009351 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009352
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009353 // push one register
9354 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice3e407972011-03-18 19:41:00 +00009355 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009356
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009357 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009358 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9359 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009360
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009361 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009362 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009363 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009364
Johnny Chen9f687722011-02-18 00:02:28 +00009365 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9366 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009367 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009368 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9369
9370 //----------------------------------------------------------------------
9371 // Supervisor Call (previously Software Interrupt)
9372 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009373 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9374
9375 //----------------------------------------------------------------------
9376 // Branch instructions
9377 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009378 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009379 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9380 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9381 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9382 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009383 // for example, "bx lr"
9384 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009385 // bxj
9386 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009387
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009388 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009389 // Data-processing instructions
9390 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009391 // adc (immediate)
9392 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9393 // adc (register)
9394 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009395 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009396 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009397 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009398 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009399 // adr
9400 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9401 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009402 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009403 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009404 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009405 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009406 // bic (immediate)
9407 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9408 // bic (register)
9409 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009410 // eor (immediate)
9411 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9412 // eor (register)
9413 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009414 // orr (immediate)
9415 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9416 // orr (register)
9417 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009418 // rsb (immediate)
9419 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9420 // rsb (register)
9421 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009422 // rsc (immediate)
9423 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9424 // rsc (register)
9425 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009426 // sbc (immediate)
9427 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9428 // sbc (register)
9429 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009430 // sub (immediate, ARM)
9431 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009432 // sub (sp minus immediate)
9433 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009434 // teq (immediate)
9435 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9436 // teq (register)
9437 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009438 // tst (immediate)
9439 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9440 // tst (register)
9441 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9442
9443
Johnny Chen01d61572011-02-25 00:23:25 +00009444 // mov (register)
9445 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009446 // mvn (immediate)
9447 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9448 // mvn (register)
9449 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009450 // cmn (immediate)
9451 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9452 // cmn (register)
9453 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009454 // cmp (immediate)
9455 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9456 // cmp (register)
9457 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009458 // asr (immediate)
9459 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009460 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009461 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009462 // lsl (immediate)
9463 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9464 // lsl (register)
9465 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9466 // lsr (immediate)
9467 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9468 // lsr (register)
9469 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009470 // rrx is a special case encoding of ror (immediate)
9471 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9472 // ror (immediate)
9473 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9474 // ror (register)
9475 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009476 // mul
9477 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009478
9479 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009480 // Load instructions
9481 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009482 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009483 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009484 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009485 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009486 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009487 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009488 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009489 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009490 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009491 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009492 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009493 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009494 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009495 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009496 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9497 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009498
9499 //----------------------------------------------------------------------
9500 // Store instructions
9501 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009502 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009503 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009504 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009505 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009506 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009507 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009508
Caroline Tice6bf65162011-03-03 17:42:58 +00009509 //----------------------------------------------------------------------
9510 // Other instructions
9511 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009512 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009513 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009514 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009515 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9516 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009517
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009518 };
9519 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9520
9521 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9522 {
9523 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9524 return &g_arm_opcodes[i];
9525 }
9526 return NULL;
9527}
Greg Clayton64c84432011-01-21 22:02:52 +00009528
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009529
9530EmulateInstructionARM::ARMOpcode*
9531EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009532{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009533
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009534 static ARMOpcode
9535 g_thumb_opcodes[] =
9536 {
9537 //----------------------------------------------------------------------
9538 // Prologue instructions
9539 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009540
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009541 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009542 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9543 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9544 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009545
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009546 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009547 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009548 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009549 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009550 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009551 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009552
Johnny Chen864a8e82011-02-18 00:07:39 +00009553 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009554 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009555
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009556 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009557 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009558 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009559 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9560 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009561
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009562 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009563 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9564 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009565
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009566 //----------------------------------------------------------------------
9567 // Epilogue instructions
9568 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009569
Johnny Chen864a8e82011-02-18 00:07:39 +00009570 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009571 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9572 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9573 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009574 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9575 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009576
9577 //----------------------------------------------------------------------
9578 // Supervisor Call (previously Software Interrupt)
9579 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009580 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9581
9582 //----------------------------------------------------------------------
9583 // If Then makes up to four following instructions conditional.
9584 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009585 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9586
9587 //----------------------------------------------------------------------
9588 // Branch instructions
9589 //----------------------------------------------------------------------
9590 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9591 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009592 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009593 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009594 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009595 // J1 == J2 == 1
9596 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9597 // J1 == J2 == 1
9598 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9599 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009600 // for example, "bx lr"
9601 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009602 // bxj
9603 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009604 // compare and branch
9605 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009606 // table branch byte
9607 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9608 // table branch halfword
9609 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009610
9611 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009612 // Data-processing instructions
9613 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009614 // adc (immediate)
9615 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9616 // adc (register)
9617 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9618 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9619 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009620 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009621 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009622 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009623 // adr
9624 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9625 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9626 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009627 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009628 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009629 // and (register)
9630 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9631 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009632 // bic (immediate)
9633 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9634 // bic (register)
9635 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9636 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009637 // eor (immediate)
9638 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9639 // eor (register)
9640 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9641 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009642 // orr (immediate)
9643 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9644 // orr (register)
9645 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9646 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009647 // rsb (immediate)
9648 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9649 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9650 // rsb (register)
9651 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009652 // sbc (immediate)
9653 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9654 // sbc (register)
9655 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9656 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009657 // add (immediate, Thumb)
9658 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9659 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9660 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9661 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009662 // sub (immediate, Thumb)
9663 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9664 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9665 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9666 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009667 // sub (sp minus immediate)
9668 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9669 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009670 // teq (immediate)
9671 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9672 // teq (register)
9673 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009674 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009675 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009676 // tst (register)
9677 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9678 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9679
Johnny Chen7c5234d2011-02-18 23:41:11 +00009680
Johnny Chen338bf542011-02-10 19:29:03 +00009681 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009682 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009683 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009684 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009685 // mov{s}<c>.w <Rd>, <Rm>
9686 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009687 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009688 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9689 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009690 // mvn (immediate)
9691 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9692 // mvn (register)
9693 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9694 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009695 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009696 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009697 // cmn (register)
9698 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009699 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009700 // cmp (immediate)
9701 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009702 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009703 // cmp (register) (Rn and Rm both from r0-r7)
9704 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9705 // cmp (register) (Rn and Rm not both from r0-r7)
9706 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009707 // asr (immediate)
9708 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009709 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009710 // asr (register)
9711 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9712 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009713 // lsl (immediate)
9714 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9715 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9716 // lsl (register)
9717 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9718 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9719 // lsr (immediate)
9720 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9721 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9722 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009723 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009724 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009725 // rrx is a special case encoding of ror (immediate)
9726 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9727 // ror (immediate)
9728 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9729 // ror (register)
9730 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9731 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009732 // mul
9733 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9734 // mul
9735 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009736
Johnny Chen26863dc2011-02-09 23:43:29 +00009737 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009738 // Load instructions
9739 //----------------------------------------------------------------------
9740 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009741 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009742 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00009743 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9744 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009745 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009746 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9747 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009748 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9749 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9750 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009751 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009752 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9753 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009754 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9755 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9756 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009757 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009758 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9759 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009760 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9761 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009762 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009763 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9764 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009765 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9766 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009767 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009768 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9769 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009770
9771 //----------------------------------------------------------------------
9772 // Store instructions
9773 //----------------------------------------------------------------------
9774 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009775 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009776 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009777 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9778 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9779 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9780 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9781 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9782 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9783 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9784 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009785 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009786 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
9787 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009788
9789 //----------------------------------------------------------------------
9790 // Other instructions
9791 //----------------------------------------------------------------------
9792 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009793 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9794 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009795 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9796 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009797 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9798 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009799 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9800 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9801 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009802
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009803 };
9804
9805 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9806 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9807 {
9808 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9809 return &g_thumb_opcodes[i];
9810 }
9811 return NULL;
9812}
Greg Clayton64c84432011-01-21 22:02:52 +00009813
Greg Clayton31e2a382011-01-30 20:03:56 +00009814bool
Greg Clayton395fc332011-02-15 21:59:32 +00009815EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009816{
9817 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009818 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009819 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009820 {
Greg Clayton395fc332011-02-15 21:59:32 +00009821 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9822 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9823 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9824 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9825 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9826 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9827 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9828 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9829 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9830 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009831 }
9832 return m_arm_isa != 0;
9833}
9834
9835
Greg Clayton64c84432011-01-21 22:02:52 +00009836bool
9837EmulateInstructionARM::ReadInstruction ()
9838{
9839 bool success = false;
9840 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
9841 if (success)
9842 {
9843 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9844 if (success)
9845 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009846 Context read_inst_context;
9847 read_inst_context.type = eContextReadOpcode;
9848 read_inst_context.SetNoArgs ();
9849
Greg Clayton64c84432011-01-21 22:02:52 +00009850 if (m_inst_cpsr & MASK_CPSR_T)
9851 {
9852 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009853 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009854
9855 if (success)
9856 {
9857 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9858 {
9859 m_inst.opcode_type = eOpcode16;
9860 m_inst.opcode.inst16 = thumb_opcode;
9861 }
9862 else
9863 {
9864 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009865 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009866 }
9867 }
9868 }
9869 else
9870 {
9871 m_inst_mode = eModeARM;
9872 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009873 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009874 }
9875 }
9876 }
9877 if (!success)
9878 {
9879 m_inst_mode = eModeInvalid;
9880 m_inst_pc = LLDB_INVALID_ADDRESS;
9881 }
9882 return success;
9883}
9884
Johnny Chenee9b1f72011-02-09 01:00:31 +00009885uint32_t
9886EmulateInstructionARM::ArchVersion ()
9887{
9888 return m_arm_isa;
9889}
9890
Greg Clayton64c84432011-01-21 22:02:52 +00009891bool
9892EmulateInstructionARM::ConditionPassed ()
9893{
9894 if (m_inst_cpsr == 0)
9895 return false;
9896
9897 const uint32_t cond = CurrentCond ();
9898
9899 if (cond == UINT32_MAX)
9900 return false;
9901
9902 bool result = false;
9903 switch (UnsignedBits(cond, 3, 1))
9904 {
9905 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9906 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9907 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9908 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9909 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9910 case 5:
9911 {
9912 bool n = (m_inst_cpsr & MASK_CPSR_N);
9913 bool v = (m_inst_cpsr & MASK_CPSR_V);
9914 result = n == v;
9915 }
9916 break;
9917 case 6:
9918 {
9919 bool n = (m_inst_cpsr & MASK_CPSR_N);
9920 bool v = (m_inst_cpsr & MASK_CPSR_V);
9921 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
9922 }
9923 break;
9924 case 7:
9925 result = true;
9926 break;
9927 }
9928
9929 if (cond & 1)
9930 result = !result;
9931 return result;
9932}
9933
Johnny Chen9ee056b2011-02-08 00:06:35 +00009934uint32_t
9935EmulateInstructionARM::CurrentCond ()
9936{
9937 switch (m_inst_mode)
9938 {
9939 default:
9940 case eModeInvalid:
9941 break;
9942
9943 case eModeARM:
9944 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
9945
9946 case eModeThumb:
9947 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9948 // 'cond' field of the encoding.
9949 if (m_inst.opcode_type == eOpcode16 &&
9950 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
9951 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
9952 {
9953 return Bits32(m_inst.opcode.inst16, 11, 7);
9954 }
9955 else if (m_inst.opcode_type == eOpcode32 &&
9956 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
9957 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
9958 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
9959 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
9960 {
9961 return Bits32(m_inst.opcode.inst32, 25, 22);
9962 }
9963
9964 return m_it_session.GetCond();
9965 }
9966 return UINT32_MAX; // Return invalid value
9967}
9968
Johnny Chen9ee056b2011-02-08 00:06:35 +00009969bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009970EmulateInstructionARM::InITBlock()
9971{
9972 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9973}
9974
9975bool
9976EmulateInstructionARM::LastInITBlock()
9977{
9978 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9979}
9980
Caroline Ticeb27771d2011-03-03 22:37:46 +00009981bool
9982EmulateInstructionARM::BadMode (uint32_t mode)
9983{
9984
9985 switch (mode)
9986 {
9987 case 16: return false; // '10000'
9988 case 17: return false; // '10001'
9989 case 18: return false; // '10010'
9990 case 19: return false; // '10011'
9991 case 22: return false; // '10110'
9992 case 23: return false; // '10111'
9993 case 27: return false; // '11011'
9994 case 31: return false; // '11111'
9995 default: return true;
9996 }
9997 return true;
9998}
9999
10000bool
10001EmulateInstructionARM::CurrentModeIsPrivileged ()
10002{
10003 uint32_t mode = Bits32 (m_inst_cpsr, 4, 0);
10004
10005 if (BadMode (mode))
10006 return false;
10007
10008 if (mode == 16)
10009 return false;
10010
10011 return true;
10012}
10013
10014void
10015EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
10016{
10017 bool privileged = CurrentModeIsPrivileged();
10018
10019 uint32_t tmp_cpsr = 0;
10020
10021 tmp_cpsr = tmp_cpsr | (Bits32 (m_inst_cpsr, 23, 20) << 20);
10022
10023 if (BitIsSet (bytemask, 3))
10024 {
10025 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
10026 if (affect_execstate)
10027 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
10028 }
10029
10030 if (BitIsSet (bytemask, 2))
10031 {
10032 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
10033 }
10034
10035 if (BitIsSet (bytemask, 1))
10036 {
10037 if (affect_execstate)
10038 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
10039 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
10040 if (privileged)
10041 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
10042 }
10043
10044 if (BitIsSet (bytemask, 0))
10045 {
10046 if (privileged)
10047 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
10048 if (affect_execstate)
10049 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
10050 if (privileged)
10051 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
10052 }
10053
10054 m_inst_cpsr = tmp_cpsr;
10055}
10056
10057
Johnny Chen098ae2d2011-02-12 00:50:05 +000010058bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000010059EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
10060{
10061 addr_t target;
10062
Johnny Chenee9b1f72011-02-09 01:00:31 +000010063 // Check the current instruction set.
10064 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010065 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010066 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000010067 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010068
Johnny Chen9ee056b2011-02-08 00:06:35 +000010069 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010070 return false;
10071
10072 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010073}
10074
10075// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
10076bool
Johnny Chen668b4512011-02-15 21:08:58 +000010077EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010078{
10079 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000010080 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
10081 // we want to record it and issue a WriteRegister callback so the clients
10082 // can track the mode changes accordingly.
10083 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010084
10085 if (BitIsSet(addr, 0))
10086 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010087 if (CurrentInstrSet() != eModeThumb)
10088 {
10089 SelectInstrSet(eModeThumb);
10090 cpsr_changed = true;
10091 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010092 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000010093 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010094 }
10095 else if (BitIsClear(addr, 1))
10096 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010097 if (CurrentInstrSet() != eModeARM)
10098 {
10099 SelectInstrSet(eModeARM);
10100 cpsr_changed = true;
10101 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010102 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000010103 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010104 }
10105 else
10106 return false; // address<1:0> == '10' => UNPREDICTABLE
10107
Johnny Chen0f309db2011-02-09 19:11:32 +000010108 if (cpsr_changed)
10109 {
Johnny Chen558133b2011-02-09 23:59:17 +000010110 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000010111 return false;
10112 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010113 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010114 return false;
10115
10116 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010117}
Greg Clayton64c84432011-01-21 22:02:52 +000010118
Johnny Chenee9b1f72011-02-09 01:00:31 +000010119// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
10120bool
Johnny Chen668b4512011-02-15 21:08:58 +000010121EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000010122{
10123 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000010124 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000010125 else
10126 return BranchWritePC((const Context)context, addr);
10127}
10128
Johnny Chen26863dc2011-02-09 23:43:29 +000010129// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
10130bool
Johnny Chen668b4512011-02-15 21:08:58 +000010131EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000010132{
10133 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000010134 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000010135 else
10136 return BranchWritePC((const Context)context, addr);
10137}
10138
Johnny Chenee9b1f72011-02-09 01:00:31 +000010139EmulateInstructionARM::Mode
10140EmulateInstructionARM::CurrentInstrSet ()
10141{
10142 return m_inst_mode;
10143}
10144
10145// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000010146// ReadInstruction() is performed. This function has a side effect of updating
10147// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000010148bool
10149EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
10150{
Johnny Chen558133b2011-02-09 23:59:17 +000010151 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010152 switch (arm_or_thumb)
10153 {
10154 default:
10155 return false;
10156 eModeARM:
10157 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010158 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010159 break;
10160 eModeThumb:
10161 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010162 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010163 break;
10164 }
10165 return true;
10166}
10167
Johnny Chenef21b592011-02-10 01:52:38 +000010168// This function returns TRUE if the processor currently provides support for
10169// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
10170// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
10171bool
10172EmulateInstructionARM::UnalignedSupport()
10173{
10174 return (ArchVersion() >= ARMv7);
10175}
10176
Johnny Chenbf6ad172011-02-11 01:29:53 +000010177// The main addition and subtraction instructions can produce status information
10178// about both unsigned carry and signed overflow conditions. This status
10179// information can be used to synthesize multi-word additions and subtractions.
10180EmulateInstructionARM::AddWithCarryResult
10181EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
10182{
10183 uint32_t result;
10184 uint8_t carry_out;
10185 uint8_t overflow;
10186
10187 uint64_t unsigned_sum = x + y + carry_in;
10188 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
10189
10190 result = UnsignedBits(unsigned_sum, 31, 0);
10191 carry_out = (result == unsigned_sum ? 0 : 1);
10192 overflow = ((int32_t)result == signed_sum ? 0 : 1);
10193
10194 AddWithCarryResult res = { result, carry_out, overflow };
10195 return res;
10196}
10197
Johnny Chen157b9592011-02-18 21:13:05 +000010198uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000010199EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000010200{
Johnny Chene39f22d2011-02-19 01:36:13 +000010201 uint32_t reg_kind, reg_num;
10202 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000010203 {
Johnny Chene39f22d2011-02-19 01:36:13 +000010204 case SP_REG:
10205 reg_kind = eRegisterKindGeneric;
10206 reg_num = LLDB_REGNUM_GENERIC_SP;
10207 break;
10208 case LR_REG:
10209 reg_kind = eRegisterKindGeneric;
10210 reg_num = LLDB_REGNUM_GENERIC_RA;
10211 break;
10212 case PC_REG:
10213 reg_kind = eRegisterKindGeneric;
10214 reg_num = LLDB_REGNUM_GENERIC_PC;
10215 break;
10216 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000010217 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000010218 {
10219 reg_kind = eRegisterKindDWARF;
10220 reg_num = dwarf_r0 + num;
10221 }
Johnny Chen157b9592011-02-18 21:13:05 +000010222 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010223 {
10224 assert(0 && "Invalid register number");
10225 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000010226 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000010227 }
10228 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010229 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010230
10231 // Read our register.
10232 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10233
10234 // When executing an ARM instruction , PC reads as the address of the current
10235 // instruction plus 8.
10236 // When executing a Thumb instruction , PC reads as the address of the current
10237 // instruction plus 4.
10238 if (num == 15)
10239 {
10240 if (CurrentInstrSet() == eModeARM)
10241 val += 8;
10242 else
10243 val += 4;
10244 }
Johnny Chen157b9592011-02-18 21:13:05 +000010245
10246 return val;
10247}
10248
Johnny Chenca67d1c2011-02-17 01:35:27 +000010249// Write the result to the ARM core register Rd, and optionally update the
10250// condition flags based on the result.
10251//
10252// This helper method tries to encapsulate the following pseudocode from the
10253// ARM Architecture Reference Manual:
10254//
10255// if d == 15 then // Can only occur for encoding A1
10256// ALUWritePC(result); // setflags is always FALSE here
10257// else
10258// R[d] = result;
10259// if setflags then
10260// APSR.N = result<31>;
10261// APSR.Z = IsZeroBit(result);
10262// APSR.C = carry;
10263// // APSR.V unchanged
10264//
10265// In the above case, the API client does not pass in the overflow arg, which
10266// defaults to ~0u.
10267bool
Johnny Chen10530c22011-02-17 22:37:12 +000010268EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10269 const uint32_t result,
10270 const uint32_t Rd,
10271 bool setflags,
10272 const uint32_t carry,
10273 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010274{
10275 if (Rd == 15)
10276 {
10277 if (!ALUWritePC (context, result))
10278 return false;
10279 }
10280 else
10281 {
Johnny Chena695f952011-02-23 21:24:25 +000010282 uint32_t reg_kind, reg_num;
10283 switch (Rd)
10284 {
10285 case SP_REG:
10286 reg_kind = eRegisterKindGeneric;
10287 reg_num = LLDB_REGNUM_GENERIC_SP;
10288 break;
10289 case LR_REG:
10290 reg_kind = eRegisterKindGeneric;
10291 reg_num = LLDB_REGNUM_GENERIC_RA;
10292 break;
10293 default:
10294 reg_kind = eRegisterKindDWARF;
10295 reg_num = dwarf_r0 + Rd;
10296 }
10297 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010298 return false;
10299 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010300 return WriteFlags (context, result, carry, overflow);
10301 }
10302 return true;
10303}
10304
10305// This helper method tries to encapsulate the following pseudocode from the
10306// ARM Architecture Reference Manual:
10307//
10308// APSR.N = result<31>;
10309// APSR.Z = IsZeroBit(result);
10310// APSR.C = carry;
10311// APSR.V = overflow
10312//
10313// Default arguments can be specified for carry and overflow parameters, which means
10314// not to update the respective flags.
10315bool
10316EmulateInstructionARM::WriteFlags (Context &context,
10317 const uint32_t result,
10318 const uint32_t carry,
10319 const uint32_t overflow)
10320{
10321 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010322 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10323 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010324 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010325 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010326 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010327 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +000010328 if (m_new_inst_cpsr != m_inst_cpsr)
10329 {
10330 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10331 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010332 }
10333 return true;
10334}
10335
Greg Clayton64c84432011-01-21 22:02:52 +000010336bool
10337EmulateInstructionARM::EvaluateInstruction ()
10338{
Johnny Chenc315f862011-02-05 00:46:10 +000010339 // Advance the ITSTATE bits to their values for the next instruction.
10340 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
10341 m_it_session.ITAdvance();
10342
Greg Clayton64c84432011-01-21 22:02:52 +000010343 return false;
10344}