blob: 70617970d2eb4e203730c0f7ccf3f56c2192b191 [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.
Greg Claytonb3448432011-03-24 21:19:54 +000027#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
28#define APSR_V Bit32(m_opcode_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)
Caroline Tice1697dd72011-03-30 17:11:45 +0000132#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000133#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000134#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000135#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000136
Johnny Chen0e00af22011-02-10 19:40:42 +0000137//----------------------------------------------------------------------
138//
139// EmulateInstructionARM implementation
140//
141//----------------------------------------------------------------------
142
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000143void
144EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000145{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000146}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000147
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000148void
149EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000150{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000151}
152
Caroline Ticefa172202011-02-11 22:49:54 +0000153// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
154bool
155EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
156{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000157 EmulateInstruction::Context context;
158 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
159 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000160
161 uint32_t random_data = rand ();
162 const uint32_t addr_byte_size = GetAddressByteSize();
163
Caroline Ticecc96eb52011-02-17 19:20:40 +0000164 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000165 return false;
166
167 return true;
168}
169
Caroline Tice713c2662011-02-11 17:59:55 +0000170// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
171bool
172EmulateInstructionARM::WriteBits32Unknown (int n)
173{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000174 EmulateInstruction::Context context;
175 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
176 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000177
Johnny Chen62ff6f52011-02-11 18:11:22 +0000178 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000179 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
180
181 if (!success)
182 return false;
183
184 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
185 return false;
186
187 return true;
188}
189
Johnny Chen08c25e82011-01-31 18:02:28 +0000190// Push Multiple Registers stores multiple registers to the stack, storing to
191// consecutive memory locations ending just below the address in SP, and updates
192// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000193bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000194EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000195{
196#if 0
197 // ARM pseudo code...
198 if (ConditionPassed())
199 {
200 EncodingSpecificOperations();
201 NullCheckIfThumbEE(13);
202 address = SP - 4*BitCount(registers);
203
204 for (i = 0 to 14)
205 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000206 if (registers<i> == '1')
Greg Clayton64c84432011-01-21 22:02:52 +0000207 {
208 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
209 MemA[address,4] = bits(32) UNKNOWN;
210 else
211 MemA[address,4] = R[i];
212 address = address + 4;
213 }
214 }
215
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000216 if (registers<15> == '1') // Only possible for encoding A1 or A2
Greg Clayton64c84432011-01-21 22:02:52 +0000217 MemA[address,4] = PCStoreValue();
218
219 SP = SP - 4*BitCount(registers);
220 }
221#endif
222
223 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +0000224 if (ConditionPassed(opcode))
Greg Clayton64c84432011-01-21 22:02:52 +0000225 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000226 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000227 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000228 if (!success)
229 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000230 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000231 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000232 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000233 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000234 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000235 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000236 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000237 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000238 // if BitCount(registers) < 1 then UNPREDICTABLE;
239 if (BitCount(registers) < 1)
240 return false;
241 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000242 case eEncodingT2:
243 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000244 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000245 // if BitCount(registers) < 2 then UNPREDICTABLE;
246 if (BitCount(registers) < 2)
247 return false;
248 break;
249 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000250 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000251 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000252 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000253 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000254 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000255 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000256 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000257 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000258 // Instead of return false, let's handle the following case as well,
259 // which amounts to pushing one reg onto the full descending stacks.
260 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000261 break;
262 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000263 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000264 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000265 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000266 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000267 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000268 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000269 default:
270 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000271 }
Johnny Chence1ca772011-01-25 01:13:00 +0000272 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000273 addr_t addr = sp - sp_offset;
274 uint32_t i;
275
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000276 EmulateInstruction::Context context;
277 context.type = EmulateInstruction::eContextPushRegisterOnStack;
278 Register dwarf_reg;
279 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000280 Register sp_reg;
281 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
Greg Clayton64c84432011-01-21 22:02:52 +0000282 for (i=0; i<15; ++i)
283 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000284 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000285 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000286 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000287 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000288 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000289 if (!success)
290 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000291 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000292 return false;
293 addr += addr_byte_size;
294 }
295 }
296
Johnny Chen7c1bf922011-02-08 23:49:37 +0000297 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000298 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000299 dwarf_reg.num = dwarf_pc;
300 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000301 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000302 if (!success)
303 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000304 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000305 return false;
306 }
307
308 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000309 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000310
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000311 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000312 return false;
313 }
314 return true;
315}
316
Johnny Chenef85e912011-01-31 23:07:40 +0000317// Pop Multiple Registers loads multiple registers from the stack, loading from
318// consecutive memory locations staring at the address in SP, and updates
319// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000320bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000321EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000322{
323#if 0
324 // ARM pseudo code...
325 if (ConditionPassed())
326 {
327 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
328 address = SP;
329 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000330 if registers<i> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000331 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000332 if registers<15> == '1' then
Johnny Chenef85e912011-01-31 23:07:40 +0000333 if UnalignedAllowed then
334 LoadWritePC(MemU[address,4]);
335 else
336 LoadWritePC(MemA[address,4]);
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000337 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
338 if registers<13> == '1' then SP = bits(32) UNKNOWN;
Johnny Chenef85e912011-01-31 23:07:40 +0000339 }
340#endif
341
342 bool success = false;
Johnny Chenef85e912011-01-31 23:07:40 +0000343
Greg Clayton7bc39082011-03-24 23:53:38 +0000344 if (ConditionPassed(opcode))
Johnny Chenef85e912011-01-31 23:07:40 +0000345 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000347 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000348 if (!success)
349 return false;
350 uint32_t registers = 0;
351 uint32_t Rt; // the destination register
352 switch (encoding) {
353 case eEncodingT1:
354 registers = Bits32(opcode, 7, 0);
355 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000356 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000357 registers |= (1u << 15);
358 // if BitCount(registers) < 1 then UNPREDICTABLE;
359 if (BitCount(registers) < 1)
360 return false;
361 break;
362 case eEncodingT2:
363 // Ignore bit 13.
364 registers = Bits32(opcode, 15, 0) & ~0x2000;
365 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000366 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000367 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000368 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
369 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
370 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000371 break;
372 case eEncodingT3:
373 Rt = Bits32(opcode, 15, 12);
374 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000375 if (Rt == 13)
376 return false;
377 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000378 return false;
379 registers = (1u << Rt);
380 break;
381 case eEncodingA1:
382 registers = Bits32(opcode, 15, 0);
383 // Instead of return false, let's handle the following case as well,
384 // which amounts to popping one reg from the full descending stacks.
385 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
386
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000387 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000388 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000389 return false;
390 break;
391 case eEncodingA2:
392 Rt = Bits32(opcode, 15, 12);
393 // if t == 13 then UNPREDICTABLE;
394 if (Rt == dwarf_sp)
395 return false;
396 registers = (1u << Rt);
397 break;
398 default:
399 return false;
400 }
401 addr_t sp_offset = addr_byte_size * BitCount (registers);
402 addr_t addr = sp;
403 uint32_t i, data;
404
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000405 EmulateInstruction::Context context;
406 context.type = EmulateInstruction::eContextPopRegisterOffStack;
407 Register dwarf_reg;
408 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice8ce836d2011-03-16 22:46:55 +0000409 Register sp_reg;
410 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Johnny Chenef85e912011-01-31 23:07:40 +0000411 for (i=0; i<15; ++i)
412 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000413 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000414 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000415 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000416 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000417 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000418 if (!success)
419 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000420 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000421 return false;
422 addr += addr_byte_size;
423 }
424 }
425
Johnny Chen7c1bf922011-02-08 23:49:37 +0000426 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000428 dwarf_reg.num = dwarf_pc;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000429 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000430 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000431 if (!success)
432 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000433 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000434 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000435 return false;
436 addr += addr_byte_size;
437 }
438
439 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000440 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000441
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000442 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000443 return false;
444 }
445 return true;
446}
447
Johnny Chen5b442b72011-01-27 19:34:30 +0000448// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000449// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000450bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000451EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000452{
453#if 0
454 // ARM pseudo code...
455 if (ConditionPassed())
456 {
457 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000458 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenbcec3af2011-01-27 01:26:19 +0000459 if d == 15 then
460 ALUWritePC(result); // setflags is always FALSE here
461 else
462 R[d] = result;
463 if setflags then
464 APSR.N = result<31>;
465 APSR.Z = IsZeroBit(result);
466 APSR.C = carry;
467 APSR.V = overflow;
468 }
469#endif
470
471 bool success = false;
Johnny Chenbcec3af2011-01-27 01:26:19 +0000472
Greg Clayton7bc39082011-03-24 23:53:38 +0000473 if (ConditionPassed(opcode))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000474 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000475 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000476 if (!success)
477 return false;
478 uint32_t Rd; // the destination register
479 uint32_t imm32;
480 switch (encoding) {
481 case eEncodingT1:
482 Rd = 7;
483 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
484 break;
485 case eEncodingA1:
486 Rd = Bits32(opcode, 15, 12);
487 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
488 break;
489 default:
490 return false;
491 }
492 addr_t sp_offset = imm32;
493 addr_t addr = sp + sp_offset; // a pointer to the stack area
494
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000495 EmulateInstruction::Context context;
496 context.type = EmulateInstruction::eContextRegisterPlusOffset;
497 Register sp_reg;
498 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
499 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000500
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000501 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000502 return false;
503 }
504 return true;
505}
506
Johnny Chen2ccad832011-01-28 19:57:25 +0000507// Set r7 or ip to the current stack pointer.
508// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000509bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000510EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000511{
512#if 0
513 // ARM pseudo code...
514 if (ConditionPassed())
515 {
516 EncodingSpecificOperations();
517 result = R[m];
518 if d == 15 then
519 ALUWritePC(result); // setflags is always FALSE here
520 else
521 R[d] = result;
522 if setflags then
523 APSR.N = result<31>;
524 APSR.Z = IsZeroBit(result);
525 // APSR.C unchanged
526 // APSR.V unchanged
527 }
528#endif
529
530 bool success = false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000531
Greg Clayton7bc39082011-03-24 23:53:38 +0000532 if (ConditionPassed(opcode))
Johnny Chen2ccad832011-01-28 19:57:25 +0000533 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000534 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000535 if (!success)
536 return false;
537 uint32_t Rd; // the destination register
538 switch (encoding) {
539 case eEncodingT1:
540 Rd = 7;
541 break;
542 case eEncodingA1:
543 Rd = 12;
544 break;
545 default:
546 return false;
547 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000548
549 EmulateInstruction::Context context;
550 context.type = EmulateInstruction::eContextRegisterPlusOffset;
551 Register sp_reg;
552 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
553 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000554
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000555 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000556 return false;
557 }
558 return true;
559}
560
Johnny Chen1c13b622011-01-29 00:11:15 +0000561// Move from high register (r8-r15) to low register (r0-r7).
562// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000563bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000564EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000565{
Greg Clayton7bc39082011-03-24 23:53:38 +0000566 return EmulateMOVRdRm (opcode, encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000567}
568
569// Move from register to register.
570// MOV (register)
571bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000572EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000573{
Johnny Chen1c13b622011-01-29 00:11:15 +0000574#if 0
575 // ARM pseudo code...
576 if (ConditionPassed())
577 {
578 EncodingSpecificOperations();
579 result = R[m];
580 if d == 15 then
581 ALUWritePC(result); // setflags is always FALSE here
582 else
583 R[d] = result;
584 if setflags then
585 APSR.N = result<31>;
586 APSR.Z = IsZeroBit(result);
587 // APSR.C unchanged
588 // APSR.V unchanged
589 }
590#endif
591
592 bool success = false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000593
Greg Clayton7bc39082011-03-24 23:53:38 +0000594 if (ConditionPassed(opcode))
Johnny Chen1c13b622011-01-29 00:11:15 +0000595 {
596 uint32_t Rm; // the source register
597 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000598 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000599 switch (encoding) {
600 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000601 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000602 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000603 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000604 if (Rd == 15 && InITBlock() && !LastInITBlock())
605 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000606 break;
607 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000608 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000609 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000610 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000611 if (InITBlock())
612 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000613 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000614 case eEncodingT3:
615 Rd = Bits32(opcode, 11, 8);
616 Rm = Bits32(opcode, 3, 0);
617 setflags = BitIsSet(opcode, 20);
618 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
619 if (setflags && (BadReg(Rd) || BadReg(Rm)))
620 return false;
621 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
622 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
623 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000624 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000625 case eEncodingA1:
626 Rd = Bits32(opcode, 15, 12);
627 Rm = Bits32(opcode, 3, 0);
628 setflags = BitIsSet(opcode, 20);
629 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
630 // TODO: Emulate SUBS PC, LR and related instructions.
631 if (Rd == 15 && setflags)
632 return false;
633 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000634 default:
635 return false;
636 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000637 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000638 if (!success)
639 return false;
640
641 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000642 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000643 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000644 Register dwarf_reg;
645 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000646 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000647
Johnny Chen10530c22011-02-17 22:37:12 +0000648 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000649 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000650 }
651 return true;
652}
653
Johnny Chen357c30f2011-02-14 22:04:25 +0000654// Move (immediate) writes an immediate value to the destination register. It
655// can optionally update the condition flags based on the value.
656// MOV (immediate)
657bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000658EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000659{
660#if 0
661 // ARM pseudo code...
662 if (ConditionPassed())
663 {
664 EncodingSpecificOperations();
665 result = imm32;
666 if d == 15 then // Can only occur for ARM encoding
667 ALUWritePC(result); // setflags is always FALSE here
668 else
669 R[d] = result;
670 if setflags then
671 APSR.N = result<31>;
672 APSR.Z = IsZeroBit(result);
673 APSR.C = carry;
674 // APSR.V unchanged
675 }
676#endif
Johnny Chen357c30f2011-02-14 22:04:25 +0000677
Greg Clayton7bc39082011-03-24 23:53:38 +0000678 if (ConditionPassed(opcode))
Johnny Chen357c30f2011-02-14 22:04:25 +0000679 {
680 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000681 uint32_t imm32; // the immediate value to be written to Rd
682 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
683 bool setflags;
684 switch (encoding) {
Caroline Tice89c6d582011-03-29 19:53:44 +0000685 case eEncodingT1:
686 Rd = Bits32(opcode, 10, 8);
687 setflags = !InITBlock();
688 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
689 carry = APSR_C;
690
691 break;
692
693 case eEncodingT2:
694 Rd = Bits32(opcode, 11, 8);
695 setflags = BitIsSet(opcode, 20);
696 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
697 if (BadReg(Rd))
698 return false;
699
700 break;
701
702 case eEncodingT3:
703 {
704 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
705 Rd = Bits32 (opcode, 11, 8);
706 setflags = false;
707 uint32_t imm4 = Bits32 (opcode, 19, 16);
708 uint32_t imm3 = Bits32 (opcode, 14, 12);
709 uint32_t i = Bit32 (opcode, 26);
710 uint32_t imm8 = Bits32 (opcode, 7, 0);
711 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
712
713 // if BadReg(d) then UNPREDICTABLE;
714 if (BadReg (Rd))
715 return false;
716 }
717 break;
718
719 case eEncodingA1:
720 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
721 // d = UInt(Rd); setflags = (S == ‘1’); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
722 Rd = Bits32 (opcode, 15, 12);
723 setflags = BitIsSet (opcode, 20);
724 imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
725
726 break;
727
728 case eEncodingA2:
729 {
730 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
731 Rd = Bits32 (opcode, 15, 12);
732 setflags = false;
733 uint32_t imm4 = Bits32 (opcode, 19, 16);
734 uint32_t imm12 = Bits32 (opcode, 11, 0);
735 imm32 = (imm4 << 12) | imm12;
736
737 // if d == 15 then UNPREDICTABLE;
738 if (Rd == 15)
739 return false;
740 }
741 break;
742
743 default:
Johnny Chen9798cfc2011-02-14 23:33:58 +0000744 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000745 }
746 uint32_t result = imm32;
747
748 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000749 EmulateInstruction::Context context;
750 context.type = EmulateInstruction::eContextImmediate;
751 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000752
Johnny Chen10530c22011-02-17 22:37:12 +0000753 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000754 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000755 }
756 return true;
757}
758
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000759// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
760// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
761// unsigned values.
762//
763// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
764// limited to only a few forms of the instruction.
765bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000766EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000767{
768#if 0
769 if ConditionPassed() then
770 EncodingSpecificOperations();
771 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
772 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
773 result = operand1 * operand2;
774 R[d] = result<31:0>;
775 if setflags then
776 APSR.N = result<31>;
777 APSR.Z = IsZeroBit(result);
778 if ArchVersion() == 4 then
779 APSR.C = bit UNKNOWN;
780 // else APSR.C unchanged
781 // APSR.V always unchanged
782#endif
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000783
Greg Clayton7bc39082011-03-24 23:53:38 +0000784 if (ConditionPassed(opcode))
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000785 {
786 uint32_t d;
787 uint32_t n;
788 uint32_t m;
789 bool setflags;
790
791 // EncodingSpecificOperations();
792 switch (encoding)
793 {
794 case eEncodingT1:
795 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
796 d = Bits32 (opcode, 2, 0);
797 n = Bits32 (opcode, 5, 3);
798 m = Bits32 (opcode, 2, 0);
799 setflags = !InITBlock();
800
801 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
802 if ((ArchVersion() < ARMv6) && (d == n))
803 return false;
804
805 break;
806
807 case eEncodingT2:
808 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
809 d = Bits32 (opcode, 11, 8);
810 n = Bits32 (opcode, 19, 16);
811 m = Bits32 (opcode, 3, 0);
812 setflags = false;
813
814 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
815 if (BadReg (d) || BadReg (n) || BadReg (m))
816 return false;
817
818 break;
819
820 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +0000821 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000822 d = Bits32 (opcode, 19, 16);
823 n = Bits32 (opcode, 3, 0);
824 m = Bits32 (opcode, 11, 8);
825 setflags = BitIsSet (opcode, 20);
826
827 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
828 if ((d == 15) || (n == 15) || (m == 15))
829 return false;
830
831 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
832 if ((ArchVersion() < ARMv6) && (d == n))
833 return false;
834
835 break;
836
837 default:
838 return false;
839 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000840
841 bool success = false;
842
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000843 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
844 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
845 if (!success)
846 return false;
847
848 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
849 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
850 if (!success)
851 return false;
852
853 // result = operand1 * operand2;
854 uint64_t result = operand1 * operand2;
855
856 // R[d] = result<31:0>;
857 Register op1_reg;
858 Register op2_reg;
859 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
860 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
861
862 EmulateInstruction::Context context;
863 context.type = eContextMultiplication;
864 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
865
866 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
867 return false;
868
869 // if setflags then
870 if (setflags)
871 {
872 // APSR.N = result<31>;
873 // APSR.Z = IsZeroBit(result);
Greg Claytonb3448432011-03-24 21:19:54 +0000874 m_new_inst_cpsr = m_opcode_cpsr;
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000875 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
876 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Greg Claytonb3448432011-03-24 21:19:54 +0000877 if (m_new_inst_cpsr != m_opcode_cpsr)
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000878 {
879 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
880 return false;
881 }
882
883 // if ArchVersion() == 4 then
884 // APSR.C = bit UNKNOWN;
885 }
886 }
887 return true;
888}
889
Johnny Chend642a6a2011-02-22 01:01:03 +0000890// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
891// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000892bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000893EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000894{
895#if 0
896 // ARM pseudo code...
897 if (ConditionPassed())
898 {
899 EncodingSpecificOperations();
900 result = NOT(imm32);
901 if d == 15 then // Can only occur for ARM encoding
902 ALUWritePC(result); // setflags is always FALSE here
903 else
904 R[d] = result;
905 if setflags then
906 APSR.N = result<31>;
907 APSR.Z = IsZeroBit(result);
908 APSR.C = carry;
909 // APSR.V unchanged
910 }
911#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000912
Greg Clayton7bc39082011-03-24 23:53:38 +0000913 if (ConditionPassed(opcode))
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000914 {
915 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000916 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
917 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000918 bool setflags;
919 switch (encoding) {
920 case eEncodingT1:
921 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000922 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000923 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000924 break;
925 case eEncodingA1:
926 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000927 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000928 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
929 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
930 // TODO: Emulate SUBS PC, LR and related instructions.
931 if (Rd == 15 && setflags)
932 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000933 break;
934 default:
935 return false;
936 }
937 uint32_t result = ~imm32;
938
939 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000940 EmulateInstruction::Context context;
941 context.type = EmulateInstruction::eContextImmediate;
942 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000943
Johnny Chen10530c22011-02-17 22:37:12 +0000944 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000945 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000946 }
947 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000948}
949
Johnny Chend642a6a2011-02-22 01:01:03 +0000950// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
951// It can optionally update the condition flags based on the result.
952bool
Greg Clayton7bc39082011-03-24 23:53:38 +0000953EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend642a6a2011-02-22 01:01:03 +0000954{
955#if 0
956 // ARM pseudo code...
957 if (ConditionPassed())
958 {
959 EncodingSpecificOperations();
960 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
961 result = NOT(shifted);
962 if d == 15 then // Can only occur for ARM encoding
963 ALUWritePC(result); // setflags is always FALSE here
964 else
965 R[d] = result;
966 if setflags then
967 APSR.N = result<31>;
968 APSR.Z = IsZeroBit(result);
969 APSR.C = carry;
970 // APSR.V unchanged
971 }
972#endif
973
Greg Clayton7bc39082011-03-24 23:53:38 +0000974 if (ConditionPassed(opcode))
Johnny Chend642a6a2011-02-22 01:01:03 +0000975 {
976 uint32_t Rm; // the source register
977 uint32_t Rd; // the destination register
978 ARM_ShifterType shift_t;
979 uint32_t shift_n; // the shift applied to the value read from Rm
980 bool setflags;
981 uint32_t carry; // the carry bit after the shift operation
982 switch (encoding) {
983 case eEncodingT1:
984 Rd = Bits32(opcode, 2, 0);
985 Rm = Bits32(opcode, 5, 3);
986 setflags = !InITBlock();
987 shift_t = SRType_LSL;
988 shift_n = 0;
989 if (InITBlock())
990 return false;
991 break;
992 case eEncodingT2:
993 Rd = Bits32(opcode, 11, 8);
994 Rm = Bits32(opcode, 3, 0);
995 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000996 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000997 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000998 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000999 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00001000 break;
Johnny Chend642a6a2011-02-22 01:01:03 +00001001 case eEncodingA1:
1002 Rd = Bits32(opcode, 15, 12);
1003 Rm = Bits32(opcode, 3, 0);
1004 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00001005 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +00001006 break;
1007 default:
1008 return false;
1009 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001010 bool success = false;
Johnny Chend642a6a2011-02-22 01:01:03 +00001011 uint32_t value = ReadCoreReg(Rm, &success);
1012 if (!success)
1013 return false;
1014
1015 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1016 uint32_t result = ~shifted;
1017
1018 // The context specifies that an immediate is to be moved into Rd.
1019 EmulateInstruction::Context context;
1020 context.type = EmulateInstruction::eContextImmediate;
1021 context.SetNoArgs ();
1022
1023 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1024 return false;
1025 }
1026 return true;
1027}
1028
Johnny Chen788e0552011-01-27 22:52:23 +00001029// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1030// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001031bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001032EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001033{
1034#if 0
1035 // ARM pseudo code...
1036 if (ConditionPassed())
1037 {
1038 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1039 base = Align(PC,4);
1040 address = if add then (base + imm32) else (base - imm32);
1041 data = MemU[address,4];
1042 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001043 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1044 elsif UnalignedSupport() || address<1:0> = '00' then
Johnny Chen788e0552011-01-27 22:52:23 +00001045 R[t] = data;
1046 else // Can only apply before ARMv7
1047 if CurrentInstrSet() == InstrSet_ARM then
1048 R[t] = ROR(data, 8*UInt(address<1:0>));
1049 else
1050 R[t] = bits(32) UNKNOWN;
1051 }
1052#endif
1053
Greg Clayton7bc39082011-03-24 23:53:38 +00001054 if (ConditionPassed(opcode))
Johnny Chen788e0552011-01-27 22:52:23 +00001055 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001056 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001057 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001058 if (!success)
1059 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001060
1061 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001062 EmulateInstruction::Context context;
1063 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1064 Register pc_reg;
1065 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1066 context.SetRegisterPlusOffset (pc_reg, 0);
1067
Johnny Chenc9de9102011-02-11 19:12:30 +00001068 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001069 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001070 bool add; // +imm32 or -imm32?
1071 addr_t base; // the base address
1072 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001073 uint32_t data; // the literal data value from the PC relative load
1074 switch (encoding) {
1075 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001076 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001077 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001078 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001079 break;
1080 case eEncodingT2:
1081 Rt = Bits32(opcode, 15, 12);
1082 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1083 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001084 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001085 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001086 break;
1087 default:
1088 return false;
1089 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001090
Johnny Chene39f22d2011-02-19 01:36:13 +00001091 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001092 if (add)
1093 address = base + imm32;
1094 else
1095 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001096
1097 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001098 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001099 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001100 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001101
1102 if (Rt == 15)
1103 {
1104 if (Bits32(address, 1, 0) == 0)
1105 {
1106 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001107 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001108 return false;
1109 }
1110 else
1111 return false;
1112 }
1113 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1114 {
1115 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1116 return false;
1117 }
1118 else // We don't handle ARM for now.
1119 return false;
1120
Johnny Chen788e0552011-01-27 22:52:23 +00001121 }
1122 return true;
1123}
1124
Johnny Chen5b442b72011-01-27 19:34:30 +00001125// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001126// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001127bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001128EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001129{
1130#if 0
1131 // ARM pseudo code...
1132 if (ConditionPassed())
1133 {
1134 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001135 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
Johnny Chenfdd179e2011-01-31 20:09:28 +00001136 if d == 15 then // Can only occur for ARM encoding
1137 ALUWritePC(result); // setflags is always FALSE here
1138 else
1139 R[d] = result;
1140 if setflags then
1141 APSR.N = result<31>;
1142 APSR.Z = IsZeroBit(result);
1143 APSR.C = carry;
1144 APSR.V = overflow;
1145 }
1146#endif
1147
1148 bool success = false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001149
Greg Clayton7bc39082011-03-24 23:53:38 +00001150 if (ConditionPassed(opcode))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001151 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001152 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001153 if (!success)
1154 return false;
1155 uint32_t imm32; // the immediate operand
Caroline Ticee2212882011-03-22 22:38:28 +00001156 uint32_t d;
1157 bool setflags;
1158 switch (encoding)
1159 {
1160 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001161 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001162 d = Bits32 (opcode, 10, 8);
1163 setflags = false;
1164 imm32 = (Bits32 (opcode, 7, 0) << 2);
1165
1166 break;
1167
1168 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001169 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
Caroline Ticee2212882011-03-22 22:38:28 +00001170 d = 13;
1171 setflags = false;
1172 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1173
1174 break;
1175
1176 default:
1177 return false;
Johnny Chenfdd179e2011-01-31 20:09:28 +00001178 }
1179 addr_t sp_offset = imm32;
1180 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1181
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001182 EmulateInstruction::Context context;
1183 context.type = EmulateInstruction::eContextAdjustStackPointer;
1184 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001185
Caroline Ticee2212882011-03-22 22:38:28 +00001186 if (d == 15)
1187 {
1188 if (!ALUWritePC (context, addr))
1189 return false;
1190 }
1191 else
1192 {
1193 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
1194 return false;
1195 }
Johnny Chenfdd179e2011-01-31 20:09:28 +00001196 }
1197 return true;
1198}
1199
1200// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001201// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001202bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001203EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001204{
1205#if 0
1206 // ARM pseudo code...
1207 if (ConditionPassed())
1208 {
1209 EncodingSpecificOperations();
1210 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001211 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
Johnny Chen5b442b72011-01-27 19:34:30 +00001212 if d == 15 then
1213 ALUWritePC(result); // setflags is always FALSE here
1214 else
1215 R[d] = result;
1216 if setflags then
1217 APSR.N = result<31>;
1218 APSR.Z = IsZeroBit(result);
1219 APSR.C = carry;
1220 APSR.V = overflow;
1221 }
1222#endif
1223
1224 bool success = false;
Johnny Chen5b442b72011-01-27 19:34:30 +00001225
Greg Clayton7bc39082011-03-24 23:53:38 +00001226 if (ConditionPassed(opcode))
Johnny Chen5b442b72011-01-27 19:34:30 +00001227 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001228 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001229 if (!success)
1230 return false;
1231 uint32_t Rm; // the second operand
1232 switch (encoding) {
1233 case eEncodingT2:
1234 Rm = Bits32(opcode, 6, 3);
1235 break;
1236 default:
1237 return false;
1238 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001239 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001240 if (!success)
1241 return false;
1242
1243 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1244
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001245 EmulateInstruction::Context context;
1246 context.type = EmulateInstruction::eContextAdjustStackPointer;
1247 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001248
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001249 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001250 return false;
1251 }
1252 return true;
1253}
1254
Johnny Chen9b8d7832011-02-02 01:13:56 +00001255// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1256// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1257// from Thumb to ARM.
1258// BLX (immediate)
1259bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001260EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001261{
1262#if 0
1263 // ARM pseudo code...
1264 if (ConditionPassed())
1265 {
1266 EncodingSpecificOperations();
1267 if CurrentInstrSet() == InstrSet_ARM then
1268 LR = PC - 4;
1269 else
1270 LR = PC<31:1> : '1';
1271 if targetInstrSet == InstrSet_ARM then
1272 targetAddress = Align(PC,4) + imm32;
1273 else
1274 targetAddress = PC + imm32;
1275 SelectInstrSet(targetInstrSet);
1276 BranchWritePC(targetAddress);
1277 }
1278#endif
1279
Greg Clayton7bc39082011-03-24 23:53:38 +00001280 bool success = true;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001281
Greg Clayton7bc39082011-03-24 23:53:38 +00001282 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001283 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001284 EmulateInstruction::Context context;
1285 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001286 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001287 if (!success)
1288 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001289 addr_t lr; // next instruction address
1290 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001291 int32_t imm32; // PC-relative offset
1292 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001293 case eEncodingT1:
1294 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001295 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001296 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001297 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001298 uint32_t J1 = Bit32(opcode, 13);
1299 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001300 uint32_t imm11 = Bits32(opcode, 10, 0);
1301 uint32_t I1 = !(J1 ^ S);
1302 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001303 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001304 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001305 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001306 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001307 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001308 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001309 break;
1310 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001311 case eEncodingT2:
1312 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001313 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001314 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001315 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001316 uint32_t J1 = Bit32(opcode, 13);
1317 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001318 uint32_t imm10L = Bits32(opcode, 10, 1);
1319 uint32_t I1 = !(J1 ^ S);
1320 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001321 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001322 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001323 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001324 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001325 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001326 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001327 break;
1328 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001329 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001330 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001331 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001332 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001333 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001334 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001335 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001336 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001337 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001338 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001339 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001340 break;
1341 default:
1342 return false;
1343 }
1344 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1345 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001346 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001347 return false;
1348 }
1349 return true;
1350}
1351
1352// Branch with Link and Exchange (register) calls a subroutine at an address and
1353// instruction set specified by a register.
1354// BLX (register)
1355bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001356EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b8d7832011-02-02 01:13:56 +00001357{
1358#if 0
1359 // ARM pseudo code...
1360 if (ConditionPassed())
1361 {
1362 EncodingSpecificOperations();
1363 target = R[m];
1364 if CurrentInstrSet() == InstrSet_ARM then
1365 next_instr_addr = PC - 4;
1366 LR = next_instr_addr;
1367 else
1368 next_instr_addr = PC - 2;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001369 LR = next_instr_addr<31:1> : '1';
Johnny Chen9b8d7832011-02-02 01:13:56 +00001370 BXWritePC(target);
1371 }
1372#endif
1373
1374 bool success = false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001375
Greg Clayton7bc39082011-03-24 23:53:38 +00001376 if (ConditionPassed(opcode))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001377 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001378 EmulateInstruction::Context context;
1379 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001380 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001381 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001382 if (!success)
1383 return false;
1384 uint32_t Rm; // the register with the target address
1385 switch (encoding) {
1386 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001387 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001388 Rm = Bits32(opcode, 6, 3);
1389 // if m == 15 then UNPREDICTABLE;
1390 if (Rm == 15)
1391 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001392 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001393 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001394 break;
1395 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001396 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001397 Rm = Bits32(opcode, 3, 0);
1398 // if m == 15 then UNPREDICTABLE;
1399 if (Rm == 15)
1400 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001401 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001402 default:
1403 return false;
1404 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001405 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001406 if (!success)
1407 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001408 Register dwarf_reg;
1409 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1410 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001411 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1412 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001413 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001414 return false;
1415 }
1416 return true;
1417}
1418
Johnny Chenab3b3512011-02-12 00:10:51 +00001419// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001420bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001421EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenab3b3512011-02-12 00:10:51 +00001422{
1423#if 0
1424 // ARM pseudo code...
1425 if (ConditionPassed())
1426 {
1427 EncodingSpecificOperations();
1428 BXWritePC(R[m]);
1429 }
1430#endif
1431
Greg Clayton7bc39082011-03-24 23:53:38 +00001432 if (ConditionPassed(opcode))
Johnny Chenab3b3512011-02-12 00:10:51 +00001433 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001434 EmulateInstruction::Context context;
1435 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001436 uint32_t Rm; // the register with the target address
1437 switch (encoding) {
1438 case eEncodingT1:
1439 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001440 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001441 return false;
1442 break;
1443 case eEncodingA1:
1444 Rm = Bits32(opcode, 3, 0);
1445 break;
1446 default:
1447 return false;
1448 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001449 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001450 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001451 if (!success)
1452 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001453
1454 Register dwarf_reg;
1455 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001456 context.SetRegister (dwarf_reg);
1457 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001458 return false;
1459 }
1460 return true;
1461}
1462
Johnny Chen59e6ab72011-02-24 21:01:20 +00001463// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1464// address and instruction set specified by a register as though it were a BX instruction.
1465//
1466// TODO: Emulate Jazelle architecture?
1467// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1468bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001469EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen59e6ab72011-02-24 21:01:20 +00001470{
1471#if 0
1472 // ARM pseudo code...
1473 if (ConditionPassed())
1474 {
1475 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001476 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
Johnny Chen59e6ab72011-02-24 21:01:20 +00001477 BXWritePC(R[m]);
1478 else
1479 if JazelleAcceptsExecution() then
1480 SwitchToJazelleExecution();
1481 else
1482 SUBARCHITECTURE_DEFINED handler call;
1483 }
1484#endif
1485
Greg Clayton7bc39082011-03-24 23:53:38 +00001486 if (ConditionPassed(opcode))
Johnny Chen59e6ab72011-02-24 21:01:20 +00001487 {
1488 EmulateInstruction::Context context;
1489 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1490 uint32_t Rm; // the register with the target address
1491 switch (encoding) {
1492 case eEncodingT1:
1493 Rm = Bits32(opcode, 19, 16);
1494 if (BadReg(Rm))
1495 return false;
1496 if (InITBlock() && !LastInITBlock())
1497 return false;
1498 break;
1499 case eEncodingA1:
1500 Rm = Bits32(opcode, 3, 0);
1501 if (Rm == 15)
1502 return false;
1503 break;
1504 default:
1505 return false;
1506 }
Greg Clayton7bc39082011-03-24 23:53:38 +00001507 bool success = false;
Johnny Chen59e6ab72011-02-24 21:01:20 +00001508 addr_t target = ReadCoreReg (Rm, &success);
1509 if (!success)
1510 return false;
1511
1512 Register dwarf_reg;
1513 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1514 context.SetRegister (dwarf_reg);
1515 if (!BXWritePC(context, target))
1516 return false;
1517 }
1518 return true;
1519}
1520
Johnny Chen0d0148e2011-01-28 02:26:08 +00001521// Set r7 to point to some ip offset.
1522// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001523bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001524EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001525{
1526#if 0
1527 // ARM pseudo code...
1528 if (ConditionPassed())
1529 {
1530 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001531 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001532 if d == 15 then // Can only occur for ARM encoding
1533 ALUWritePC(result); // setflags is always FALSE here
1534 else
1535 R[d] = result;
1536 if setflags then
1537 APSR.N = result<31>;
1538 APSR.Z = IsZeroBit(result);
1539 APSR.C = carry;
1540 APSR.V = overflow;
1541 }
1542#endif
1543
Greg Clayton7bc39082011-03-24 23:53:38 +00001544 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001545 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001546 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001547 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001548 if (!success)
1549 return false;
1550 uint32_t imm32;
1551 switch (encoding) {
1552 case eEncodingA1:
1553 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1554 break;
1555 default:
1556 return false;
1557 }
1558 addr_t ip_offset = imm32;
1559 addr_t addr = ip - ip_offset; // the adjusted ip value
1560
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001561 EmulateInstruction::Context context;
1562 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1563 Register dwarf_reg;
1564 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1565 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001566
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001567 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001568 return false;
1569 }
1570 return true;
1571}
1572
1573// Set ip to point to some stack offset.
1574// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001575bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001576EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001577{
1578#if 0
1579 // ARM pseudo code...
1580 if (ConditionPassed())
1581 {
1582 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001583 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen0d0148e2011-01-28 02:26:08 +00001584 if d == 15 then // Can only occur for ARM encoding
1585 ALUWritePC(result); // setflags is always FALSE here
1586 else
1587 R[d] = result;
1588 if setflags then
1589 APSR.N = result<31>;
1590 APSR.Z = IsZeroBit(result);
1591 APSR.C = carry;
1592 APSR.V = overflow;
1593 }
1594#endif
1595
Greg Clayton7bc39082011-03-24 23:53:38 +00001596 if (ConditionPassed(opcode))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001597 {
Greg Clayton7bc39082011-03-24 23:53:38 +00001598 bool success = false;
Johnny Chene39f22d2011-02-19 01:36:13 +00001599 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001600 if (!success)
1601 return false;
1602 uint32_t imm32;
1603 switch (encoding) {
1604 case eEncodingA1:
1605 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1606 break;
1607 default:
1608 return false;
1609 }
1610 addr_t sp_offset = imm32;
1611 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1612
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001613 EmulateInstruction::Context context;
1614 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1615 Register dwarf_reg;
1616 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1617 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001618
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001619 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001620 return false;
1621 }
1622 return true;
1623}
1624
Johnny Chenc9e747f2011-02-23 01:55:07 +00001625// This instruction subtracts an immediate value from the SP value, and writes
1626// the result to the destination register.
1627//
1628// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001629bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001630EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001631{
1632#if 0
1633 // ARM pseudo code...
1634 if (ConditionPassed())
1635 {
1636 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001637 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001638 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001639 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001640 else
1641 R[d] = result;
1642 if setflags then
1643 APSR.N = result<31>;
1644 APSR.Z = IsZeroBit(result);
1645 APSR.C = carry;
1646 APSR.V = overflow;
1647 }
1648#endif
1649
1650 bool success = false;
Greg Clayton7bc39082011-03-24 23:53:38 +00001651 if (ConditionPassed(opcode))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001652 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001653 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001654 if (!success)
1655 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001656
1657 uint32_t Rd;
1658 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001659 uint32_t imm32;
1660 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001661 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001662 Rd = 13;
1663 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001664 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001665 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001666 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001667 Rd = Bits32(opcode, 11, 8);
1668 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001669 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001670 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00001671 return EmulateCMPImm(opcode, eEncodingT2);
Johnny Chenc9e747f2011-02-23 01:55:07 +00001672 if (Rd == 15 && !setflags)
1673 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001674 break;
1675 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001676 Rd = Bits32(opcode, 11, 8);
1677 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001678 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001679 if (Rd == 15)
1680 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001681 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001682 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001683 Rd = Bits32(opcode, 15, 12);
1684 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001685 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001686 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1687 // TODO: Emulate SUBS PC, LR and related instructions.
1688 if (Rd == 15 && setflags)
1689 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001690 break;
1691 default:
1692 return false;
1693 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001694 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1695
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001696 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001697 if (Rd == 13)
1698 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001699 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1700 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001701 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001702 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001703 }
1704 else
1705 {
1706 context.type = EmulateInstruction::eContextImmediate;
1707 context.SetNoArgs ();
1708 }
1709
1710 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001711 return false;
1712 }
1713 return true;
1714}
1715
Johnny Chen08c25e82011-01-31 18:02:28 +00001716// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001717bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001718EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001719{
1720#if 0
1721 // ARM pseudo code...
1722 if (ConditionPassed())
1723 {
1724 EncodingSpecificOperations();
1725 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1726 address = if index then offset_addr else R[n];
1727 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1728 if wback then R[n] = offset_addr;
1729 }
1730#endif
1731
1732 bool success = false;
Johnny Chence1ca772011-01-25 01:13:00 +00001733
Greg Clayton7bc39082011-03-24 23:53:38 +00001734 if (ConditionPassed(opcode))
Johnny Chence1ca772011-01-25 01:13:00 +00001735 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001736 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001737 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001738 if (!success)
1739 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001740 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001741 uint32_t imm12;
Caroline Tice3e407972011-03-18 19:41:00 +00001742 uint32_t Rn; // This function assumes Rn is the SP, but we should verify that.
1743
1744 bool index;
1745 bool add;
1746 bool wback;
Johnny Chence1ca772011-01-25 01:13:00 +00001747 switch (encoding) {
1748 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001749 Rt = Bits32(opcode, 15, 12);
1750 imm12 = Bits32(opcode, 11, 0);
Caroline Tice3e407972011-03-18 19:41:00 +00001751 Rn = Bits32 (opcode, 19, 16);
1752
1753 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
1754 return false;
1755
1756 index = BitIsSet (opcode, 24);
1757 add = BitIsSet (opcode, 23);
1758 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
1759
1760 if (wback && ((Rn == 15) || (Rn == Rt)))
1761 return false;
Johnny Chence1ca772011-01-25 01:13:00 +00001762 break;
1763 default:
1764 return false;
1765 }
Caroline Tice3e407972011-03-18 19:41:00 +00001766 addr_t offset_addr;
1767 if (add)
1768 offset_addr = sp + imm12;
1769 else
1770 offset_addr = sp - imm12;
1771
1772 addr_t addr;
1773 if (index)
1774 addr = offset_addr;
1775 else
1776 addr = sp;
Johnny Chence1ca772011-01-25 01:13:00 +00001777
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001778 EmulateInstruction::Context context;
1779 context.type = EmulateInstruction::eContextPushRegisterOnStack;
Caroline Tice3e407972011-03-18 19:41:00 +00001780 Register sp_reg;
1781 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1782 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Johnny Chen91d99862011-01-25 19:07:04 +00001783 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001784 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001785 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001786 if (!success)
1787 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001788 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001789 return false;
1790 }
1791 else
1792 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001793 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001794 if (!success)
1795 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001796 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001797 return false;
1798 }
1799
Caroline Tice3e407972011-03-18 19:41:00 +00001800
1801 if (wback)
1802 {
1803 context.type = EmulateInstruction::eContextAdjustStackPointer;
1804 context.SetImmediateSigned (addr - sp);
1805 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
1806 return false;
1807 }
Johnny Chence1ca772011-01-25 01:13:00 +00001808 }
1809 return true;
1810}
1811
Johnny Chen08c25e82011-01-31 18:02:28 +00001812// Vector Push stores multiple extension registers to the stack.
1813// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001814bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001815EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001816{
1817#if 0
1818 // ARM pseudo code...
1819 if (ConditionPassed())
1820 {
1821 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1822 address = SP - imm32;
1823 SP = SP - imm32;
1824 if single_regs then
1825 for r = 0 to regs-1
1826 MemA[address,4] = S[d+r]; address = address+4;
1827 else
1828 for r = 0 to regs-1
1829 // Store as two word-aligned words in the correct order for current endianness.
1830 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1831 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1832 address = address+8;
1833 }
1834#endif
1835
1836 bool success = false;
Johnny Chen799dfd02011-01-26 23:14:33 +00001837
Greg Clayton7bc39082011-03-24 23:53:38 +00001838 if (ConditionPassed(opcode))
Johnny Chen799dfd02011-01-26 23:14:33 +00001839 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001840 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001841 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001842 if (!success)
1843 return false;
1844 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001845 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001846 uint32_t imm32; // stack offset
1847 uint32_t regs; // number of registers
1848 switch (encoding) {
1849 case eEncodingT1:
1850 case eEncodingA1:
1851 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001852 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001853 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1854 // If UInt(imm8) is odd, see "FSTMX".
1855 regs = Bits32(opcode, 7, 0) / 2;
1856 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1857 if (regs == 0 || regs > 16 || (d + regs) > 32)
1858 return false;
1859 break;
1860 case eEncodingT2:
1861 case eEncodingA2:
1862 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001863 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001864 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1865 regs = Bits32(opcode, 7, 0);
1866 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1867 if (regs == 0 || regs > 16 || (d + regs) > 32)
1868 return false;
1869 break;
1870 default:
1871 return false;
1872 }
1873 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1874 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1875 addr_t sp_offset = imm32;
1876 addr_t addr = sp - sp_offset;
1877 uint32_t i;
1878
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001879 EmulateInstruction::Context context;
1880 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1881 Register dwarf_reg;
1882 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001883 Register sp_reg;
1884 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1885 for (i=0; i<regs; ++i)
Johnny Chen799dfd02011-01-26 23:14:33 +00001886 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001887 dwarf_reg.num = start_reg + d + i;
1888 context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001889 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001890 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001891 if (!success)
1892 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001893 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001894 return false;
1895 addr += reg_byte_size;
1896 }
1897
1898 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001899 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001900
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001901 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001902 return false;
1903 }
1904 return true;
1905}
1906
Johnny Chen587a0a42011-02-01 18:35:28 +00001907// Vector Pop loads multiple extension registers from the stack.
1908// It also updates SP to point just above the loaded data.
1909bool
Greg Clayton7bc39082011-03-24 23:53:38 +00001910EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen587a0a42011-02-01 18:35:28 +00001911{
1912#if 0
1913 // ARM pseudo code...
1914 if (ConditionPassed())
1915 {
1916 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1917 address = SP;
1918 SP = SP + imm32;
1919 if single_regs then
1920 for r = 0 to regs-1
1921 S[d+r] = MemA[address,4]; address = address+4;
1922 else
1923 for r = 0 to regs-1
1924 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1925 // Combine the word-aligned words in the correct order for current endianness.
1926 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1927 }
1928#endif
1929
1930 bool success = false;
Johnny Chen587a0a42011-02-01 18:35:28 +00001931
Greg Clayton7bc39082011-03-24 23:53:38 +00001932 if (ConditionPassed(opcode))
Johnny Chen587a0a42011-02-01 18:35:28 +00001933 {
1934 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001935 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001936 if (!success)
1937 return false;
1938 bool single_regs;
1939 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1940 uint32_t imm32; // stack offset
1941 uint32_t regs; // number of registers
1942 switch (encoding) {
1943 case eEncodingT1:
1944 case eEncodingA1:
1945 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001946 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001947 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1948 // If UInt(imm8) is odd, see "FLDMX".
1949 regs = Bits32(opcode, 7, 0) / 2;
1950 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1951 if (regs == 0 || regs > 16 || (d + regs) > 32)
1952 return false;
1953 break;
1954 case eEncodingT2:
1955 case eEncodingA2:
1956 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001957 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001958 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1959 regs = Bits32(opcode, 7, 0);
1960 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1961 if (regs == 0 || regs > 16 || (d + regs) > 32)
1962 return false;
1963 break;
1964 default:
1965 return false;
1966 }
1967 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1968 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1969 addr_t sp_offset = imm32;
1970 addr_t addr = sp;
1971 uint32_t i;
1972 uint64_t data; // uint64_t to accomodate 64-bit registers.
1973
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001974 EmulateInstruction::Context context;
1975 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1976 Register dwarf_reg;
1977 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001978 Register sp_reg;
1979 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
1980 for (i=0; i<regs; ++i)
Johnny Chen587a0a42011-02-01 18:35:28 +00001981 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00001982 dwarf_reg.num = start_reg + d + i;
1983 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001984 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001985 if (!success)
1986 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001987 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001988 return false;
1989 addr += reg_byte_size;
1990 }
1991
1992 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001993 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001994
1995 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1996 return false;
1997 }
1998 return true;
1999}
2000
Johnny Chenb77be412011-02-04 00:40:18 +00002001// SVC (previously SWI)
2002bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002003EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb77be412011-02-04 00:40:18 +00002004{
2005#if 0
2006 // ARM pseudo code...
2007 if (ConditionPassed())
2008 {
2009 EncodingSpecificOperations();
2010 CallSupervisor();
2011 }
2012#endif
2013
2014 bool success = false;
Johnny Chenb77be412011-02-04 00:40:18 +00002015
Greg Clayton7bc39082011-03-24 23:53:38 +00002016 if (ConditionPassed(opcode))
Johnny Chenb77be412011-02-04 00:40:18 +00002017 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002018 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002019 addr_t lr; // next instruction address
2020 if (!success)
2021 return false;
2022 uint32_t imm32; // the immediate constant
2023 uint32_t mode; // ARM or Thumb mode
2024 switch (encoding) {
2025 case eEncodingT1:
2026 lr = (pc + 2) | 1u; // return address
2027 imm32 = Bits32(opcode, 7, 0);
2028 mode = eModeThumb;
2029 break;
2030 case eEncodingA1:
2031 lr = pc + 4; // return address
2032 imm32 = Bits32(opcode, 23, 0);
2033 mode = eModeARM;
2034 break;
2035 default:
2036 return false;
2037 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002038
2039 EmulateInstruction::Context context;
2040 context.type = EmulateInstruction::eContextSupervisorCall;
2041 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002042 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2043 return false;
2044 }
2045 return true;
2046}
2047
Johnny Chenc315f862011-02-05 00:46:10 +00002048// If Then makes up to four following instructions (the IT block) conditional.
2049bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002050EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenc315f862011-02-05 00:46:10 +00002051{
2052#if 0
2053 // ARM pseudo code...
2054 EncodingSpecificOperations();
2055 ITSTATE.IT<7:0> = firstcond:mask;
2056#endif
2057
Johnny Chenc315f862011-02-05 00:46:10 +00002058 m_it_session.InitIT(Bits32(opcode, 7, 0));
2059 return true;
2060}
2061
Johnny Chen3b620b32011-02-07 20:11:47 +00002062// Branch causes a branch to a target address.
2063bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002064EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen3b620b32011-02-07 20:11:47 +00002065{
2066#if 0
2067 // ARM pseudo code...
2068 if (ConditionPassed())
2069 {
2070 EncodingSpecificOperations();
2071 BranchWritePC(PC + imm32);
2072 }
2073#endif
2074
2075 bool success = false;
Johnny Chen3b620b32011-02-07 20:11:47 +00002076
Greg Clayton7bc39082011-03-24 23:53:38 +00002077 if (ConditionPassed(opcode))
Johnny Chen9ee056b2011-02-08 00:06:35 +00002078 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002079 EmulateInstruction::Context context;
2080 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002081 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002082 if (!success)
2083 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002084 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002085 int32_t imm32; // PC-relative offset
2086 switch (encoding) {
2087 case eEncodingT1:
2088 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2089 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002090 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002091 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002092 break;
2093 case eEncodingT2:
2094 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002095 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002096 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002097 break;
2098 case eEncodingT3:
2099 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2100 {
Johnny Chenbd599902011-02-10 21:39:01 +00002101 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002102 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002103 uint32_t J1 = Bit32(opcode, 13);
2104 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002105 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002106 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002107 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002108 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002109 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002110 break;
2111 }
2112 case eEncodingT4:
2113 {
Johnny Chenbd599902011-02-10 21:39:01 +00002114 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002115 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002116 uint32_t J1 = Bit32(opcode, 13);
2117 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002118 uint32_t imm11 = Bits32(opcode, 10, 0);
2119 uint32_t I1 = !(J1 ^ S);
2120 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002121 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002122 imm32 = llvm::SignExtend32<25>(imm25);
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 eEncodingA1:
2128 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002129 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002130 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002131 break;
2132 default:
2133 return false;
2134 }
2135 if (!BranchWritePC(context, target))
2136 return false;
2137 }
2138 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002139}
2140
Johnny Chen53ebab72011-02-08 23:21:57 +00002141// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2142// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2143// CBNZ, CBZ
2144bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002145EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen53ebab72011-02-08 23:21:57 +00002146{
2147#if 0
2148 // ARM pseudo code...
2149 EncodingSpecificOperations();
2150 if nonzero ^ IsZero(R[n]) then
2151 BranchWritePC(PC + imm32);
2152#endif
2153
2154 bool success = false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002155
2156 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002157 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002158 if (!success)
2159 return false;
2160
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002161 EmulateInstruction::Context context;
2162 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002163 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002164 if (!success)
2165 return false;
2166
2167 addr_t target; // target address
2168 uint32_t imm32; // PC-relative offset to branch forward
2169 bool nonzero;
2170 switch (encoding) {
2171 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002172 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002173 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002174 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002175 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002176 break;
2177 default:
2178 return false;
2179 }
2180 if (nonzero ^ (reg_val == 0))
2181 if (!BranchWritePC(context, target))
2182 return false;
2183
2184 return true;
2185}
2186
Johnny Chen60299ec2011-02-17 19:34:27 +00002187// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2188// A base register provides a pointer to the table, and a second register supplies an index into the table.
2189// The branch length is twice the value of the byte returned from the table.
2190//
2191// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2192// A base register provides a pointer to the table, and a second register supplies an index into the table.
2193// The branch length is twice the value of the halfword returned from the table.
2194// TBB, TBH
2195bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002196EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen60299ec2011-02-17 19:34:27 +00002197{
2198#if 0
2199 // ARM pseudo code...
2200 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2201 if is_tbh then
2202 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2203 else
2204 halfwords = UInt(MemU[R[n]+R[m], 1]);
2205 BranchWritePC(PC + 2*halfwords);
2206#endif
2207
2208 bool success = false;
Johnny Chen60299ec2011-02-17 19:34:27 +00002209
2210 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2211 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2212 bool is_tbh; // true if table branch halfword
2213 switch (encoding) {
2214 case eEncodingT1:
2215 Rn = Bits32(opcode, 19, 16);
2216 Rm = Bits32(opcode, 3, 0);
2217 is_tbh = BitIsSet(opcode, 4);
2218 if (Rn == 13 || BadReg(Rm))
2219 return false;
2220 if (InITBlock() && !LastInITBlock())
2221 return false;
2222 break;
2223 default:
2224 return false;
2225 }
2226
2227 // Read the address of the table from the operand register Rn.
2228 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002229 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002230 if (!success)
2231 return false;
2232
2233 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002234 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002235 if (!success)
2236 return false;
2237
2238 // the offsetted table address
2239 addr_t addr = base + (is_tbh ? index*2 : index);
2240
2241 // PC-relative offset to branch forward
2242 EmulateInstruction::Context context;
2243 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002244 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002245 if (!success)
2246 return false;
2247
Johnny Chene39f22d2011-02-19 01:36:13 +00002248 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002249 if (!success)
2250 return false;
2251
2252 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002253 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002254 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2255 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2256
2257 if (!BranchWritePC(context, target))
2258 return false;
2259
2260 return true;
2261}
2262
Caroline Ticedcc11b32011-03-02 23:57:02 +00002263// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2264// It can optionally update the condition flags based on the result.
2265bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002266EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticedcc11b32011-03-02 23:57:02 +00002267{
2268#if 0
2269 if ConditionPassed() then
2270 EncodingSpecificOperations();
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002271 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002272 R[d] = result;
2273 if setflags then
2274 APSR.N = result<31>;
2275 APSR.Z = IsZeroBit(result);
2276 APSR.C = carry;
2277 APSR.V = overflow;
2278#endif
2279
2280 bool success = false;
Caroline Ticedcc11b32011-03-02 23:57:02 +00002281
Greg Clayton7bc39082011-03-24 23:53:38 +00002282 if (ConditionPassed(opcode))
Caroline Ticedcc11b32011-03-02 23:57:02 +00002283 {
2284 uint32_t d;
2285 uint32_t n;
2286 bool setflags;
2287 uint32_t imm32;
2288 uint32_t carry_out;
2289
2290 //EncodingSpecificOperations();
2291 switch (encoding)
2292 {
2293 case eEncodingT1:
2294 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2295 d = Bits32 (opcode, 2, 0);
2296 n = Bits32 (opcode, 5, 3);
2297 setflags = !InITBlock();
2298 imm32 = Bits32 (opcode, 8,6);
2299
2300 break;
2301
2302 case eEncodingT2:
2303 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2304 d = Bits32 (opcode, 10, 8);
2305 n = Bits32 (opcode, 10, 8);
2306 setflags = !InITBlock();
2307 imm32 = Bits32 (opcode, 7, 0);
2308
2309 break;
2310
2311 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002312 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
2313 // if Rn == '1101' then SEE ADD (SP plus immediate);
2314 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002315 d = Bits32 (opcode, 11, 8);
2316 n = Bits32 (opcode, 19, 16);
2317 setflags = BitIsSet (opcode, 20);
2318 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2319
2320 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2321 if (BadReg (d) || (n == 15))
2322 return false;
2323
2324 break;
2325
2326 case eEncodingT4:
2327 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002328 // if Rn == '1111' then SEE ADR;
2329 // if Rn == '1101' then SEE ADD (SP plus immediate);
Caroline Ticedcc11b32011-03-02 23:57:02 +00002330 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2331 d = Bits32 (opcode, 11, 8);
2332 n = Bits32 (opcode, 19, 16);
2333 setflags = false;
2334 uint32_t i = Bit32 (opcode, 26);
2335 uint32_t imm3 = Bits32 (opcode, 14, 12);
2336 uint32_t imm8 = Bits32 (opcode, 7, 0);
2337 imm32 = (i << 11) | (imm3 << 8) | imm8;
2338
2339 // if BadReg(d) then UNPREDICTABLE;
2340 if (BadReg (d))
2341 return false;
2342
2343 break;
2344 }
2345 default:
2346 return false;
2347 }
2348
2349 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2350 if (!success)
2351 return false;
2352
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002353 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
Caroline Ticedcc11b32011-03-02 23:57:02 +00002354 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2355
2356 Register reg_n;
2357 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2358
2359 EmulateInstruction::Context context;
2360 context.type = eContextAddition;
2361 context.SetRegisterPlusOffset (reg_n, imm32);
2362
2363 //R[d] = result;
2364 //if setflags then
2365 //APSR.N = result<31>;
2366 //APSR.Z = IsZeroBit(result);
2367 //APSR.C = carry;
2368 //APSR.V = overflow;
2369 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2370 return false;
2371
2372 }
2373 return true;
2374}
2375
Johnny Chen8fa20592011-02-18 01:22:22 +00002376// This instruction adds an immediate value to a register value, and writes the result to the destination
2377// register. It can optionally update the condition flags based on the result.
2378bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002379EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen8fa20592011-02-18 01:22:22 +00002380{
2381#if 0
2382 // ARM pseudo code...
2383 if ConditionPassed() then
2384 EncodingSpecificOperations();
2385 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2386 if d == 15 then
2387 ALUWritePC(result); // setflags is always FALSE here
2388 else
2389 R[d] = result;
2390 if setflags then
2391 APSR.N = result<31>;
2392 APSR.Z = IsZeroBit(result);
2393 APSR.C = carry;
2394 APSR.V = overflow;
2395#endif
2396
2397 bool success = false;
Johnny Chen8fa20592011-02-18 01:22:22 +00002398
Greg Clayton7bc39082011-03-24 23:53:38 +00002399 if (ConditionPassed(opcode))
Johnny Chen8fa20592011-02-18 01:22:22 +00002400 {
2401 uint32_t Rd, Rn;
2402 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2403 bool setflags;
2404 switch (encoding)
2405 {
2406 case eEncodingA1:
2407 Rd = Bits32(opcode, 15, 12);
2408 Rn = Bits32(opcode, 19, 16);
2409 setflags = BitIsSet(opcode, 20);
2410 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2411 break;
2412 default:
2413 return false;
2414 }
2415
Johnny Chen8fa20592011-02-18 01:22:22 +00002416 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002417 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002418 if (!success)
2419 return false;
2420
2421 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2422
2423 EmulateInstruction::Context context;
2424 context.type = EmulateInstruction::eContextImmediate;
2425 context.SetNoArgs ();
2426
2427 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2428 return false;
2429 }
2430 return true;
2431}
2432
Johnny Chend761dcf2011-02-17 22:03:29 +00002433// This instruction adds a register value and an optionally-shifted register value, and writes the result
2434// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002435bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002436EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002437{
2438#if 0
2439 // ARM pseudo code...
2440 if ConditionPassed() then
2441 EncodingSpecificOperations();
2442 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2443 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2444 if d == 15 then
2445 ALUWritePC(result); // setflags is always FALSE here
2446 else
2447 R[d] = result;
2448 if setflags then
2449 APSR.N = result<31>;
2450 APSR.Z = IsZeroBit(result);
2451 APSR.C = carry;
2452 APSR.V = overflow;
2453#endif
2454
2455 bool success = false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002456
Greg Clayton7bc39082011-03-24 23:53:38 +00002457 if (ConditionPassed(opcode))
Johnny Chen26863dc2011-02-09 23:43:29 +00002458 {
2459 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002460 ARM_ShifterType shift_t;
2461 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002462 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002463 switch (encoding)
2464 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002465 case eEncodingT1:
2466 Rd = Bits32(opcode, 2, 0);
2467 Rn = Bits32(opcode, 5, 3);
2468 Rm = Bits32(opcode, 8, 6);
2469 setflags = !InITBlock();
2470 shift_t = SRType_LSL;
2471 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002472 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002473 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002474 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002475 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002476 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002477 shift_t = SRType_LSL;
2478 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002479 if (Rn == 15 && Rm == 15)
2480 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002481 if (Rd == 15 && InITBlock() && !LastInITBlock())
2482 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002483 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002484 case eEncodingA1:
2485 Rd = Bits32(opcode, 15, 12);
2486 Rn = Bits32(opcode, 19, 16);
2487 Rm = Bits32(opcode, 3, 0);
2488 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002489 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002490 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002491 default:
2492 return false;
2493 }
2494
Johnny Chen26863dc2011-02-09 23:43:29 +00002495 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002496 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002497 if (!success)
2498 return false;
2499
2500 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002501 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002502 if (!success)
2503 return false;
2504
Johnny Chene97c0d52011-02-18 19:32:20 +00002505 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002506 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002507
2508 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002509 context.type = EmulateInstruction::eContextAddition;
2510 Register op1_reg;
2511 Register op2_reg;
2512 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2513 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2514 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002515
Johnny Chen10530c22011-02-17 22:37:12 +00002516 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002517 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002518 }
2519 return true;
2520}
2521
Johnny Chen34075cb2011-02-22 01:56:31 +00002522// Compare Negative (immediate) adds a register value and an immediate value.
2523// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002524bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002525EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002526{
2527#if 0
2528 // ARM pseudo code...
2529 if ConditionPassed() then
2530 EncodingSpecificOperations();
2531 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2532 APSR.N = result<31>;
2533 APSR.Z = IsZeroBit(result);
2534 APSR.C = carry;
2535 APSR.V = overflow;
2536#endif
2537
2538 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002539
2540 uint32_t Rn; // the first operand
2541 uint32_t imm32; // the immediate value to be compared with
2542 switch (encoding) {
2543 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002544 Rn = Bits32(opcode, 19, 16);
2545 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2546 if (Rn == 15)
2547 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002548 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002549 case eEncodingA1:
2550 Rn = Bits32(opcode, 19, 16);
2551 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2552 break;
2553 default:
2554 return false;
2555 }
2556 // Read the register value from the operand register Rn.
2557 uint32_t reg_val = ReadCoreReg(Rn, &success);
2558 if (!success)
2559 return false;
2560
Johnny Chen078fbc62011-02-22 19:48:22 +00002561 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002562
2563 EmulateInstruction::Context context;
2564 context.type = EmulateInstruction::eContextImmediate;
2565 context.SetNoArgs ();
2566 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2567 return false;
2568
2569 return true;
2570}
2571
2572// Compare Negative (register) adds a register value and an optionally-shifted register value.
2573// It updates the condition flags based on the result, and discards the result.
2574bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002575EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen34075cb2011-02-22 01:56:31 +00002576{
2577#if 0
2578 // ARM pseudo code...
2579 if ConditionPassed() then
2580 EncodingSpecificOperations();
2581 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2582 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2583 APSR.N = result<31>;
2584 APSR.Z = IsZeroBit(result);
2585 APSR.C = carry;
2586 APSR.V = overflow;
2587#endif
2588
2589 bool success = false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002590
2591 uint32_t Rn; // the first operand
2592 uint32_t Rm; // the second operand
2593 ARM_ShifterType shift_t;
2594 uint32_t shift_n; // the shift applied to the value read from Rm
2595 switch (encoding) {
2596 case eEncodingT1:
2597 Rn = Bits32(opcode, 2, 0);
2598 Rm = Bits32(opcode, 5, 3);
2599 shift_t = SRType_LSL;
2600 shift_n = 0;
2601 break;
2602 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002603 Rn = Bits32(opcode, 19, 16);
2604 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002605 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002606 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2607 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002608 return false;
2609 break;
2610 case eEncodingA1:
2611 Rn = Bits32(opcode, 19, 16);
2612 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002613 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002614 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002615 default:
2616 return false;
2617 }
2618 // Read the register value from register Rn.
2619 uint32_t val1 = ReadCoreReg(Rn, &success);
2620 if (!success)
2621 return false;
2622
2623 // Read the register value from register Rm.
2624 uint32_t val2 = ReadCoreReg(Rm, &success);
2625 if (!success)
2626 return false;
2627
2628 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002629 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002630
2631 EmulateInstruction::Context context;
2632 context.type = EmulateInstruction::eContextImmediate;
2633 context.SetNoArgs();
2634 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2635 return false;
2636
2637 return true;
2638}
2639
2640// Compare (immediate) subtracts an immediate value from a register value.
2641// It updates the condition flags based on the result, and discards the result.
2642bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002643EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002644{
2645#if 0
2646 // ARM pseudo code...
2647 if ConditionPassed() then
2648 EncodingSpecificOperations();
2649 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2650 APSR.N = result<31>;
2651 APSR.Z = IsZeroBit(result);
2652 APSR.C = carry;
2653 APSR.V = overflow;
2654#endif
2655
2656 bool success = false;
Johnny Chend4dc4442011-02-11 02:02:56 +00002657
2658 uint32_t Rn; // the first operand
2659 uint32_t imm32; // the immediate value to be compared with
2660 switch (encoding) {
2661 case eEncodingT1:
2662 Rn = Bits32(opcode, 10, 8);
2663 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002664 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002665 case eEncodingT2:
2666 Rn = Bits32(opcode, 19, 16);
2667 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2668 if (Rn == 15)
2669 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002670 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002671 case eEncodingA1:
2672 Rn = Bits32(opcode, 19, 16);
2673 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002674 break;
2675 default:
2676 return false;
2677 }
2678 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002679 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002680 if (!success)
2681 return false;
2682
Johnny Chen10530c22011-02-17 22:37:12 +00002683 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2684
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002685 EmulateInstruction::Context context;
2686 context.type = EmulateInstruction::eContextImmediate;
2687 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002688 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2689 return false;
2690
Johnny Chend4dc4442011-02-11 02:02:56 +00002691 return true;
2692}
2693
Johnny Chen34075cb2011-02-22 01:56:31 +00002694// Compare (register) subtracts an optionally-shifted register value from a register value.
2695// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002696bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002697EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002698{
2699#if 0
2700 // ARM pseudo code...
2701 if ConditionPassed() then
2702 EncodingSpecificOperations();
2703 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2704 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2705 APSR.N = result<31>;
2706 APSR.Z = IsZeroBit(result);
2707 APSR.C = carry;
2708 APSR.V = overflow;
2709#endif
2710
2711 bool success = false;
Johnny Chene4a4d302011-02-11 21:53:58 +00002712
2713 uint32_t Rn; // the first operand
2714 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002715 ARM_ShifterType shift_t;
2716 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002717 switch (encoding) {
2718 case eEncodingT1:
2719 Rn = Bits32(opcode, 2, 0);
2720 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002721 shift_t = SRType_LSL;
2722 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002723 break;
2724 case eEncodingT2:
2725 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2726 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002727 shift_t = SRType_LSL;
2728 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002729 if (Rn < 8 && Rm < 8)
2730 return false;
2731 if (Rn == 15 || Rm == 15)
2732 return false;
2733 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002734 case eEncodingA1:
2735 Rn = Bits32(opcode, 19, 16);
2736 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002737 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002738 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002739 default:
2740 return false;
2741 }
2742 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002743 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002744 if (!success)
2745 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002746
Johnny Chene4a4d302011-02-11 21:53:58 +00002747 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002748 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002749 if (!success)
2750 return false;
2751
Johnny Chen34075cb2011-02-22 01:56:31 +00002752 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2753 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002754
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002755 EmulateInstruction::Context context;
2756 context.type = EmulateInstruction::eContextImmediate;
2757 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002758 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2759 return false;
2760
Johnny Chene4a4d302011-02-11 21:53:58 +00002761 return true;
2762}
2763
Johnny Chen82f16aa2011-02-15 20:10:55 +00002764// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2765// shifting in copies of its sign bit, and writes the result to the destination register. It can
2766// optionally update the condition flags based on the result.
2767bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002768EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen82f16aa2011-02-15 20:10:55 +00002769{
2770#if 0
2771 // ARM pseudo code...
2772 if ConditionPassed() then
2773 EncodingSpecificOperations();
2774 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2775 if d == 15 then // Can only occur for ARM encoding
2776 ALUWritePC(result); // setflags is always FALSE here
2777 else
2778 R[d] = result;
2779 if setflags then
2780 APSR.N = result<31>;
2781 APSR.Z = IsZeroBit(result);
2782 APSR.C = carry;
2783 // APSR.V unchanged
2784#endif
2785
Greg Clayton7bc39082011-03-24 23:53:38 +00002786 return EmulateShiftImm (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002787}
2788
2789// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2790// shifting in copies of its sign bit, and writes the result to the destination register.
2791// The variable number of bits is read from the bottom byte of a register. It can optionally update
2792// the condition flags based on the result.
2793bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002794EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002795{
2796#if 0
2797 // ARM pseudo code...
2798 if ConditionPassed() then
2799 EncodingSpecificOperations();
2800 shift_n = UInt(R[m]<7:0>);
2801 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2802 R[d] = result;
2803 if setflags then
2804 APSR.N = result<31>;
2805 APSR.Z = IsZeroBit(result);
2806 APSR.C = carry;
2807 // APSR.V unchanged
2808#endif
2809
Greg Clayton7bc39082011-03-24 23:53:38 +00002810 return EmulateShiftReg (opcode, encoding, SRType_ASR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002811}
2812
2813// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2814// shifting in zeros, and writes the result to the destination register. It can optionally
2815// update the condition flags based on the result.
2816bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002817EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002818{
2819#if 0
2820 // ARM pseudo code...
2821 if ConditionPassed() then
2822 EncodingSpecificOperations();
2823 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2824 if d == 15 then // Can only occur for ARM encoding
2825 ALUWritePC(result); // setflags is always FALSE here
2826 else
2827 R[d] = result;
2828 if setflags then
2829 APSR.N = result<31>;
2830 APSR.Z = IsZeroBit(result);
2831 APSR.C = carry;
2832 // APSR.V unchanged
2833#endif
2834
Greg Clayton7bc39082011-03-24 23:53:38 +00002835 return EmulateShiftImm (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002836}
2837
2838// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2839// shifting in zeros, and writes the result to the destination register. The variable number
2840// of bits is read from the bottom byte of a register. It can optionally update the condition
2841// flags based on the result.
2842bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002843EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002844{
2845#if 0
2846 // ARM pseudo code...
2847 if ConditionPassed() then
2848 EncodingSpecificOperations();
2849 shift_n = UInt(R[m]<7:0>);
2850 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2851 R[d] = result;
2852 if setflags then
2853 APSR.N = result<31>;
2854 APSR.Z = IsZeroBit(result);
2855 APSR.C = carry;
2856 // APSR.V unchanged
2857#endif
2858
Greg Clayton7bc39082011-03-24 23:53:38 +00002859 return EmulateShiftReg (opcode, encoding, SRType_LSL);
Johnny Chen41a0a152011-02-16 01:27:54 +00002860}
2861
2862// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2863// shifting in zeros, and writes the result to the destination register. It can optionally
2864// update the condition flags based on the result.
2865bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002866EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002867{
2868#if 0
2869 // ARM pseudo code...
2870 if ConditionPassed() then
2871 EncodingSpecificOperations();
2872 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2873 if d == 15 then // Can only occur for ARM encoding
2874 ALUWritePC(result); // setflags is always FALSE here
2875 else
2876 R[d] = result;
2877 if setflags then
2878 APSR.N = result<31>;
2879 APSR.Z = IsZeroBit(result);
2880 APSR.C = carry;
2881 // APSR.V unchanged
2882#endif
2883
Greg Clayton7bc39082011-03-24 23:53:38 +00002884 return EmulateShiftImm (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002885}
2886
2887// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2888// shifting in zeros, and writes the result to the destination register. The variable number
2889// of bits is read from the bottom byte of a register. It can optionally update the condition
2890// flags based on the result.
2891bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002892EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen41a0a152011-02-16 01:27:54 +00002893{
2894#if 0
2895 // ARM pseudo code...
2896 if ConditionPassed() then
2897 EncodingSpecificOperations();
2898 shift_n = UInt(R[m]<7:0>);
2899 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2900 R[d] = result;
2901 if setflags then
2902 APSR.N = result<31>;
2903 APSR.Z = IsZeroBit(result);
2904 APSR.C = carry;
2905 // APSR.V unchanged
2906#endif
2907
Greg Clayton7bc39082011-03-24 23:53:38 +00002908 return EmulateShiftReg (opcode, encoding, SRType_LSR);
Johnny Chen41a0a152011-02-16 01:27:54 +00002909}
2910
Johnny Cheneeab4852011-02-16 22:14:44 +00002911// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2912// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2913// It can optionally update the condition flags based on the result.
2914bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002915EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002916{
2917#if 0
2918 // ARM pseudo code...
2919 if ConditionPassed() then
2920 EncodingSpecificOperations();
2921 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2922 if d == 15 then // Can only occur for ARM encoding
2923 ALUWritePC(result); // setflags is always FALSE here
2924 else
2925 R[d] = result;
2926 if setflags then
2927 APSR.N = result<31>;
2928 APSR.Z = IsZeroBit(result);
2929 APSR.C = carry;
2930 // APSR.V unchanged
2931#endif
2932
Greg Clayton7bc39082011-03-24 23:53:38 +00002933 return EmulateShiftImm (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002934}
2935
2936// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2937// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2938// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2939// flags based on the result.
2940bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002941EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002942{
2943#if 0
2944 // ARM pseudo code...
2945 if ConditionPassed() then
2946 EncodingSpecificOperations();
2947 shift_n = UInt(R[m]<7:0>);
2948 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2949 R[d] = result;
2950 if setflags then
2951 APSR.N = result<31>;
2952 APSR.Z = IsZeroBit(result);
2953 APSR.C = carry;
2954 // APSR.V unchanged
2955#endif
2956
Greg Clayton7bc39082011-03-24 23:53:38 +00002957 return EmulateShiftReg (opcode, encoding, SRType_ROR);
Johnny Cheneeab4852011-02-16 22:14:44 +00002958}
2959
2960// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2961// with the carry flag shifted into bit [31].
2962//
2963// RRX can optionally update the condition flags based on the result.
2964// In that case, bit [0] is shifted into the carry flag.
2965bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002966EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
Johnny Cheneeab4852011-02-16 22:14:44 +00002967{
2968#if 0
2969 // ARM pseudo code...
2970 if ConditionPassed() then
2971 EncodingSpecificOperations();
2972 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2973 if d == 15 then // Can only occur for ARM encoding
2974 ALUWritePC(result); // setflags is always FALSE here
2975 else
2976 R[d] = result;
2977 if setflags then
2978 APSR.N = result<31>;
2979 APSR.Z = IsZeroBit(result);
2980 APSR.C = carry;
2981 // APSR.V unchanged
2982#endif
2983
Greg Clayton7bc39082011-03-24 23:53:38 +00002984 return EmulateShiftImm (opcode, encoding, SRType_RRX);
Johnny Cheneeab4852011-02-16 22:14:44 +00002985}
2986
Johnny Chen41a0a152011-02-16 01:27:54 +00002987bool
Greg Clayton7bc39082011-03-24 23:53:38 +00002988EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chen41a0a152011-02-16 01:27:54 +00002989{
Caroline Ticebb48f0b2011-03-28 16:10:45 +00002990 assert(shift_type == SRType_ASR
2991 || shift_type == SRType_LSL
2992 || shift_type == SRType_LSR
2993 || shift_type == SRType_ROR
2994 || shift_type == SRType_RRX);
Johnny Chen41a0a152011-02-16 01:27:54 +00002995
Johnny Chen82f16aa2011-02-15 20:10:55 +00002996 bool success = false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002997
Greg Clayton7bc39082011-03-24 23:53:38 +00002998 if (ConditionPassed(opcode))
Johnny Chen82f16aa2011-02-15 20:10:55 +00002999 {
Johnny Chene7f89532011-02-15 23:22:46 +00003000 uint32_t Rd; // the destination register
3001 uint32_t Rm; // the first operand register
3002 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003003 uint32_t carry; // the carry bit after the shift operation
3004 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003005
3006 // Special case handling!
3007 // A8.6.139 ROR (immediate) -- Encoding T1
Greg Clayton7bc39082011-03-24 23:53:38 +00003008 ARMEncoding use_encoding = encoding;
3009 if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
Johnny Cheneeab4852011-02-16 22:14:44 +00003010 {
3011 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3012 // have the same decoding of bit fields as the other Thumb2 shift operations.
Greg Clayton7bc39082011-03-24 23:53:38 +00003013 use_encoding = eEncodingT2;
Johnny Cheneeab4852011-02-16 22:14:44 +00003014 }
3015
Greg Clayton7bc39082011-03-24 23:53:38 +00003016 switch (use_encoding) {
Johnny Chen82f16aa2011-02-15 20:10:55 +00003017 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003018 // Due to the above special case handling!
3019 assert(shift_type != SRType_ROR);
3020
Johnny Chen82f16aa2011-02-15 20:10:55 +00003021 Rd = Bits32(opcode, 2, 0);
3022 Rm = Bits32(opcode, 5, 3);
3023 setflags = !InITBlock();
3024 imm5 = Bits32(opcode, 10, 6);
3025 break;
3026 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003027 // A8.6.141 RRX
3028 assert(shift_type != SRType_RRX);
3029
Johnny Chen82f16aa2011-02-15 20:10:55 +00003030 Rd = Bits32(opcode, 11, 8);
3031 Rm = Bits32(opcode, 3, 0);
3032 setflags = BitIsSet(opcode, 20);
3033 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3034 if (BadReg(Rd) || BadReg(Rm))
3035 return false;
3036 break;
3037 case eEncodingA1:
3038 Rd = Bits32(opcode, 15, 12);
3039 Rm = Bits32(opcode, 3, 0);
3040 setflags = BitIsSet(opcode, 20);
3041 imm5 = Bits32(opcode, 11, 7);
3042 break;
3043 default:
3044 return false;
3045 }
3046
Johnny Cheneeab4852011-02-16 22:14:44 +00003047 // A8.6.139 ROR (immediate)
3048 if (shift_type == SRType_ROR && imm5 == 0)
3049 shift_type = SRType_RRX;
3050
Johnny Chen82f16aa2011-02-15 20:10:55 +00003051 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003052 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003053 if (!success)
3054 return false;
3055
Johnny Cheneeab4852011-02-16 22:14:44 +00003056 // Decode the shift amount if not RRX.
3057 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003058
Johnny Chene97c0d52011-02-18 19:32:20 +00003059 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003060
3061 // The context specifies that an immediate is to be moved into Rd.
3062 EmulateInstruction::Context context;
3063 context.type = EmulateInstruction::eContextImmediate;
3064 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003065
Johnny Chen10530c22011-02-17 22:37:12 +00003066 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003067 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003068 }
3069 return true;
3070}
3071
Johnny Chene7f89532011-02-15 23:22:46 +00003072bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003073EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003074{
Johnny Chen41a0a152011-02-16 01:27:54 +00003075 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003076
3077 bool success = false;
Johnny Chene7f89532011-02-15 23:22:46 +00003078
Greg Clayton7bc39082011-03-24 23:53:38 +00003079 if (ConditionPassed(opcode))
Johnny Chene7f89532011-02-15 23:22:46 +00003080 {
3081 uint32_t Rd; // the destination register
3082 uint32_t Rn; // the first operand register
3083 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3084 uint32_t carry; // the carry bit after the shift operation
3085 bool setflags;
3086 switch (encoding) {
3087 case eEncodingT1:
3088 Rd = Bits32(opcode, 2, 0);
3089 Rn = Rd;
3090 Rm = Bits32(opcode, 5, 3);
3091 setflags = !InITBlock();
3092 break;
3093 case eEncodingT2:
3094 Rd = Bits32(opcode, 11, 8);
3095 Rn = Bits32(opcode, 19, 16);
3096 Rm = Bits32(opcode, 3, 0);
3097 setflags = BitIsSet(opcode, 20);
3098 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3099 return false;
3100 break;
3101 case eEncodingA1:
3102 Rd = Bits32(opcode, 15, 12);
3103 Rn = Bits32(opcode, 3, 0);
3104 Rm = Bits32(opcode, 11, 8);
3105 setflags = BitIsSet(opcode, 20);
3106 if (Rd == 15 || Rn == 15 || Rm == 15)
3107 return false;
3108 break;
3109 default:
3110 return false;
3111 }
3112
3113 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003114 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003115 if (!success)
3116 return false;
3117 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003118 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003119 if (!success)
3120 return false;
3121
3122 // Get the shift amount.
3123 uint32_t amt = Bits32(val, 7, 0);
3124
Johnny Chene97c0d52011-02-18 19:32:20 +00003125 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003126
3127 // The context specifies that an immediate is to be moved into Rd.
3128 EmulateInstruction::Context context;
3129 context.type = EmulateInstruction::eContextImmediate;
3130 context.SetNoArgs ();
3131
Johnny Chen10530c22011-02-17 22:37:12 +00003132 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003133 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003134 }
3135 return true;
3136}
3137
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003138// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003139// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003140// can be written back to the base register.
3141bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003142EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003143{
3144#if 0
3145 // ARM pseudo code...
3146 if ConditionPassed()
3147 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3148 address = R[n];
3149
3150 for i = 0 to 14
3151 if registers<i> == '1' then
3152 R[i] = MemA[address, 4]; address = address + 4;
3153 if registers<15> == '1' then
3154 LoadWritePC (MemA[address, 4]);
3155
3156 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3157 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3158
3159#endif
3160
3161 bool success = false;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003162
Greg Clayton7bc39082011-03-24 23:53:38 +00003163 if (ConditionPassed(opcode))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003164 {
3165 uint32_t n;
3166 uint32_t registers = 0;
3167 bool wback;
3168 const uint32_t addr_byte_size = GetAddressByteSize();
3169 switch (encoding)
3170 {
3171 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003172 // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003173 n = Bits32 (opcode, 10, 8);
3174 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003175 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003176 wback = BitIsClear (registers, n);
3177 // if BitCount(registers) < 1 then UNPREDICTABLE;
3178 if (BitCount(registers) < 1)
3179 return false;
3180 break;
3181 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003182 // if W == '1' && Rn == '1101' then SEE POP;
3183 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003184 n = Bits32 (opcode, 19, 16);
3185 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003186 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003187 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003188
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003189 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003190 if ((n == 15)
3191 || (BitCount (registers) < 2)
3192 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3193 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003194
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003195 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003196 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003197 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003198
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003199 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003200 if (wback
3201 && BitIsSet (registers, n))
3202 return false;
3203 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003204
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003205 case eEncodingA1:
3206 n = Bits32 (opcode, 19, 16);
3207 registers = Bits32 (opcode, 15, 0);
3208 wback = BitIsSet (opcode, 21);
3209 if ((n == 15)
3210 || (BitCount (registers) < 1))
3211 return false;
3212 break;
3213 default:
3214 return false;
3215 }
3216
3217 int32_t offset = 0;
3218 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3219 if (!success)
3220 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003221
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003222 EmulateInstruction::Context context;
3223 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3224 Register dwarf_reg;
3225 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3226 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003227
3228 for (int i = 0; i < 14; ++i)
3229 {
3230 if (BitIsSet (registers, i))
3231 {
Caroline Tice85aab332011-02-08 23:56:10 +00003232 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003233 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003234 if (wback && (n == 13)) // Pop Instruction
3235 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3236
3237 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003238 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003239 if (!success)
3240 return false;
3241
3242 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3243 return false;
3244
3245 offset += addr_byte_size;
3246 }
3247 }
3248
3249 if (BitIsSet (registers, 15))
3250 {
3251 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003252 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003253 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003254 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003255 if (!success)
3256 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003257 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003258 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003259 return false;
3260 }
3261
3262 if (wback && BitIsClear (registers, n))
3263 {
Caroline Ticefa172202011-02-11 22:49:54 +00003264 // R[n] = R[n] + 4 * BitCount (registers)
3265 int32_t offset = addr_byte_size * BitCount (registers);
3266 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003267 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003268
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003269 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3270 return false;
3271 }
3272 if (wback && BitIsSet (registers, n))
3273 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003274 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003275 }
3276 return true;
3277}
Caroline Tice713c2662011-02-11 17:59:55 +00003278
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003279// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
3280// The consecutive memory locations end at this address and the address just below the lowest of those locations
3281// can optionally be written back to the base register.
Caroline Tice713c2662011-02-11 17:59:55 +00003282bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003283EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice713c2662011-02-11 17:59:55 +00003284{
3285#if 0
3286 // ARM pseudo code...
3287 if ConditionPassed() then
3288 EncodingSpecificOperations();
3289 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003290
Caroline Tice713c2662011-02-11 17:59:55 +00003291 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003292 if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003293 R[i] = MemA[address,4]; address = address + 4;
3294
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003295 if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003296 LoadWritePC(MemA[address,4]);
3297
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003298 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3299 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003300#endif
3301
3302 bool success = false;
Caroline Tice713c2662011-02-11 17:59:55 +00003303
Greg Clayton7bc39082011-03-24 23:53:38 +00003304 if (ConditionPassed(opcode))
Caroline Tice713c2662011-02-11 17:59:55 +00003305 {
3306 uint32_t n;
3307 uint32_t registers = 0;
3308 bool wback;
3309 const uint32_t addr_byte_size = GetAddressByteSize();
3310
3311 // EncodingSpecificOperations();
3312 switch (encoding)
3313 {
3314 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003315 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice713c2662011-02-11 17:59:55 +00003316 n = Bits32 (opcode, 19, 16);
3317 registers = Bits32 (opcode, 15, 0);
3318 wback = BitIsSet (opcode, 21);
3319
3320 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3321 if ((n == 15) || (BitCount (registers) < 1))
3322 return false;
3323
3324 break;
3325
3326 default:
3327 return false;
3328 }
3329 // address = R[n] - 4*BitCount(registers) + 4;
3330
3331 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003332 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003333
3334 if (!success)
3335 return false;
3336
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003337 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
Caroline Tice713c2662011-02-11 17:59:55 +00003338
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003339 EmulateInstruction::Context context;
3340 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3341 Register dwarf_reg;
3342 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3343 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003344
3345 // for i = 0 to 14
3346 for (int i = 0; i < 14; ++i)
3347 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003348 // if registers<i> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003349 if (BitIsSet (registers, i))
3350 {
3351 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003352 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003353 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003354 if (!success)
3355 return false;
3356 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3357 return false;
3358 offset += addr_byte_size;
3359 }
3360 }
3361
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003362 // if registers<15> == '1' then
Caroline Tice713c2662011-02-11 17:59:55 +00003363 // LoadWritePC(MemA[address,4]);
3364 if (BitIsSet (registers, 15))
3365 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003366 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003367 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003368 if (!success)
3369 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003370 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003371 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003372 return false;
3373 }
3374
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003375 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice713c2662011-02-11 17:59:55 +00003376 if (wback && BitIsClear (registers, n))
3377 {
Caroline Tice713c2662011-02-11 17:59:55 +00003378 if (!success)
3379 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003380
3381 offset = (addr_byte_size * BitCount (registers)) * -1;
3382 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003383 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003384 addr_t addr = Rn + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003385 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3386 return false;
3387 }
3388
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003389 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003390 if (wback && BitIsSet (registers, n))
3391 return WriteBits32Unknown (n);
3392 }
3393 return true;
3394}
3395
3396// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3397// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3398// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003399bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003400EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0b29e242011-02-08 23:16:02 +00003401{
3402#if 0
3403 // ARM pseudo code...
3404 if ConditionPassed() then
3405 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3406 address = R[n] - 4*BitCount(registers);
3407
3408 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003409 if registers<i> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003410 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003411 if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003412 LoadWritePC(MemA[address,4]);
3413
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003414 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
3415 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003416#endif
3417
3418 bool success = false;
Caroline Tice0b29e242011-02-08 23:16:02 +00003419
Greg Clayton7bc39082011-03-24 23:53:38 +00003420 if (ConditionPassed(opcode))
Caroline Tice0b29e242011-02-08 23:16:02 +00003421 {
3422 uint32_t n;
3423 uint32_t registers = 0;
3424 bool wback;
3425 const uint32_t addr_byte_size = GetAddressByteSize();
3426 switch (encoding)
3427 {
3428 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003429 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003430 n = Bits32 (opcode, 19, 16);
3431 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003432 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003433 wback = BitIsSet (opcode, 21);
3434
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003435 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003436 if ((n == 15)
3437 || (BitCount (registers) < 2)
3438 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3439 return false;
3440
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003441 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003442 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003443 return false;
3444
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003445 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Tice0b29e242011-02-08 23:16:02 +00003446 if (wback && BitIsSet (registers, n))
3447 return false;
3448
3449 break;
3450
3451 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003452 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice0b29e242011-02-08 23:16:02 +00003453 n = Bits32 (opcode, 19, 16);
3454 registers = Bits32 (opcode, 15, 0);
3455 wback = BitIsSet (opcode, 21);
3456
3457 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3458 if ((n == 15) || (BitCount (registers) < 1))
3459 return false;
3460
3461 break;
3462
3463 default:
3464 return false;
3465 }
3466
Caroline Tice713c2662011-02-11 17:59:55 +00003467 // address = R[n] - 4*BitCount(registers);
3468
Caroline Tice0b29e242011-02-08 23:16:02 +00003469 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003470 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003471
3472 if (!success)
3473 return false;
3474
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003475 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003476 EmulateInstruction::Context context;
3477 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3478 Register dwarf_reg;
3479 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003480 context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
Caroline Tice0b29e242011-02-08 23:16:02 +00003481
3482 for (int i = 0; i < 14; ++i)
3483 {
3484 if (BitIsSet (registers, i))
3485 {
3486 // R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003487 context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00003488 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003489 if (!success)
3490 return false;
3491
3492 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3493 return false;
3494
3495 offset += addr_byte_size;
3496 }
3497 }
3498
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003499 // if registers<15> == '1' then
Caroline Tice0b29e242011-02-08 23:16:02 +00003500 // LoadWritePC(MemA[address,4]);
3501 if (BitIsSet (registers, 15))
3502 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003503 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003504 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003505 if (!success)
3506 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003507 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003508 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003509 return false;
3510 }
3511
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003512 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
Caroline Tice0b29e242011-02-08 23:16:02 +00003513 if (wback && BitIsClear (registers, n))
3514 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003515 if (!success)
3516 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003517
3518 offset = (addr_byte_size * BitCount (registers)) * -1;
3519 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003520 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003521 addr_t addr = Rn + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003522 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3523 return false;
3524 }
3525
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003526 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice0b29e242011-02-08 23:16:02 +00003527 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003528 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003529 }
3530 return true;
3531}
Caroline Tice85aab332011-02-08 23:56:10 +00003532
Caroline Tice713c2662011-02-11 17:59:55 +00003533// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3534// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3535// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003536bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003537EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice85aab332011-02-08 23:56:10 +00003538{
3539#if 0
3540 if ConditionPassed() then
3541 EncodingSpecificOperations();
3542 address = R[n] + 4;
3543
3544 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003545 if registers<i> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003546 R[i] = MemA[address,4]; address = address + 4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003547 if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003548 LoadWritePC(MemA[address,4]);
3549
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003550 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
3551 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
Caroline Tice85aab332011-02-08 23:56:10 +00003552#endif
3553
3554 bool success = false;
Caroline Tice85aab332011-02-08 23:56:10 +00003555
Greg Clayton7bc39082011-03-24 23:53:38 +00003556 if (ConditionPassed(opcode))
Caroline Tice85aab332011-02-08 23:56:10 +00003557 {
3558 uint32_t n;
3559 uint32_t registers = 0;
3560 bool wback;
3561 const uint32_t addr_byte_size = GetAddressByteSize();
3562 switch (encoding)
3563 {
3564 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003565 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice85aab332011-02-08 23:56:10 +00003566 n = Bits32 (opcode, 19, 16);
3567 registers = Bits32 (opcode, 15, 0);
3568 wback = BitIsSet (opcode, 21);
3569
3570 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3571 if ((n == 15) || (BitCount (registers) < 1))
3572 return false;
3573
3574 break;
3575 default:
3576 return false;
3577 }
3578 // address = R[n] + 4;
3579
3580 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003581 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003582
3583 if (!success)
3584 return false;
3585
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003586 addr_t address = Rn + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003587
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003588 EmulateInstruction::Context context;
3589 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3590 Register dwarf_reg;
3591 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3592 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003593
3594 for (int i = 0; i < 14; ++i)
3595 {
3596 if (BitIsSet (registers, i))
3597 {
3598 // R[i] = MemA[address,4]; address = address + 4;
3599
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003600 context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003601 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003602 if (!success)
3603 return false;
3604
3605 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3606 return false;
3607
3608 offset += addr_byte_size;
3609 }
3610 }
3611
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003612 // if registers<15> == '1' then
Caroline Tice85aab332011-02-08 23:56:10 +00003613 // LoadWritePC(MemA[address,4]);
3614 if (BitIsSet (registers, 15))
3615 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003616 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003617 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003618 if (!success)
3619 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003620 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003621 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003622 return false;
3623 }
3624
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003625 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
Caroline Tice85aab332011-02-08 23:56:10 +00003626 if (wback && BitIsClear (registers, n))
3627 {
Caroline Tice85aab332011-02-08 23:56:10 +00003628 if (!success)
3629 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003630
3631 offset = addr_byte_size * BitCount (registers);
3632 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003633 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003634 addr_t addr = Rn + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003635 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3636 return false;
3637 }
3638
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003639 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
Caroline Tice85aab332011-02-08 23:56:10 +00003640 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003641 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003642 }
3643 return true;
3644}
Caroline Tice0b29e242011-02-08 23:16:02 +00003645
Johnny Chenef21b592011-02-10 01:52:38 +00003646// Load Register (immediate) calculates an address from a base register value and
3647// an immediate offset, loads a word from memory, and writes to a register.
3648// LDR (immediate, Thumb)
3649bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003650EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenef21b592011-02-10 01:52:38 +00003651{
3652#if 0
3653 // ARM pseudo code...
3654 if (ConditionPassed())
3655 {
3656 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3657 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3658 address = if index then offset_addr else R[n];
3659 data = MemU[address,4];
3660 if wback then R[n] = offset_addr;
3661 if t == 15 then
3662 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3663 elsif UnalignedSupport() || address<1:0> = '00' then
3664 R[t] = data;
3665 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3666 }
3667#endif
3668
3669 bool success = false;
Johnny Chenef21b592011-02-10 01:52:38 +00003670
Greg Clayton7bc39082011-03-24 23:53:38 +00003671 if (ConditionPassed(opcode))
Johnny Chenef21b592011-02-10 01:52:38 +00003672 {
3673 uint32_t Rt; // the destination register
3674 uint32_t Rn; // the base register
3675 uint32_t imm32; // the immediate offset used to form the address
3676 addr_t offset_addr; // the offset address
3677 addr_t address; // the calculated address
3678 uint32_t data; // the literal data value from memory load
3679 bool add, index, wback;
3680 switch (encoding) {
Caroline Ticebaf1f642011-03-24 19:23:45 +00003681 case eEncodingT1:
3682 Rt = Bits32(opcode, 5, 3);
3683 Rn = Bits32(opcode, 2, 0);
3684 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3685 // index = TRUE; add = TRUE; wback = FALSE
3686 add = true;
3687 index = true;
3688 wback = false;
3689
3690 break;
3691
3692 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003693 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003694 Rt = Bits32 (opcode, 10, 8);
3695 Rn = 13;
3696 imm32 = Bits32 (opcode, 7, 0) << 2;
3697
3698 // index = TRUE; add = TRUE; wback = FALSE;
3699 index = true;
3700 add = true;
3701 wback = false;
3702
3703 break;
3704
3705 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003706 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticebaf1f642011-03-24 19:23:45 +00003707 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
3708 Rt = Bits32 (opcode, 15, 12);
3709 Rn = Bits32 (opcode, 19, 16);
3710 imm32 = Bits32 (opcode, 11, 0);
3711
3712 // index = TRUE; add = TRUE; wback = FALSE;
3713 index = true;
3714 add = true;
3715 wback = false;
3716
3717 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
3718 if ((Rt == 15) && InITBlock() && !LastInITBlock())
3719 return false;
3720
3721 break;
3722
3723 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003724 // if Rn == '1111' then SEE LDR (literal);
3725 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
3726 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
3727 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003728 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
3729 return false;
3730
3731 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
3732 Rt = Bits32 (opcode, 15, 12);
3733 Rn = Bits32 (opcode, 19, 16);
3734 imm32 = Bits32 (opcode, 7, 0);
3735
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003736 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticebaf1f642011-03-24 19:23:45 +00003737 index = BitIsSet (opcode, 10);
3738 add = BitIsSet (opcode, 9);
3739 wback = BitIsSet (opcode, 8);
3740
3741 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
3742 if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
3743 return false;
3744
3745 break;
3746
3747 default:
3748 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003749 }
Caroline Ticebaf1f642011-03-24 19:23:45 +00003750 uint32_t base = ReadCoreReg (Rn, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003751 if (!success)
3752 return false;
3753 if (add)
3754 offset_addr = base + imm32;
3755 else
3756 offset_addr = base - imm32;
3757
3758 address = (index ? offset_addr : base);
3759
Caroline Ticebaf1f642011-03-24 19:23:45 +00003760 Register base_reg;
3761 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
Johnny Chenef21b592011-02-10 01:52:38 +00003762 if (wback)
3763 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003764 EmulateInstruction::Context ctx;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003765 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
3766 ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003767
Johnny Chenef21b592011-02-10 01:52:38 +00003768 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3769 return false;
3770 }
3771
3772 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003773 EmulateInstruction::Context context;
Caroline Ticebaf1f642011-03-24 19:23:45 +00003774 context.type = EmulateInstruction::eContextRegisterLoad;
3775 context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
Johnny Chenef21b592011-02-10 01:52:38 +00003776
3777 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003778 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003779 if (!success)
3780 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003781
3782 if (Rt == 15)
3783 {
3784 if (Bits32(address, 1, 0) == 0)
3785 {
Johnny Chen668b4512011-02-15 21:08:58 +00003786 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003787 return false;
3788 }
3789 else
3790 return false;
3791 }
3792 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3793 {
3794 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3795 return false;
3796 }
3797 else
Caroline Ticebaf1f642011-03-24 19:23:45 +00003798 WriteBits32Unknown (Rt);
Johnny Chenef21b592011-02-10 01:52:38 +00003799 }
3800 return true;
3801}
3802
Caroline Ticeaf556562011-02-15 18:42:15 +00003803// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3804// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3805// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003806bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003807EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefa172202011-02-11 22:49:54 +00003808{
3809#if 0
3810 if ConditionPassed() then
3811 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3812 address = R[n];
3813
3814 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003815 if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003816 if i == n && wback && i != LowestSetBit(registers) then
3817 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3818 else
3819 MemA[address,4] = R[i];
3820 address = address + 4;
3821
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003822 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003823 MemA[address,4] = PCStoreValue();
3824 if wback then R[n] = R[n] + 4*BitCount(registers);
3825#endif
3826
3827 bool success = false;
Caroline Ticefa172202011-02-11 22:49:54 +00003828
Greg Clayton7bc39082011-03-24 23:53:38 +00003829 if (ConditionPassed(opcode))
Caroline Ticefa172202011-02-11 22:49:54 +00003830 {
3831 uint32_t n;
3832 uint32_t registers = 0;
3833 bool wback;
3834 const uint32_t addr_byte_size = GetAddressByteSize();
3835
3836 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3837 switch (encoding)
3838 {
3839 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003840 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
Caroline Ticefa172202011-02-11 22:49:54 +00003841 n = Bits32 (opcode, 10, 8);
3842 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003843 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003844 wback = true;
3845
3846 // if BitCount(registers) < 1 then UNPREDICTABLE;
3847 if (BitCount (registers) < 1)
3848 return false;
3849
3850 break;
3851
3852 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003853 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003854 n = Bits32 (opcode, 19, 16);
3855 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003856 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003857 wback = BitIsSet (opcode, 21);
3858
3859 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3860 if ((n == 15) || (BitCount (registers) < 2))
3861 return false;
3862
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003863 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticefa172202011-02-11 22:49:54 +00003864 if (wback && BitIsSet (registers, n))
3865 return false;
3866
3867 break;
3868
3869 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003870 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticefa172202011-02-11 22:49:54 +00003871 n = Bits32 (opcode, 19, 16);
3872 registers = Bits32 (opcode, 15, 0);
3873 wback = BitIsSet (opcode, 21);
3874
3875 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3876 if ((n == 15) || (BitCount (registers) < 1))
3877 return false;
3878
3879 break;
3880
3881 default:
3882 return false;
3883 }
3884
3885 // address = R[n];
3886 int32_t offset = 0;
3887 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3888 if (!success)
3889 return false;
3890
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003891 EmulateInstruction::Context context;
3892 context.type = EmulateInstruction::eContextRegisterStore;
3893 Register base_reg;
3894 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003895
3896 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003897 int lowest_set_bit = 14;
Caroline Ticefa172202011-02-11 22:49:54 +00003898 for (int i = 0; i < 14; ++i)
3899 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003900 // if registers<i> == '1' then
Caroline Ticefa172202011-02-11 22:49:54 +00003901 if (BitIsSet (registers, i))
3902 {
3903 if (i < lowest_set_bit)
3904 lowest_set_bit = i;
3905 // if i == n && wback && i != LowestSetBit(registers) then
3906 if ((i == n) && wback && (i != lowest_set_bit))
3907 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3908 WriteBits32UnknownToMemory (address + offset);
3909 else
3910 {
3911 // MemA[address,4] = R[i];
3912 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3913 if (!success)
3914 return false;
3915
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003916 Register data_reg;
3917 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3918 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003919 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003920 return false;
3921 }
3922
3923 // address = address + 4;
3924 offset += addr_byte_size;
3925 }
3926 }
3927
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003928 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticefa172202011-02-11 22:49:54 +00003929 // MemA[address,4] = PCStoreValue();
3930 if (BitIsSet (registers, 15))
3931 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003932 Register pc_reg;
3933 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3934 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00003935 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00003936 if (!success)
3937 return false;
3938
Caroline Tice8d681f52011-03-17 23:50:16 +00003939 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003940 return false;
3941 }
3942
3943 // if wback then R[n] = R[n] + 4*BitCount(registers);
3944 if (wback)
3945 {
3946 offset = addr_byte_size * BitCount (registers);
3947 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003948 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003949 addr_t data = address + offset;
3950 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3951 return false;
3952 }
3953 }
3954 return true;
3955}
3956
Caroline Ticeaf556562011-02-15 18:42:15 +00003957// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3958// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3959// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003960bool
Greg Clayton7bc39082011-03-24 23:53:38 +00003961EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice1511f502011-02-15 00:19:42 +00003962{
3963#if 0
3964 if ConditionPassed() then
3965 EncodingSpecificOperations();
3966 address = R[n] - 4*BitCount(registers) + 4;
3967
3968 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003969 if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00003970 if i == n && wback && i != LowestSetBit(registers) then
3971 MemA[address,4] = bits(32) UNKNOWN;
3972 else
3973 MemA[address,4] = R[i];
3974 address = address + 4;
3975
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003976 if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00003977 MemA[address,4] = PCStoreValue();
3978
3979 if wback then R[n] = R[n] - 4*BitCount(registers);
3980#endif
3981
3982 bool success = false;
Caroline Tice1511f502011-02-15 00:19:42 +00003983
Greg Clayton7bc39082011-03-24 23:53:38 +00003984 if (ConditionPassed(opcode))
Caroline Tice1511f502011-02-15 00:19:42 +00003985 {
3986 uint32_t n;
3987 uint32_t registers = 0;
3988 bool wback;
3989 const uint32_t addr_byte_size = GetAddressByteSize();
3990
3991 // EncodingSpecificOperations();
3992 switch (encoding)
3993 {
3994 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00003995 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Tice1511f502011-02-15 00:19:42 +00003996 n = Bits32 (opcode, 19, 16);
3997 registers = Bits32 (opcode, 15, 0);
3998 wback = BitIsSet (opcode, 21);
3999
4000 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4001 if ((n == 15) || (BitCount (registers) < 1))
4002 return false;
4003 break;
4004 default:
4005 return false;
4006 }
4007
4008 // address = R[n] - 4*BitCount(registers) + 4;
4009 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004010 addr_t Rn = ReadCoreReg (n, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004011 if (!success)
4012 return false;
4013
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004014 addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
Caroline Tice1511f502011-02-15 00:19:42 +00004015
4016 EmulateInstruction::Context context;
4017 context.type = EmulateInstruction::eContextRegisterStore;
4018 Register base_reg;
4019 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4020
4021 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004022 int lowest_bit_set = 14;
Caroline Tice1511f502011-02-15 00:19:42 +00004023 for (int i = 0; i < 14; ++i)
4024 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004025 // if registers<i> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004026 if (BitIsSet (registers, i))
4027 {
4028 if (i < lowest_bit_set)
4029 lowest_bit_set = i;
4030 //if i == n && wback && i != LowestSetBit(registers) then
4031 if ((i == n) && wback && (i != lowest_bit_set))
4032 // MemA[address,4] = bits(32) UNKNOWN;
4033 WriteBits32UnknownToMemory (address + offset);
4034 else
4035 {
4036 // MemA[address,4] = R[i];
4037 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4038 if (!success)
4039 return false;
4040
4041 Register data_reg;
4042 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004043 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004044 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004045 return false;
4046 }
4047
4048 // address = address + 4;
4049 offset += addr_byte_size;
4050 }
4051 }
4052
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004053 // if registers<15> == '1' then
Caroline Tice1511f502011-02-15 00:19:42 +00004054 // MemA[address,4] = PCStoreValue();
4055 if (BitIsSet (registers, 15))
4056 {
4057 Register pc_reg;
4058 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4059 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004060 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004061 if (!success)
4062 return false;
4063
Caroline Tice8d681f52011-03-17 23:50:16 +00004064 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004065 return false;
4066 }
4067
4068 // if wback then R[n] = R[n] - 4*BitCount(registers);
4069 if (wback)
4070 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004071 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004072 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4073 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004074 addr_t data = Rn + offset;
Caroline Tice1511f502011-02-15 00:19:42 +00004075 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4076 return false;
4077 }
4078 }
4079 return true;
4080}
4081
Caroline Ticeaf556562011-02-15 18:42:15 +00004082// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4083// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4084// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004085bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004086EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004087{
4088#if 0
4089 if ConditionPassed() then
4090 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4091 address = R[n] - 4*BitCount(registers);
4092
4093 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004094 if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004095 if i == n && wback && i != LowestSetBit(registers) then
4096 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4097 else
4098 MemA[address,4] = R[i];
4099 address = address + 4;
4100
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004101 if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004102 MemA[address,4] = PCStoreValue();
4103
4104 if wback then R[n] = R[n] - 4*BitCount(registers);
4105#endif
4106
4107
4108 bool success = false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004109
Greg Clayton7bc39082011-03-24 23:53:38 +00004110 if (ConditionPassed(opcode))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004111 {
4112 uint32_t n;
4113 uint32_t registers = 0;
4114 bool wback;
4115 const uint32_t addr_byte_size = GetAddressByteSize();
4116
4117 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4118 switch (encoding)
4119 {
4120 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004121 // if W == '1' && Rn == '1101' then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004122 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4123 {
4124 // See PUSH
4125 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004126 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004127 n = Bits32 (opcode, 19, 16);
4128 registers = Bits32 (opcode, 15, 0);
4129 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4130 wback = BitIsSet (opcode, 21);
4131 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4132 if ((n == 15) || BitCount (registers) < 2)
4133 return false;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004134 // if wback && registers<n> == '1' then UNPREDICTABLE;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004135 if (wback && BitIsSet (registers, n))
4136 return false;
4137 break;
4138
4139 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004140 // if W == '1' && Rn == '1101’ && BitCount(register_list) >= 2 then SEE PUSH;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004141 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4142 {
4143 // See Push
4144 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004145 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004146 n = Bits32 (opcode, 19, 16);
4147 registers = Bits32 (opcode, 15, 0);
4148 wback = BitIsSet (opcode, 21);
4149 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4150 if ((n == 15) || BitCount (registers) < 1)
4151 return false;
4152 break;
4153
4154 default:
4155 return false;
4156 }
4157
4158 // address = R[n] - 4*BitCount(registers);
4159
4160 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004161 addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004162 if (!success)
4163 return false;
4164
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004165 addr_t address = Rn - (addr_byte_size * BitCount (registers));
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004166
4167 EmulateInstruction::Context context;
4168 context.type = EmulateInstruction::eContextRegisterStore;
4169 Register base_reg;
4170 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4171
4172 // for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004173 uint32_t lowest_set_bit = 14;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004174 for (int i = 0; i < 14; ++i)
4175 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004176 // if registers<i> == '1' then
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004177 if (BitIsSet (registers, i))
4178 {
4179 if (i < lowest_set_bit)
4180 lowest_set_bit = i;
4181 // if i == n && wback && i != LowestSetBit(registers) then
4182 if ((i == n) && wback && (i != lowest_set_bit))
4183 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4184 WriteBits32UnknownToMemory (address + offset);
4185 else
4186 {
4187 // MemA[address,4] = R[i];
4188 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4189 if (!success)
4190 return false;
4191
4192 Register data_reg;
4193 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004194 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
Caroline Ticecc96eb52011-02-17 19:20:40 +00004195 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004196 return false;
4197 }
4198
4199 // address = address + 4;
4200 offset += addr_byte_size;
4201 }
4202 }
4203
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004204 // if registers<15> == '1' then // Only possible for encoding A1
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004205 // MemA[address,4] = PCStoreValue();
4206 if (BitIsSet (registers, 15))
4207 {
4208 Register pc_reg;
4209 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4210 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004211 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004212 if (!success)
4213 return false;
4214
Caroline Tice8d681f52011-03-17 23:50:16 +00004215 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004216 return false;
4217 }
4218
4219 // if wback then R[n] = R[n] - 4*BitCount(registers);
4220 if (wback)
4221 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004222 offset = (addr_byte_size * BitCount (registers)) * -1;
4223 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4224 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004225 addr_t data = Rn + offset;
Caroline Ticeaf556562011-02-15 18:42:15 +00004226 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4227 return false;
4228 }
4229 }
4230 return true;
4231}
4232
4233// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4234// from a base register. The consecutive memory locations start just above this address, and the address of the last
4235// of those locations can optionally be written back to the base register.
4236bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004237EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeaf556562011-02-15 18:42:15 +00004238{
4239#if 0
4240 if ConditionPassed() then
4241 EncodingSpecificOperations();
4242 address = R[n] + 4;
4243
4244 for i = 0 to 14
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004245 if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004246 if i == n && wback && i != LowestSetBit(registers) then
4247 MemA[address,4] = bits(32) UNKNOWN;
4248 else
4249 MemA[address,4] = R[i];
4250 address = address + 4;
4251
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004252 if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004253 MemA[address,4] = PCStoreValue();
4254
4255 if wback then R[n] = R[n] + 4*BitCount(registers);
4256#endif
4257
4258 bool success = false;
Caroline Ticeaf556562011-02-15 18:42:15 +00004259
Greg Clayton7bc39082011-03-24 23:53:38 +00004260 if (ConditionPassed(opcode))
Caroline Ticeaf556562011-02-15 18:42:15 +00004261 {
4262 uint32_t n;
4263 uint32_t registers = 0;
4264 bool wback;
4265 const uint32_t addr_byte_size = GetAddressByteSize();
4266
4267 // EncodingSpecificOperations();
4268 switch (encoding)
4269 {
4270 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004271 // n = UInt(Rn); registers = register_list; wback = (W == '1');
Caroline Ticeaf556562011-02-15 18:42:15 +00004272 n = Bits32 (opcode, 19, 16);
4273 registers = Bits32 (opcode, 15, 0);
4274 wback = BitIsSet (opcode, 21);
4275
4276 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4277 if ((n == 15) && (BitCount (registers) < 1))
4278 return false;
4279 break;
4280 default:
4281 return false;
4282 }
4283 // address = R[n] + 4;
4284
4285 int32_t offset = 0;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004286 addr_t Rn = ReadCoreReg (n, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004287 if (!success)
4288 return false;
4289
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004290 addr_t address = Rn + addr_byte_size;
Caroline Ticeaf556562011-02-15 18:42:15 +00004291
4292 EmulateInstruction::Context context;
4293 context.type = EmulateInstruction::eContextRegisterStore;
4294 Register base_reg;
4295 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4296
4297 uint32_t lowest_set_bit = 14;
4298 // for i = 0 to 14
4299 for (int i = 0; i < 14; ++i)
4300 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004301 // if registers<i> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004302 if (BitIsSet (registers, i))
4303 {
4304 if (i < lowest_set_bit)
4305 lowest_set_bit = i;
4306 // if i == n && wback && i != LowestSetBit(registers) then
4307 if ((i == n) && wback && (i != lowest_set_bit))
4308 // MemA[address,4] = bits(32) UNKNOWN;
4309 WriteBits32UnknownToMemory (address + offset);
4310 // else
4311 else
4312 {
4313 // MemA[address,4] = R[i];
4314 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4315 if (!success)
4316 return false;
4317
4318 Register data_reg;
4319 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004320 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004321 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004322 return false;
4323 }
4324
4325 // address = address + 4;
4326 offset += addr_byte_size;
4327 }
4328 }
4329
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004330 // if registers<15> == '1' then
Caroline Ticeaf556562011-02-15 18:42:15 +00004331 // MemA[address,4] = PCStoreValue();
4332 if (BitIsSet (registers, 15))
4333 {
4334 Register pc_reg;
4335 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4336 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004337 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004338 if (!success)
4339 return false;
4340
Caroline Tice8d681f52011-03-17 23:50:16 +00004341 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004342 return false;
4343 }
4344
4345 // if wback then R[n] = R[n] + 4*BitCount(registers);
4346 if (wback)
4347 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004348 offset = addr_byte_size * BitCount (registers);
4349 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4350 context.SetImmediateSigned (offset);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004351 addr_t data = Rn + offset;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004352 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4353 return false;
4354 }
4355 }
4356 return true;
4357}
Caroline Tice7fac8572011-02-15 22:53:54 +00004358
4359// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4360// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4361bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004362EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice7fac8572011-02-15 22:53:54 +00004363{
4364#if 0
4365 if ConditionPassed() then
4366 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4367 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4368 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004369 if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004370 MemU[address,4] = R[t];
4371 else // Can only occur before ARMv7
4372 MemU[address,4] = bits(32) UNKNOWN;
4373 if wback then R[n] = offset_addr;
4374#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004375
Caroline Tice7fac8572011-02-15 22:53:54 +00004376 bool success = false;
Caroline Tice7fac8572011-02-15 22:53:54 +00004377
Greg Clayton7bc39082011-03-24 23:53:38 +00004378 if (ConditionPassed(opcode))
Caroline Tice7fac8572011-02-15 22:53:54 +00004379 {
4380 const uint32_t addr_byte_size = GetAddressByteSize();
4381
4382 uint32_t t;
4383 uint32_t n;
4384 uint32_t imm32;
4385 bool index;
4386 bool add;
4387 bool wback;
4388 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4389 switch (encoding)
4390 {
4391 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004392 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004393 t = Bits32 (opcode, 2, 0);
4394 n = Bits32 (opcode, 5, 3);
4395 imm32 = Bits32 (opcode, 10, 6) << 2;
4396
4397 // index = TRUE; add = TRUE; wback = FALSE;
4398 index = true;
4399 add = false;
4400 wback = false;
4401 break;
4402
4403 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004404 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
Caroline Tice7fac8572011-02-15 22:53:54 +00004405 t = Bits32 (opcode, 10, 8);
4406 n = 13;
4407 imm32 = Bits32 (opcode, 7, 0) << 2;
4408
4409 // index = TRUE; add = TRUE; wback = FALSE;
4410 index = true;
4411 add = true;
4412 wback = false;
4413 break;
4414
4415 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004416 // if Rn == '1111' then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004417 if (Bits32 (opcode, 19, 16) == 15)
4418 return false;
4419
4420 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4421 t = Bits32 (opcode, 15, 12);
4422 n = Bits32 (opcode, 19, 16);
4423 imm32 = Bits32 (opcode, 11, 0);
4424
4425 // index = TRUE; add = TRUE; wback = FALSE;
4426 index = true;
4427 add = true;
4428 wback = false;
4429
4430 // if t == 15 then UNPREDICTABLE;
4431 if (t == 15)
4432 return false;
4433 break;
4434
4435 case eEncodingT4:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004436 // if P == '1' && U == '1' && W == '0' then SEE STRT;
4437 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
4438 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice7fac8572011-02-15 22:53:54 +00004439 if ((Bits32 (opcode, 19, 16) == 15)
4440 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4441 return false;
4442
4443 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4444 t = Bits32 (opcode, 15, 12);
4445 n = Bits32 (opcode, 19, 16);
4446 imm32 = Bits32 (opcode, 7, 0);
4447
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004448 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice7fac8572011-02-15 22:53:54 +00004449 index = BitIsSet (opcode, 10);
4450 add = BitIsSet (opcode, 9);
4451 wback = BitIsSet (opcode, 8);
4452
4453 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4454 if ((t == 15) || (wback && (n == t)))
4455 return false;
4456 break;
4457
4458 default:
4459 return false;
4460 }
4461
4462 addr_t offset_addr;
4463 addr_t address;
4464
4465 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
Caroline Ticebaf1f642011-03-24 19:23:45 +00004466 uint32_t base_address = ReadCoreReg (n, &success);
Caroline Tice7fac8572011-02-15 22:53:54 +00004467 if (!success)
4468 return false;
4469
4470 if (add)
4471 offset_addr = base_address + imm32;
4472 else
4473 offset_addr = base_address - imm32;
4474
4475 // address = if index then offset_addr else R[n];
4476 if (index)
4477 address = offset_addr;
4478 else
4479 address = base_address;
4480
4481 EmulateInstruction::Context context;
4482 context.type = eContextRegisterStore;
4483 Register base_reg;
4484 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4485
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004486 // if UnalignedSupport() || address<1:0> == '00' then
Caroline Tice7fac8572011-02-15 22:53:54 +00004487 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4488 {
4489 // MemU[address,4] = R[t];
4490 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4491 if (!success)
4492 return false;
4493
4494 Register data_reg;
4495 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4496 int32_t offset = address - base_address;
4497 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004498 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004499 return false;
4500 }
4501 else
4502 {
4503 // MemU[address,4] = bits(32) UNKNOWN;
4504 WriteBits32UnknownToMemory (address);
4505 }
4506
4507 // if wback then R[n] = offset_addr;
4508 if (wback)
4509 {
4510 context.type = eContextRegisterLoad;
4511 context.SetAddress (offset_addr);
4512 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4513 return false;
4514 }
4515 }
4516 return true;
4517}
Caroline Ticeaf556562011-02-15 18:42:15 +00004518
Caroline Tice3fd63e92011-02-16 00:33:43 +00004519// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4520// word from a register to memory. The offset register value can optionally be shifted.
4521bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004522EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice3fd63e92011-02-16 00:33:43 +00004523{
4524#if 0
4525 if ConditionPassed() then
4526 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4527 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4528 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4529 address = if index then offset_addr else R[n];
4530 if t == 15 then // Only possible for encoding A1
4531 data = PCStoreValue();
4532 else
4533 data = R[t];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004534 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004535 MemU[address,4] = data;
4536 else // Can only occur before ARMv7
4537 MemU[address,4] = bits(32) UNKNOWN;
4538 if wback then R[n] = offset_addr;
4539#endif
4540
4541 bool success = false;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004542
Greg Clayton7bc39082011-03-24 23:53:38 +00004543 if (ConditionPassed(opcode))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004544 {
4545 const uint32_t addr_byte_size = GetAddressByteSize();
4546
4547 uint32_t t;
4548 uint32_t n;
4549 uint32_t m;
4550 ARM_ShifterType shift_t;
4551 uint32_t shift_n;
4552 bool index;
4553 bool add;
4554 bool wback;
4555
4556 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4557 switch (encoding)
4558 {
4559 case eEncodingT1:
4560 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4561 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4562 t = Bits32 (opcode, 2, 0);
4563 n = Bits32 (opcode, 5, 3);
4564 m = Bits32 (opcode, 8, 6);
4565
4566 // index = TRUE; add = TRUE; wback = FALSE;
4567 index = true;
4568 add = true;
4569 wback = false;
4570
4571 // (shift_t, shift_n) = (SRType_LSL, 0);
4572 shift_t = SRType_LSL;
4573 shift_n = 0;
4574 break;
4575
4576 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004577 // if Rn == '1111' then UNDEFINED;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004578 if (Bits32 (opcode, 19, 16) == 15)
4579 return false;
4580
4581 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4582 t = Bits32 (opcode, 15, 12);
4583 n = Bits32 (opcode, 19, 16);
4584 m = Bits32 (opcode, 3, 0);
4585
4586 // index = TRUE; add = TRUE; wback = FALSE;
4587 index = true;
4588 add = true;
4589 wback = false;
4590
4591 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4592 shift_t = SRType_LSL;
4593 shift_n = Bits32 (opcode, 5, 4);
4594
4595 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4596 if ((t == 15) || (BadReg (m)))
4597 return false;
4598 break;
4599
4600 case eEncodingA1:
4601 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004602 // if P == '0' && W == '1' then SEE STRT;
Caroline Tice3fd63e92011-02-16 00:33:43 +00004603 // 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
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004608 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice3fd63e92011-02-16 00:33:43 +00004609 index = BitIsSet (opcode, 24);
4610 add = BitIsSet (opcode, 23);
4611 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4612
4613 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4614 uint32_t typ = Bits32 (opcode, 6, 5);
4615 uint32_t imm5 = Bits32 (opcode, 11, 7);
4616 shift_n = DecodeImmShift(typ, imm5, shift_t);
4617
4618 // if m == 15 then UNPREDICTABLE;
4619 if (m == 15)
4620 return false;
4621
4622 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4623 if (wback && ((n == 15) || (n == t)))
4624 return false;
4625
4626 break;
4627 }
4628 default:
4629 return false;
4630 }
4631
4632 addr_t offset_addr;
4633 addr_t address;
4634 int32_t offset = 0;
4635
4636 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4637 if (!success)
4638 return false;
4639
4640 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4641 if (!success)
4642 return false;
4643
4644 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004645 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004646
4647 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4648 if (add)
4649 offset_addr = base_address + offset;
4650 else
4651 offset_addr = base_address - offset;
4652
4653 // address = if index then offset_addr else R[n];
4654 if (index)
4655 address = offset_addr;
4656 else
4657 address = base_address;
4658
4659 uint32_t data;
4660 // if t == 15 then // Only possible for encoding A1
4661 if (t == 15)
4662 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004663 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004664 else
4665 // data = R[t];
4666 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4667
4668 if (!success)
4669 return false;
4670
4671 EmulateInstruction::Context context;
4672 context.type = eContextRegisterStore;
4673
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004674 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
Caroline Tice3fd63e92011-02-16 00:33:43 +00004675 if (UnalignedSupport ()
4676 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4677 || CurrentInstrSet() == eModeARM)
4678 {
4679 // MemU[address,4] = data;
4680
4681 Register base_reg;
4682 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4683
4684 Register data_reg;
4685 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4686
4687 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004688 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004689 return false;
4690
4691 }
4692 else
4693 // MemU[address,4] = bits(32) UNKNOWN;
4694 WriteBits32UnknownToMemory (address);
4695
4696 // if wback then R[n] = offset_addr;
4697 if (wback)
4698 {
4699 context.type = eContextRegisterLoad;
4700 context.SetAddress (offset_addr);
4701 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4702 return false;
4703 }
4704
4705 }
4706 return true;
4707}
Caroline Tice73a29de2011-02-16 20:22:22 +00004708
4709bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004710EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice73a29de2011-02-16 20:22:22 +00004711{
4712#if 0
4713 if ConditionPassed() then
4714 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4715 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4716 address = if index then offset_addr else R[n];
4717 MemU[address,1] = R[t]<7:0>;
4718 if wback then R[n] = offset_addr;
4719#endif
4720
4721
4722 bool success = false;
Caroline Tice73a29de2011-02-16 20:22:22 +00004723
Greg Clayton7bc39082011-03-24 23:53:38 +00004724 if (ConditionPassed(opcode))
Caroline Tice73a29de2011-02-16 20:22:22 +00004725 {
4726 uint32_t t;
4727 uint32_t n;
4728 uint32_t imm32;
4729 bool index;
4730 bool add;
4731 bool wback;
4732 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4733 switch (encoding)
4734 {
4735 case eEncodingT1:
4736 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4737 t = Bits32 (opcode, 2, 0);
4738 n = Bits32 (opcode, 5, 3);
4739 imm32 = Bits32 (opcode, 10, 6);
4740
4741 // index = TRUE; add = TRUE; wback = FALSE;
4742 index = true;
4743 add = true;
4744 wback = false;
4745 break;
4746
4747 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004748 // if Rn == '1111' then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004749 if (Bits32 (opcode, 19, 16) == 15)
4750 return false;
4751
4752 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4753 t = Bits32 (opcode, 15, 12);
4754 n = Bits32 (opcode, 19, 16);
4755 imm32 = Bits32 (opcode, 11, 0);
4756
4757 // index = TRUE; add = TRUE; wback = FALSE;
4758 index = true;
4759 add = true;
4760 wback = false;
4761
4762 // if BadReg(t) then UNPREDICTABLE;
4763 if (BadReg (t))
4764 return false;
4765 break;
4766
4767 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004768 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
4769 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
Caroline Tice73a29de2011-02-16 20:22:22 +00004770 if (Bits32 (opcode, 19, 16) == 15)
4771 return false;
4772
4773 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4774 t = Bits32 (opcode, 15, 12);
4775 n = Bits32 (opcode, 19, 16);
4776 imm32 = Bits32 (opcode, 7, 0);
4777
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004778 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice73a29de2011-02-16 20:22:22 +00004779 index = BitIsSet (opcode, 10);
4780 add = BitIsSet (opcode, 9);
4781 wback = BitIsSet (opcode, 8);
4782
4783 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4784 if ((BadReg (t)) || (wback && (n == t)))
4785 return false;
4786 break;
4787
4788 default:
4789 return false;
4790 }
4791
4792 addr_t offset_addr;
4793 addr_t address;
4794 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4795 if (!success)
4796 return false;
4797
4798 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4799 if (add)
4800 offset_addr = base_address + imm32;
4801 else
4802 offset_addr = base_address - imm32;
4803
4804 // address = if index then offset_addr else R[n];
4805 if (index)
4806 address = offset_addr;
4807 else
4808 address = base_address;
4809
Caroline Ticecc96eb52011-02-17 19:20:40 +00004810 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004811 Register base_reg;
4812 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4813
4814 Register data_reg;
4815 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4816
4817 EmulateInstruction::Context context;
4818 context.type = eContextRegisterStore;
4819 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4820
4821 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4822 if (!success)
4823 return false;
4824
4825 data = Bits32 (data, 7, 0);
4826
Caroline Ticecc96eb52011-02-17 19:20:40 +00004827 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004828 return false;
4829
4830 // if wback then R[n] = offset_addr;
4831 if (wback)
4832 {
4833 context.type = eContextRegisterLoad;
4834 context.SetAddress (offset_addr);
4835 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4836 return false;
4837 }
4838
4839 }
4840
4841 return true;
4842}
Caroline Tice8ce836d2011-03-16 22:46:55 +00004843
4844// STRH (register) calculates an address from a base register value and an offset register value, and stores a
4845// halfword from a register to memory. The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
4846bool
Greg Clayton7bc39082011-03-24 23:53:38 +00004847EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce836d2011-03-16 22:46:55 +00004848{
4849#if 0
4850 if ConditionPassed() then
4851 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4852 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4853 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4854 address = if index then offset_addr else R[n];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004855 if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004856 MemU[address,2] = R[t]<15:0>;
4857 else // Can only occur before ARMv7
4858 MemU[address,2] = bits(16) UNKNOWN;
4859 if wback then R[n] = offset_addr;
4860#endif
4861
4862 bool success = false;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004863
Greg Clayton7bc39082011-03-24 23:53:38 +00004864 if (ConditionPassed(opcode))
Caroline Tice8ce836d2011-03-16 22:46:55 +00004865 {
4866 uint32_t t;
4867 uint32_t n;
4868 uint32_t m;
4869 bool index;
4870 bool add;
4871 bool wback;
4872 ARM_ShifterType shift_t;
4873 uint32_t shift_n;
4874
4875 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4876 switch (encoding)
4877 {
4878 case eEncodingT1:
4879 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4880 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4881 t = Bits32 (opcode, 2, 0);
4882 n = Bits32 (opcode, 5, 3);
4883 m = Bits32 (opcode, 8, 6);
4884
4885 // index = TRUE; add = TRUE; wback = FALSE;
4886 index = true;
4887 add = true;
4888 wback = false;
4889
4890 // (shift_t, shift_n) = (SRType_LSL, 0);
4891 shift_t = SRType_LSL;
4892 shift_n = 0;
4893
4894 break;
4895
4896 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004897 // if Rn == '1111' then UNDEFINED;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004898 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4899 t = Bits32 (opcode, 15, 12);
4900 n = Bits32 (opcode, 19, 16);
4901 m = Bits32 (opcode, 3, 0);
4902 if (n == 15)
4903 return false;
4904
4905 // index = TRUE; add = TRUE; wback = FALSE;
4906 index = true;
4907 add = true;
4908 wback = false;
4909
4910 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4911 shift_t = SRType_LSL;
4912 shift_n = Bits32 (opcode, 5, 4);
4913
4914 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4915 if (BadReg (t) || BadReg (m))
4916 return false;
4917
4918 break;
4919
4920 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004921 // if P == '0' && W == '1' then SEE STRHT;
Caroline Tice8ce836d2011-03-16 22:46:55 +00004922 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4923 t = Bits32 (opcode, 15, 12);
4924 n = Bits32 (opcode, 19, 16);
4925 m = Bits32 (opcode, 3, 0);
4926
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004927 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice8ce836d2011-03-16 22:46:55 +00004928 index = BitIsSet (opcode, 24);
4929 add = BitIsSet (opcode, 23);
4930 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4931
4932 // (shift_t, shift_n) = (SRType_LSL, 0);
4933 shift_t = SRType_LSL;
4934 shift_n = 0;
4935
4936 // if t == 15 || m == 15 then UNPREDICTABLE;
4937 if ((t == 15) || (m == 15))
4938 return false;
4939
4940 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4941 if (wback && ((n == 15) || (n == t)))
4942 return false;
4943
4944 break;
4945
4946 default:
4947 return false;
4948 }
4949
4950 uint32_t Rm = ReadCoreReg (m, &success);
4951 if (!success)
4952 return false;
4953
4954 uint32_t Rn = ReadCoreReg (n, &success);
4955 if (!success)
4956 return false;
4957
4958 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4959 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
4960
4961 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4962 addr_t offset_addr;
4963 if (add)
4964 offset_addr = Rn + offset;
4965 else
4966 offset_addr = Rn - offset;
4967
4968 // address = if index then offset_addr else R[n];
4969 addr_t address;
4970 if (index)
4971 address = offset_addr;
4972 else
4973 address = Rn;
4974
4975 EmulateInstruction::Context context;
4976 context.type = eContextRegisterStore;
4977 Register base_reg;
4978 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4979 Register offset_reg;
4980 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4981
Caroline Ticebb48f0b2011-03-28 16:10:45 +00004982 // if UnalignedSupport() || address<0> == '0' then
Caroline Tice8ce836d2011-03-16 22:46:55 +00004983 if (UnalignedSupport() || BitIsClear (address, 0))
4984 {
4985 // MemU[address,2] = R[t]<15:0>;
4986 uint32_t Rt = ReadCoreReg (t, &success);
4987 if (!success)
4988 return false;
4989
4990 EmulateInstruction::Context context;
4991 context.type = eContextRegisterStore;
4992 Register base_reg;
4993 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4994 Register offset_reg;
4995 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4996 Register data_reg;
4997 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4998 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
4999
5000 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5001 return false;
5002 }
5003 else // Can only occur before ARMv7
5004 {
5005 // MemU[address,2] = bits(16) UNKNOWN;
5006 }
5007
5008 // if wback then R[n] = offset_addr;
5009 if (wback)
5010 {
5011 context.type = eContextAdjustBaseRegister;
5012 context.SetAddress (offset_addr);
5013 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5014 return false;
5015 }
5016 }
5017
5018 return true;
5019}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005020
Johnny Chen157b9592011-02-18 21:13:05 +00005021// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5022// and writes the result to the destination register. It can optionally update the condition flags
5023// based on the result.
5024bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005025EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005026{
5027#if 0
5028 // ARM pseudo code...
5029 if ConditionPassed() then
5030 EncodingSpecificOperations();
5031 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5032 if d == 15 then // Can only occur for ARM encoding
5033 ALUWritePC(result); // setflags is always FALSE here
5034 else
5035 R[d] = result;
5036 if setflags then
5037 APSR.N = result<31>;
5038 APSR.Z = IsZeroBit(result);
5039 APSR.C = carry;
5040 APSR.V = overflow;
5041#endif
5042
5043 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005044
Greg Clayton7bc39082011-03-24 23:53:38 +00005045 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005046 {
5047 uint32_t Rd, Rn;
5048 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5049 bool setflags;
5050 switch (encoding)
5051 {
5052 case eEncodingT1:
5053 Rd = Bits32(opcode, 11, 8);
5054 Rn = Bits32(opcode, 19, 16);
5055 setflags = BitIsSet(opcode, 20);
5056 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5057 if (BadReg(Rd) || BadReg(Rn))
5058 return false;
5059 break;
5060 case eEncodingA1:
5061 Rd = Bits32(opcode, 15, 12);
5062 Rn = Bits32(opcode, 19, 16);
5063 setflags = BitIsSet(opcode, 20);
5064 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5065 // TODO: Emulate SUBS PC, LR and related instructions.
5066 if (Rd == 15 && setflags)
5067 return false;
5068 break;
5069 default:
5070 return false;
5071 }
5072
5073 // Read the first operand.
5074 int32_t val1 = ReadCoreReg(Rn, &success);
5075 if (!success)
5076 return false;
5077
5078 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5079
5080 EmulateInstruction::Context context;
5081 context.type = EmulateInstruction::eContextImmediate;
5082 context.SetNoArgs ();
5083
5084 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5085 return false;
5086 }
5087 return true;
5088}
5089
5090// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5091// register value, and writes the result to the destination register. It can optionally update the
5092// condition flags based on the result.
5093bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005094EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen157b9592011-02-18 21:13:05 +00005095{
5096#if 0
5097 // ARM pseudo code...
5098 if ConditionPassed() then
5099 EncodingSpecificOperations();
5100 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5101 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5102 if d == 15 then // Can only occur for ARM encoding
5103 ALUWritePC(result); // setflags is always FALSE here
5104 else
5105 R[d] = result;
5106 if setflags then
5107 APSR.N = result<31>;
5108 APSR.Z = IsZeroBit(result);
5109 APSR.C = carry;
5110 APSR.V = overflow;
5111#endif
5112
5113 bool success = false;
Johnny Chen157b9592011-02-18 21:13:05 +00005114
Greg Clayton7bc39082011-03-24 23:53:38 +00005115 if (ConditionPassed(opcode))
Johnny Chen157b9592011-02-18 21:13:05 +00005116 {
5117 uint32_t Rd, Rn, Rm;
5118 ARM_ShifterType shift_t;
5119 uint32_t shift_n; // the shift applied to the value read from Rm
5120 bool setflags;
5121 switch (encoding)
5122 {
5123 case eEncodingT1:
5124 Rd = Rn = Bits32(opcode, 2, 0);
5125 Rm = Bits32(opcode, 5, 3);
5126 setflags = !InITBlock();
5127 shift_t = SRType_LSL;
5128 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005129 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005130 case eEncodingT2:
5131 Rd = Bits32(opcode, 11, 8);
5132 Rn = Bits32(opcode, 19, 16);
5133 Rm = Bits32(opcode, 3, 0);
5134 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005135 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005136 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5137 return false;
5138 break;
5139 case eEncodingA1:
5140 Rd = Bits32(opcode, 15, 12);
5141 Rn = Bits32(opcode, 19, 16);
5142 Rm = Bits32(opcode, 3, 0);
5143 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005144 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005145 // TODO: Emulate SUBS PC, LR and related instructions.
5146 if (Rd == 15 && setflags)
5147 return false;
5148 break;
5149 default:
5150 return false;
5151 }
5152
5153 // Read the first operand.
5154 int32_t val1 = ReadCoreReg(Rn, &success);
5155 if (!success)
5156 return false;
5157
5158 // Read the second operand.
5159 int32_t val2 = ReadCoreReg(Rm, &success);
5160 if (!success)
5161 return false;
5162
5163 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5164 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5165
5166 EmulateInstruction::Context context;
5167 context.type = EmulateInstruction::eContextImmediate;
5168 context.SetNoArgs ();
5169
5170 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5171 return false;
5172 }
5173 return true;
5174}
5175
Johnny Chena695f952011-02-23 21:24:25 +00005176// This instruction adds an immediate value to the PC value to form a PC-relative address,
5177// and writes the result to the destination register.
5178bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005179EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chena695f952011-02-23 21:24:25 +00005180{
5181#if 0
5182 // ARM pseudo code...
5183 if ConditionPassed() then
5184 EncodingSpecificOperations();
5185 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5186 if d == 15 then // Can only occur for ARM encodings
5187 ALUWritePC(result);
5188 else
5189 R[d] = result;
5190#endif
5191
5192 bool success = false;
Johnny Chena695f952011-02-23 21:24:25 +00005193
Greg Clayton7bc39082011-03-24 23:53:38 +00005194 if (ConditionPassed(opcode))
Johnny Chena695f952011-02-23 21:24:25 +00005195 {
5196 uint32_t Rd;
5197 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5198 bool add;
5199 switch (encoding)
5200 {
5201 case eEncodingT1:
5202 Rd = Bits32(opcode, 10, 8);
5203 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5204 break;
5205 case eEncodingT2:
5206 case eEncodingT3:
5207 Rd = Bits32(opcode, 11, 8);
5208 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5209 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5210 if (BadReg(Rd))
5211 return false;
5212 break;
5213 case eEncodingA1:
5214 case eEncodingA2:
5215 Rd = Bits32(opcode, 15, 12);
5216 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5217 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5218 break;
5219 default:
5220 return false;
5221 }
5222
5223 // Read the PC value.
5224 uint32_t pc = ReadCoreReg(PC_REG, &success);
5225 if (!success)
5226 return false;
5227
5228 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5229
5230 EmulateInstruction::Context context;
5231 context.type = EmulateInstruction::eContextImmediate;
5232 context.SetNoArgs ();
5233
5234 if (!WriteCoreReg(context, result, Rd))
5235 return false;
5236 }
5237 return true;
5238}
5239
Johnny Chene97c0d52011-02-18 19:32:20 +00005240// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5241// to the destination register. It can optionally update the condition flags based on the result.
5242bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005243EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005244{
5245#if 0
5246 // ARM pseudo code...
5247 if ConditionPassed() then
5248 EncodingSpecificOperations();
5249 result = R[n] AND imm32;
5250 if d == 15 then // Can only occur for ARM encoding
5251 ALUWritePC(result); // setflags is always FALSE here
5252 else
5253 R[d] = result;
5254 if setflags then
5255 APSR.N = result<31>;
5256 APSR.Z = IsZeroBit(result);
5257 APSR.C = carry;
5258 // APSR.V unchanged
5259#endif
5260
5261 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005262
Greg Clayton7bc39082011-03-24 23:53:38 +00005263 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005264 {
5265 uint32_t Rd, Rn;
5266 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5267 bool setflags;
5268 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5269 switch (encoding)
5270 {
5271 case eEncodingT1:
5272 Rd = Bits32(opcode, 11, 8);
5273 Rn = Bits32(opcode, 19, 16);
5274 setflags = BitIsSet(opcode, 20);
5275 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005276 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005277 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005278 return EmulateTSTImm(opcode, eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005279 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5280 return false;
5281 break;
5282 case eEncodingA1:
5283 Rd = Bits32(opcode, 15, 12);
5284 Rn = Bits32(opcode, 19, 16);
5285 setflags = BitIsSet(opcode, 20);
5286 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5287 // TODO: Emulate SUBS PC, LR and related instructions.
5288 if (Rd == 15 && setflags)
5289 return false;
5290 break;
5291 default:
5292 return false;
5293 }
5294
Johnny Chene97c0d52011-02-18 19:32:20 +00005295 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005296 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005297 if (!success)
5298 return false;
5299
5300 uint32_t result = val1 & imm32;
5301
5302 EmulateInstruction::Context context;
5303 context.type = EmulateInstruction::eContextImmediate;
5304 context.SetNoArgs ();
5305
5306 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5307 return false;
5308 }
5309 return true;
5310}
5311
5312// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5313// and writes the result to the destination register. It can optionally update the condition flags
5314// based on the result.
5315bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005316EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chene97c0d52011-02-18 19:32:20 +00005317{
5318#if 0
5319 // ARM pseudo code...
5320 if ConditionPassed() then
5321 EncodingSpecificOperations();
5322 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5323 result = R[n] AND shifted;
5324 if d == 15 then // Can only occur for ARM encoding
5325 ALUWritePC(result); // setflags is always FALSE here
5326 else
5327 R[d] = result;
5328 if setflags then
5329 APSR.N = result<31>;
5330 APSR.Z = IsZeroBit(result);
5331 APSR.C = carry;
5332 // APSR.V unchanged
5333#endif
5334
5335 bool success = false;
Johnny Chene97c0d52011-02-18 19:32:20 +00005336
Greg Clayton7bc39082011-03-24 23:53:38 +00005337 if (ConditionPassed(opcode))
Johnny Chene97c0d52011-02-18 19:32:20 +00005338 {
5339 uint32_t Rd, Rn, Rm;
5340 ARM_ShifterType shift_t;
5341 uint32_t shift_n; // the shift applied to the value read from Rm
5342 bool setflags;
5343 uint32_t carry;
5344 switch (encoding)
5345 {
5346 case eEncodingT1:
5347 Rd = Rn = Bits32(opcode, 2, 0);
5348 Rm = Bits32(opcode, 5, 3);
5349 setflags = !InITBlock();
5350 shift_t = SRType_LSL;
5351 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005352 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005353 case eEncodingT2:
5354 Rd = Bits32(opcode, 11, 8);
5355 Rn = Bits32(opcode, 19, 16);
5356 Rm = Bits32(opcode, 3, 0);
5357 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005358 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005359 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005360 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00005361 return EmulateTSTReg(opcode, eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005362 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5363 return false;
5364 break;
5365 case eEncodingA1:
5366 Rd = Bits32(opcode, 15, 12);
5367 Rn = Bits32(opcode, 19, 16);
5368 Rm = Bits32(opcode, 3, 0);
5369 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005370 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005371 // TODO: Emulate SUBS PC, LR and related instructions.
5372 if (Rd == 15 && setflags)
5373 return false;
5374 break;
5375 default:
5376 return false;
5377 }
5378
Johnny Chene97c0d52011-02-18 19:32:20 +00005379 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005380 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005381 if (!success)
5382 return false;
5383
5384 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005385 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005386 if (!success)
5387 return false;
5388
5389 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5390 uint32_t result = val1 & shifted;
5391
5392 EmulateInstruction::Context context;
5393 context.type = EmulateInstruction::eContextImmediate;
5394 context.SetNoArgs ();
5395
5396 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5397 return false;
5398 }
5399 return true;
5400}
5401
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005402// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5403// immediate value, and writes the result to the destination register. It can optionally update the
5404// condition flags based on the result.
5405bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005406EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005407{
5408#if 0
5409 // ARM pseudo code...
5410 if ConditionPassed() then
5411 EncodingSpecificOperations();
5412 result = R[n] AND NOT(imm32);
5413 if d == 15 then // Can only occur for ARM encoding
5414 ALUWritePC(result); // setflags is always FALSE here
5415 else
5416 R[d] = result;
5417 if setflags then
5418 APSR.N = result<31>;
5419 APSR.Z = IsZeroBit(result);
5420 APSR.C = carry;
5421 // APSR.V unchanged
5422#endif
5423
5424 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005425
Greg Clayton7bc39082011-03-24 23:53:38 +00005426 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005427 {
5428 uint32_t Rd, Rn;
5429 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5430 bool setflags;
5431 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5432 switch (encoding)
5433 {
5434 case eEncodingT1:
5435 Rd = Bits32(opcode, 11, 8);
5436 Rn = Bits32(opcode, 19, 16);
5437 setflags = BitIsSet(opcode, 20);
5438 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5439 if (BadReg(Rd) || BadReg(Rn))
5440 return false;
5441 break;
5442 case eEncodingA1:
5443 Rd = Bits32(opcode, 15, 12);
5444 Rn = Bits32(opcode, 19, 16);
5445 setflags = BitIsSet(opcode, 20);
5446 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005447 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005448 // TODO: Emulate SUBS PC, LR and related instructions.
5449 if (Rd == 15 && setflags)
5450 return false;
5451 break;
5452 default:
5453 return false;
5454 }
5455
5456 // Read the first operand.
5457 uint32_t val1 = ReadCoreReg(Rn, &success);
5458 if (!success)
5459 return false;
5460
5461 uint32_t result = val1 & ~imm32;
5462
5463 EmulateInstruction::Context context;
5464 context.type = EmulateInstruction::eContextImmediate;
5465 context.SetNoArgs ();
5466
5467 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5468 return false;
5469 }
5470 return true;
5471}
5472
5473// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5474// optionally-shifted register value, and writes the result to the destination register.
5475// It can optionally update the condition flags based on the result.
5476bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005477EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005478{
5479#if 0
5480 // ARM pseudo code...
5481 if ConditionPassed() then
5482 EncodingSpecificOperations();
5483 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5484 result = R[n] AND NOT(shifted);
5485 if d == 15 then // Can only occur for ARM encoding
5486 ALUWritePC(result); // setflags is always FALSE here
5487 else
5488 R[d] = result;
5489 if setflags then
5490 APSR.N = result<31>;
5491 APSR.Z = IsZeroBit(result);
5492 APSR.C = carry;
5493 // APSR.V unchanged
5494#endif
5495
5496 bool success = false;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005497
Greg Clayton7bc39082011-03-24 23:53:38 +00005498 if (ConditionPassed(opcode))
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005499 {
5500 uint32_t Rd, Rn, Rm;
5501 ARM_ShifterType shift_t;
5502 uint32_t shift_n; // the shift applied to the value read from Rm
5503 bool setflags;
5504 uint32_t carry;
5505 switch (encoding)
5506 {
5507 case eEncodingT1:
5508 Rd = Rn = Bits32(opcode, 2, 0);
5509 Rm = Bits32(opcode, 5, 3);
5510 setflags = !InITBlock();
5511 shift_t = SRType_LSL;
5512 shift_n = 0;
5513 break;
5514 case eEncodingT2:
5515 Rd = Bits32(opcode, 11, 8);
5516 Rn = Bits32(opcode, 19, 16);
5517 Rm = Bits32(opcode, 3, 0);
5518 setflags = BitIsSet(opcode, 20);
5519 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5520 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5521 return false;
5522 break;
5523 case eEncodingA1:
5524 Rd = Bits32(opcode, 15, 12);
5525 Rn = Bits32(opcode, 19, 16);
5526 Rm = Bits32(opcode, 3, 0);
5527 setflags = BitIsSet(opcode, 20);
5528 shift_n = DecodeImmShiftARM(opcode, shift_t);
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005529 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005530 // TODO: Emulate SUBS PC, LR and related instructions.
5531 if (Rd == 15 && setflags)
5532 return false;
5533 break;
5534 default:
5535 return false;
5536 }
5537
5538 // Read the first operand.
5539 uint32_t val1 = ReadCoreReg(Rn, &success);
5540 if (!success)
5541 return false;
5542
5543 // Read the second operand.
5544 uint32_t val2 = ReadCoreReg(Rm, &success);
5545 if (!success)
5546 return false;
5547
5548 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5549 uint32_t result = val1 & ~shifted;
5550
5551 EmulateInstruction::Context context;
5552 context.type = EmulateInstruction::eContextImmediate;
5553 context.SetNoArgs ();
5554
5555 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5556 return false;
5557 }
5558 return true;
5559}
5560
Caroline Tice4d729c52011-02-18 00:55:53 +00005561// 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 +00005562// 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 +00005563bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005564EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice4d729c52011-02-18 00:55:53 +00005565{
5566#if 0
5567 if ConditionPassed() then
5568 EncodingSpecificOperations();
5569 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5570 address = if index then offset_addr else R[n];
5571 data = MemU[address,4];
5572 if wback then R[n] = offset_addr;
5573 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005574 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5575 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005576 R[t] = data;
5577 else // Can only apply before ARMv7
5578 R[t] = ROR(data, 8*UInt(address<1:0>));
5579#endif
5580
5581 bool success = false;
Caroline Tice4d729c52011-02-18 00:55:53 +00005582
Greg Clayton7bc39082011-03-24 23:53:38 +00005583 if (ConditionPassed(opcode))
Caroline Tice4d729c52011-02-18 00:55:53 +00005584 {
5585 const uint32_t addr_byte_size = GetAddressByteSize();
5586
5587 uint32_t t;
5588 uint32_t n;
5589 uint32_t imm32;
5590 bool index;
5591 bool add;
5592 bool wback;
5593
5594 switch (encoding)
5595 {
5596 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005597 // if Rn == '1111' then SEE LDR (literal);
5598 // if P == '0' && W == '1' then SEE LDRT;
5599 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP;
Caroline Tice4d729c52011-02-18 00:55:53 +00005600 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5601 t = Bits32 (opcode, 15, 12);
5602 n = Bits32 (opcode, 19, 16);
5603 imm32 = Bits32 (opcode, 11, 0);
5604
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005605 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
5606 index = BitIsSet (opcode, 24);
5607 add = BitIsSet (opcode, 23);
5608 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
Caroline Tice4d729c52011-02-18 00:55:53 +00005609
5610 // if wback && n == t then UNPREDICTABLE;
5611 if (wback && (n == t))
5612 return false;
5613
5614 break;
5615
5616 default:
5617 return false;
5618 }
5619
5620 addr_t address;
5621 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005622 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005623 if (!success)
5624 return false;
5625
5626 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5627 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005628 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005629 else
5630 offset_addr = base_address - imm32;
5631
5632 // address = if index then offset_addr else R[n];
5633 if (index)
5634 address = offset_addr;
5635 else
5636 address = base_address;
5637
5638 // data = MemU[address,4];
5639
5640 Register base_reg;
5641 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5642
5643 EmulateInstruction::Context context;
5644 context.type = eContextRegisterLoad;
5645 context.SetRegisterPlusOffset (base_reg, address - base_address);
5646
5647 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5648 if (!success)
5649 return false;
5650
5651 // if wback then R[n] = offset_addr;
5652 if (wback)
5653 {
5654 context.type = eContextAdjustBaseRegister;
5655 context.SetAddress (offset_addr);
5656 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5657 return false;
5658 }
5659
5660 // if t == 15 then
5661 if (t == 15)
5662 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005663 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Tice4d729c52011-02-18 00:55:53 +00005664 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5665 {
5666 // LoadWritePC (data);
5667 context.type = eContextRegisterLoad;
5668 context.SetRegisterPlusOffset (base_reg, address - base_address);
5669 LoadWritePC (context, data);
5670 }
5671 else
5672 return false;
5673 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005674 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Tice4d729c52011-02-18 00:55:53 +00005675 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5676 {
5677 // R[t] = data;
5678 context.type = eContextRegisterLoad;
5679 context.SetRegisterPlusOffset (base_reg, address - base_address);
5680 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5681 return false;
5682 }
5683 // else // Can only apply before ARMv7
5684 else
5685 {
5686 // R[t] = ROR(data, 8*UInt(address<1:0>));
5687 data = ROR (data, Bits32 (address, 1, 0));
5688 context.type = eContextRegisterLoad;
5689 context.SetImmediate (data);
5690 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5691 return false;
5692 }
5693
5694 }
5695 return true;
5696}
5697
Caroline Ticefe479112011-02-18 18:52:37 +00005698// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5699// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5700bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005701EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticefe479112011-02-18 18:52:37 +00005702{
5703#if 0
5704 if ConditionPassed() then
5705 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5706 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5707 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5708 address = if index then offset_addr else R[n];
5709 data = MemU[address,4];
5710 if wback then R[n] = offset_addr;
5711 if t == 15 then
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005712 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
5713 elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005714 R[t] = data;
5715 else // Can only apply before ARMv7
5716 if CurrentInstrSet() == InstrSet_ARM then
5717 R[t] = ROR(data, 8*UInt(address<1:0>));
5718 else
5719 R[t] = bits(32) UNKNOWN;
5720#endif
5721
5722 bool success = false;
Caroline Ticefe479112011-02-18 18:52:37 +00005723
Greg Clayton7bc39082011-03-24 23:53:38 +00005724 if (ConditionPassed(opcode))
Caroline Ticefe479112011-02-18 18:52:37 +00005725 {
5726 const uint32_t addr_byte_size = GetAddressByteSize();
5727
5728 uint32_t t;
5729 uint32_t n;
5730 uint32_t m;
5731 bool index;
5732 bool add;
5733 bool wback;
5734 ARM_ShifterType shift_t;
5735 uint32_t shift_n;
5736
5737 switch (encoding)
5738 {
5739 case eEncodingT1:
5740 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5741 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5742 t = Bits32 (opcode, 2, 0);
5743 n = Bits32 (opcode, 5, 3);
5744 m = Bits32 (opcode, 8, 6);
5745
5746 // index = TRUE; add = TRUE; wback = FALSE;
5747 index = true;
5748 add = true;
5749 wback = false;
5750
5751 // (shift_t, shift_n) = (SRType_LSL, 0);
5752 shift_t = SRType_LSL;
5753 shift_n = 0;
5754
5755 break;
5756
5757 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005758 // if Rn == '1111' then SEE LDR (literal);
Caroline Ticefe479112011-02-18 18:52:37 +00005759 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5760 t = Bits32 (opcode, 15, 12);
5761 n = Bits32 (opcode, 19, 16);
5762 m = Bits32 (opcode, 3, 0);
5763
5764 // index = TRUE; add = TRUE; wback = FALSE;
5765 index = true;
5766 add = true;
5767 wback = false;
5768
5769 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5770 shift_t = SRType_LSL;
5771 shift_n = Bits32 (opcode, 5, 4);
5772
5773 // if BadReg(m) then UNPREDICTABLE;
5774 if (BadReg (m))
5775 return false;
5776
5777 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5778 if ((t == 15) && InITBlock() && !LastInITBlock())
5779 return false;
5780
5781 break;
5782
5783 case eEncodingA1:
5784 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005785 // if P == '0' && W == '1' then SEE LDRT;
Caroline Ticefe479112011-02-18 18:52:37 +00005786 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5787 t = Bits32 (opcode, 15, 12);
5788 n = Bits32 (opcode, 19, 16);
5789 m = Bits32 (opcode, 3, 0);
5790
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005791 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticefe479112011-02-18 18:52:37 +00005792 index = BitIsSet (opcode, 24);
5793 add = BitIsSet (opcode, 23);
5794 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5795
5796 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5797 uint32_t type = Bits32 (opcode, 6, 5);
5798 uint32_t imm5 = Bits32 (opcode, 11, 7);
5799 shift_n = DecodeImmShift (type, imm5, shift_t);
5800
5801 // if m == 15 then UNPREDICTABLE;
5802 if (m == 15)
5803 return false;
5804
5805 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5806 if (wback && ((n == 15) || (n == t)))
5807 return false;
5808 }
5809 break;
5810
5811
5812 default:
5813 return false;
5814 }
5815
5816 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5817 if (!success)
5818 return false;
5819
5820 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5821 if (!success)
5822 return false;
5823
5824 addr_t offset_addr;
5825 addr_t address;
5826
5827 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Greg Claytonb3448432011-03-24 21:19:54 +00005828 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005829
5830 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5831 if (add)
5832 offset_addr = Rn + offset;
5833 else
5834 offset_addr = Rn - offset;
5835
5836 // address = if index then offset_addr else R[n];
5837 if (index)
5838 address = offset_addr;
5839 else
5840 address = Rn;
5841
5842 // data = MemU[address,4];
5843 Register base_reg;
5844 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5845
5846 EmulateInstruction::Context context;
5847 context.type = eContextRegisterLoad;
5848 context.SetRegisterPlusOffset (base_reg, address - Rn);
5849
5850 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5851 if (!success)
5852 return false;
5853
5854 // if wback then R[n] = offset_addr;
5855 if (wback)
5856 {
5857 context.type = eContextAdjustBaseRegister;
5858 context.SetAddress (offset_addr);
5859 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5860 return false;
5861 }
5862
5863 // if t == 15 then
5864 if (t == 15)
5865 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005866 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
Caroline Ticefe479112011-02-18 18:52:37 +00005867 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5868 {
5869 context.type = eContextRegisterLoad;
5870 context.SetRegisterPlusOffset (base_reg, address - Rn);
5871 LoadWritePC (context, data);
5872 }
5873 else
5874 return false;
5875 }
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005876 // elsif UnalignedSupport() || address<1:0> = '00' then
Caroline Ticefe479112011-02-18 18:52:37 +00005877 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5878 {
5879 // R[t] = data;
5880 context.type = eContextRegisterLoad;
5881 context.SetRegisterPlusOffset (base_reg, address - Rn);
5882 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5883 return false;
5884 }
5885 else // Can only apply before ARMv7
5886 {
5887 // if CurrentInstrSet() == InstrSet_ARM then
5888 if (CurrentInstrSet () == eModeARM)
5889 {
5890 // R[t] = ROR(data, 8*UInt(address<1:0>));
5891 data = ROR (data, Bits32 (address, 1, 0));
5892 context.type = eContextRegisterLoad;
5893 context.SetImmediate (data);
5894 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5895 return false;
5896 }
5897 else
5898 {
5899 // R[t] = bits(32) UNKNOWN;
5900 WriteBits32Unknown (t);
5901 }
5902 }
5903 }
5904 return true;
5905}
Caroline Tice21b604b2011-02-18 21:06:04 +00005906
5907// LDRB (immediate, Thumb)
5908bool
Greg Clayton7bc39082011-03-24 23:53:38 +00005909EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice21b604b2011-02-18 21:06:04 +00005910{
5911#if 0
5912 if ConditionPassed() then
5913 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5914 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5915 address = if index then offset_addr else R[n];
5916 R[t] = ZeroExtend(MemU[address,1], 32);
5917 if wback then R[n] = offset_addr;
5918#endif
5919
5920 bool success = false;
Caroline Tice21b604b2011-02-18 21:06:04 +00005921
Greg Clayton7bc39082011-03-24 23:53:38 +00005922 if (ConditionPassed(opcode))
Caroline Tice21b604b2011-02-18 21:06:04 +00005923 {
5924 uint32_t t;
5925 uint32_t n;
5926 uint32_t imm32;
5927 bool index;
5928 bool add;
5929 bool wback;
5930
5931 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5932 switch (encoding)
5933 {
5934 case eEncodingT1:
5935 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5936 t = Bits32 (opcode, 2, 0);
5937 n = Bits32 (opcode, 5, 3);
5938 imm32 = Bits32 (opcode, 10, 6);
5939
5940 // index = TRUE; add = TRUE; wback = FALSE;
5941 index = true;
5942 add = true;
5943 wback= false;
5944
5945 break;
5946
5947 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005948 // if Rt == '1111' then SEE PLD;
5949 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice21b604b2011-02-18 21:06:04 +00005950 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5951 t = Bits32 (opcode, 15, 12);
5952 n = Bits32 (opcode, 19, 16);
5953 imm32 = Bits32 (opcode, 11, 0);
5954
5955 // index = TRUE; add = TRUE; wback = FALSE;
5956 index = true;
5957 add = true;
5958 wback = false;
5959
5960 // if t == 13 then UNPREDICTABLE;
5961 if (t == 13)
5962 return false;
5963
5964 break;
5965
5966 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005967 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
5968 // if Rn == '1111' then SEE LDRB (literal);
5969 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
5970 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice21b604b2011-02-18 21:06:04 +00005971 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5972 return false;
5973
5974 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5975 t = Bits32 (opcode, 15, 12);
5976 n = Bits32 (opcode, 19, 16);
5977 imm32 = Bits32 (opcode, 7, 0);
5978
Caroline Ticebb48f0b2011-03-28 16:10:45 +00005979 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice21b604b2011-02-18 21:06:04 +00005980 index = BitIsSet (opcode, 10);
5981 add = BitIsSet (opcode, 9);
5982 wback = BitIsSet (opcode, 8);
5983
5984 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5985 if (BadReg (t) || (wback && (n == t)))
5986 return false;
5987
5988 break;
5989
5990 default:
5991 return false;
5992 }
5993
5994 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5995 if (!success)
5996 return false;
5997
5998 addr_t address;
5999 addr_t offset_addr;
6000
6001 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6002 if (add)
6003 offset_addr = Rn + imm32;
6004 else
6005 offset_addr = Rn - imm32;
6006
6007 // address = if index then offset_addr else R[n];
6008 if (index)
6009 address = offset_addr;
6010 else
6011 address = Rn;
6012
6013 // R[t] = ZeroExtend(MemU[address,1], 32);
6014 Register base_reg;
6015 Register data_reg;
6016 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6017 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6018
6019 EmulateInstruction::Context context;
6020 context.type = eContextRegisterLoad;
6021 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6022
6023 uint64_t data = MemURead (context, address, 1, 0, &success);
6024 if (!success)
6025 return false;
6026
6027 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6028 return false;
6029
6030 // if wback then R[n] = offset_addr;
6031 if (wback)
6032 {
6033 context.type = eContextAdjustBaseRegister;
6034 context.SetAddress (offset_addr);
6035 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6036 return false;
6037 }
6038 }
6039 return true;
6040}
Caroline Ticef55261f2011-02-18 22:24:22 +00006041
6042// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6043// zero-extends it to form a 32-bit word and writes it to a register.
6044bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006045EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticef55261f2011-02-18 22:24:22 +00006046{
6047#if 0
6048 if ConditionPassed() then
6049 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6050 base = Align(PC,4);
6051 address = if add then (base + imm32) else (base - imm32);
6052 R[t] = ZeroExtend(MemU[address,1], 32);
6053#endif
6054
6055 bool success = false;
Caroline Ticef55261f2011-02-18 22:24:22 +00006056
Greg Clayton7bc39082011-03-24 23:53:38 +00006057 if (ConditionPassed(opcode))
Caroline Ticef55261f2011-02-18 22:24:22 +00006058 {
6059 uint32_t t;
6060 uint32_t imm32;
6061 bool add;
6062 switch (encoding)
6063 {
6064 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006065 // if Rt == '1111' then SEE PLD;
6066 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006067 t = Bits32 (opcode, 15, 12);
6068 imm32 = Bits32 (opcode, 11, 0);
6069 add = BitIsSet (opcode, 23);
6070
6071 // if t == 13 then UNPREDICTABLE;
6072 if (t == 13)
6073 return false;
6074
6075 break;
6076
6077 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006078 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticef55261f2011-02-18 22:24:22 +00006079 t = Bits32 (opcode, 15, 12);
6080 imm32 = Bits32 (opcode, 11, 0);
6081 add = BitIsSet (opcode, 23);
6082
6083 // if t == 15 then UNPREDICTABLE;
6084 if (t == 15)
6085 return false;
6086 break;
6087
6088 default:
6089 return false;
6090 }
6091
6092 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006093 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006094 if (!success)
6095 return false;
6096
6097 uint32_t base = AlignPC (pc_val);
6098
6099 addr_t address;
6100 // address = if add then (base + imm32) else (base - imm32);
6101 if (add)
6102 address = base + imm32;
6103 else
6104 address = base - imm32;
6105
6106 // R[t] = ZeroExtend(MemU[address,1], 32);
6107 EmulateInstruction::Context context;
6108 context.type = eContextRelativeBranchImmediate;
6109 context.SetImmediate (address - base);
6110
6111 uint64_t data = MemURead (context, address, 1, 0, &success);
6112 if (!success)
6113 return false;
6114
6115 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6116 return false;
6117 }
6118 return true;
6119}
Caroline Tice30fec122011-02-18 23:52:21 +00006120
6121// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6122// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6123// optionally be shifted.
6124bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006125EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice30fec122011-02-18 23:52:21 +00006126{
6127#if 0
6128 if ConditionPassed() then
6129 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6130 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6131 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6132 address = if index then offset_addr else R[n];
6133 R[t] = ZeroExtend(MemU[address,1],32);
6134 if wback then R[n] = offset_addr;
6135#endif
6136
6137 bool success = false;
Caroline Tice30fec122011-02-18 23:52:21 +00006138
Greg Clayton7bc39082011-03-24 23:53:38 +00006139 if (ConditionPassed(opcode))
Caroline Tice30fec122011-02-18 23:52:21 +00006140 {
6141 uint32_t t;
6142 uint32_t n;
6143 uint32_t m;
6144 bool index;
6145 bool add;
6146 bool wback;
6147 ARM_ShifterType shift_t;
6148 uint32_t shift_n;
6149
6150 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6151 switch (encoding)
6152 {
6153 case eEncodingT1:
6154 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6155 t = Bits32 (opcode, 2, 0);
6156 n = Bits32 (opcode, 5, 3);
6157 m = Bits32 (opcode, 8, 6);
6158
6159 // index = TRUE; add = TRUE; wback = FALSE;
6160 index = true;
6161 add = true;
6162 wback = false;
6163
6164 // (shift_t, shift_n) = (SRType_LSL, 0);
6165 shift_t = SRType_LSL;
6166 shift_n = 0;
6167 break;
6168
6169 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006170 // if Rt == '1111' then SEE PLD;
6171 // if Rn == '1111' then SEE LDRB (literal);
Caroline Tice30fec122011-02-18 23:52:21 +00006172 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6173 t = Bits32 (opcode, 15, 12);
6174 n = Bits32 (opcode, 19, 16);
6175 m = Bits32 (opcode, 3, 0);
6176
6177 // index = TRUE; add = TRUE; wback = FALSE;
6178 index = true;
6179 add = true;
6180 wback = false;
6181
6182 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6183 shift_t = SRType_LSL;
6184 shift_n = Bits32 (opcode, 5, 4);
6185
6186 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6187 if ((t == 13) || BadReg (m))
6188 return false;
6189 break;
6190
6191 case eEncodingA1:
6192 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006193 // if P == '0' && W == '1' then SEE LDRBT;
Caroline Tice30fec122011-02-18 23:52:21 +00006194 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6195 t = Bits32 (opcode, 15, 12);
6196 n = Bits32 (opcode, 19, 16);
6197 m = Bits32 (opcode, 3, 0);
6198
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006199 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice30fec122011-02-18 23:52:21 +00006200 index = BitIsSet (opcode, 24);
6201 add = BitIsSet (opcode, 23);
6202 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6203
6204 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6205 uint32_t type = Bits32 (opcode, 6, 5);
6206 uint32_t imm5 = Bits32 (opcode, 11, 7);
6207 shift_n = DecodeImmShift (type, imm5, shift_t);
6208
6209 // if t == 15 || m == 15 then UNPREDICTABLE;
6210 if ((t == 15) || (m == 15))
6211 return false;
6212
6213 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6214 if (wback && ((n == 15) || (n == t)))
6215 return false;
6216 }
6217 break;
6218
6219 default:
6220 return false;
6221 }
6222
6223 addr_t offset_addr;
6224 addr_t address;
6225
6226 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6227 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6228 if (!success)
6229 return false;
6230
6231 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6232
6233 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6234 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6235 if (!success)
6236 return false;
6237
6238 if (add)
6239 offset_addr = Rn + offset;
6240 else
6241 offset_addr = Rn - offset;
6242
6243 // address = if index then offset_addr else R[n];
6244 if (index)
6245 address = offset_addr;
6246 else
6247 address = Rn;
6248
6249 // R[t] = ZeroExtend(MemU[address,1],32);
6250 Register base_reg;
6251 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6252
6253 EmulateInstruction::Context context;
6254 context.type = eContextRegisterLoad;
6255 context.SetRegisterPlusOffset (base_reg, address - Rn);
6256
6257 uint64_t data = MemURead (context, address, 1, 0, &success);
6258 if (!success)
6259 return false;
6260
6261 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6262 return false;
6263
6264 // if wback then R[n] = offset_addr;
6265 if (wback)
6266 {
6267 context.type = eContextAdjustBaseRegister;
6268 context.SetAddress (offset_addr);
6269 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6270 return false;
6271 }
6272 }
6273 return true;
6274}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006275
6276// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6277// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6278// post-indexed, or pre-indexed addressing.
6279bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006280EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0491b3b2011-02-28 22:39:58 +00006281{
6282#if 0
6283 if ConditionPassed() then
6284 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6285 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6286 address = if index then offset_addr else R[n];
6287 data = MemU[address,2];
6288 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006289 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006290 R[t] = ZeroExtend(data, 32);
6291 else // Can only apply before ARMv7
6292 R[t] = bits(32) UNKNOWN;
6293#endif
6294
6295
6296 bool success = false;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006297
Greg Clayton7bc39082011-03-24 23:53:38 +00006298 if (ConditionPassed(opcode))
Caroline Tice0491b3b2011-02-28 22:39:58 +00006299 {
6300 uint32_t t;
6301 uint32_t n;
6302 uint32_t imm32;
6303 bool index;
6304 bool add;
6305 bool wback;
6306
6307 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6308 switch (encoding)
6309 {
6310 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006311 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006312 t = Bits32 (opcode, 2, 0);
6313 n = Bits32 (opcode, 5, 3);
6314 imm32 = Bits32 (opcode, 10, 6) << 1;
6315
6316 // index = TRUE; add = TRUE; wback = FALSE;
6317 index = true;
6318 add = true;
6319 wback = false;
6320
6321 break;
6322
6323 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006324 // if Rt == '1111' then SEE "Unallocated memory hints";
6325 // if Rn == '1111' then SEE LDRH (literal);
Caroline Tice0491b3b2011-02-28 22:39:58 +00006326 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6327 t = Bits32 (opcode, 15, 12);
6328 n = Bits32 (opcode, 19, 16);
6329 imm32 = Bits32 (opcode, 11, 0);
6330
6331 // index = TRUE; add = TRUE; wback = FALSE;
6332 index = true;
6333 add = true;
6334 wback = false;
6335
6336 // if t == 13 then UNPREDICTABLE;
6337 if (t == 13)
6338 return false;
6339 break;
6340
6341 case eEncodingT3:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006342 // if Rn == '1111' then SEE LDRH (literal);
6343 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
6344 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
6345 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice0491b3b2011-02-28 22:39:58 +00006346 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6347 return false;
6348
6349 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6350 t = Bits32 (opcode, 15, 12);
6351 n = Bits32 (opcode, 19, 16);
6352 imm32 = Bits32 (opcode, 7, 0);
6353
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006354 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice0491b3b2011-02-28 22:39:58 +00006355 index = BitIsSet (opcode, 10);
6356 add = BitIsSet (opcode, 9);
6357 wback = BitIsSet (opcode, 8);
6358
6359 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6360 if (BadReg (t) || (wback && (n == t)))
6361 return false;
6362 break;
6363
6364 default:
6365 return false;
6366 }
6367
6368 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6369 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6370 if (!success)
6371 return false;
6372
6373 addr_t offset_addr;
6374 addr_t address;
6375
6376 if (add)
6377 offset_addr = Rn + imm32;
6378 else
6379 offset_addr = Rn - imm32;
6380
6381 // address = if index then offset_addr else R[n];
6382 if (index)
6383 address = offset_addr;
6384 else
6385 address = Rn;
6386
6387 // data = MemU[address,2];
6388 Register base_reg;
6389 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6390
6391 EmulateInstruction::Context context;
6392 context.type = eContextRegisterLoad;
6393 context.SetRegisterPlusOffset (base_reg, address - Rn);
6394
6395 uint64_t data = MemURead (context, address, 2, 0, &success);
6396 if (!success)
6397 return false;
6398
6399 // if wback then R[n] = offset_addr;
6400 if (wback)
6401 {
6402 context.type = eContextAdjustBaseRegister;
6403 context.SetAddress (offset_addr);
6404 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6405 return false;
6406 }
6407
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006408 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0491b3b2011-02-28 22:39:58 +00006409 if (UnalignedSupport () || BitIsClear (address, 0))
6410 {
6411 // R[t] = ZeroExtend(data, 32);
6412 context.type = eContextRegisterLoad;
6413 context.SetRegisterPlusOffset (base_reg, address - Rn);
6414 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6415 return false;
6416 }
6417 else // Can only apply before ARMv7
6418 {
6419 // R[t] = bits(32) UNKNOWN;
6420 WriteBits32Unknown (t);
6421 }
6422 }
6423 return true;
6424}
Caroline Ticefe479112011-02-18 18:52:37 +00006425
Caroline Tice952b5382011-02-28 23:15:24 +00006426// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6427// zero-extends it to form a 32-bit word, and writes it to a register.
6428bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006429EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice952b5382011-02-28 23:15:24 +00006430{
6431#if 0
6432 if ConditionPassed() then
6433 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6434 base = Align(PC,4);
6435 address = if add then (base + imm32) else (base - imm32);
6436 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006437 if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006438 R[t] = ZeroExtend(data, 32);
6439 else // Can only apply before ARMv7
6440 R[t] = bits(32) UNKNOWN;
6441#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006442
Caroline Tice952b5382011-02-28 23:15:24 +00006443 bool success = false;
Caroline Tice952b5382011-02-28 23:15:24 +00006444
Greg Clayton7bc39082011-03-24 23:53:38 +00006445 if (ConditionPassed(opcode))
Caroline Tice952b5382011-02-28 23:15:24 +00006446 {
6447 uint32_t t;
6448 uint32_t imm32;
6449 bool add;
6450
6451 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6452 switch (encoding)
6453 {
6454 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006455 // if Rt == '1111' then SEE "Unallocated memory hints";
6456 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006457 t = Bits32 (opcode, 15, 12);
6458 imm32 = Bits32 (opcode, 11, 0);
6459 add = BitIsSet (opcode, 23);
6460
6461 // if t == 13 then UNPREDICTABLE;
6462 if (t == 13)
6463 return false;
6464
6465 break;
6466
6467 case eEncodingA1:
6468 {
6469 uint32_t imm4H = Bits32 (opcode, 11, 8);
6470 uint32_t imm4L = Bits32 (opcode, 3, 0);
6471
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006472 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice952b5382011-02-28 23:15:24 +00006473 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006474 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006475 add = BitIsSet (opcode, 23);
6476
6477 // if t == 15 then UNPREDICTABLE;
6478 if (t == 15)
6479 return false;
6480 break;
6481 }
6482
6483 default:
6484 return false;
6485 }
6486
6487 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006488 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006489 if (!success)
6490 return false;
6491
6492 addr_t base = AlignPC (pc_value);
6493 addr_t address;
6494
6495 // address = if add then (base + imm32) else (base - imm32);
6496 if (add)
6497 address = base + imm32;
6498 else
6499 address = base - imm32;
6500
6501 // data = MemU[address,2];
6502 Register base_reg;
6503 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6504
6505 EmulateInstruction::Context context;
6506 context.type = eContextRegisterLoad;
6507 context.SetRegisterPlusOffset (base_reg, address - base);
6508
6509 uint64_t data = MemURead (context, address, 2, 0, &success);
6510 if (!success)
6511 return false;
6512
6513
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006514 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice952b5382011-02-28 23:15:24 +00006515 if (UnalignedSupport () || BitIsClear (address, 0))
6516 {
6517 // R[t] = ZeroExtend(data, 32);
6518 context.type = eContextRegisterLoad;
6519 context.SetRegisterPlusOffset (base_reg, address - base);
6520 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6521 return false;
6522
6523 }
6524 else // Can only apply before ARMv7
6525 {
6526 // R[t] = bits(32) UNKNOWN;
6527 WriteBits32Unknown (t);
6528 }
6529 }
6530 return true;
6531}
6532
Caroline Tice0e6bc952011-03-01 18:00:42 +00006533// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6534// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6535// be shifted left by 0, 1, 2, or 3 bits.
6536bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006537EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice0e6bc952011-03-01 18:00:42 +00006538{
6539#if 0
6540 if ConditionPassed() then
6541 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6542 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6543 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6544 address = if index then offset_addr else R[n];
6545 data = MemU[address,2];
6546 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006547 if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006548 R[t] = ZeroExtend(data, 32);
6549 else // Can only apply before ARMv7
6550 R[t] = bits(32) UNKNOWN;
6551#endif
6552
6553 bool success = false;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006554
Greg Clayton7bc39082011-03-24 23:53:38 +00006555 if (ConditionPassed(opcode))
Caroline Tice0e6bc952011-03-01 18:00:42 +00006556 {
6557 uint32_t t;
6558 uint32_t n;
6559 uint32_t m;
6560 bool index;
6561 bool add;
6562 bool wback;
6563 ARM_ShifterType shift_t;
6564 uint32_t shift_n;
6565
6566 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6567 switch (encoding)
6568 {
6569 case eEncodingT1:
6570 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6571 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6572 t = Bits32 (opcode, 2, 0);
6573 n = Bits32 (opcode, 5, 3);
6574 m = Bits32 (opcode, 8, 6);
6575
6576 // index = TRUE; add = TRUE; wback = FALSE;
6577 index = true;
6578 add = true;
6579 wback = false;
6580
6581 // (shift_t, shift_n) = (SRType_LSL, 0);
6582 shift_t = SRType_LSL;
6583 shift_n = 0;
6584
6585 break;
6586
6587 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006588 // if Rn == '1111' then SEE LDRH (literal);
6589 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice0e6bc952011-03-01 18:00:42 +00006590 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6591 t = Bits32 (opcode, 15, 12);
6592 n = Bits32 (opcode, 19, 16);
6593 m = Bits32 (opcode, 3, 0);
6594
6595 // index = TRUE; add = TRUE; wback = FALSE;
6596 index = true;
6597 add = true;
6598 wback = false;
6599
6600 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6601 shift_t = SRType_LSL;
6602 shift_n = Bits32 (opcode, 5, 4);
6603
6604 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6605 if ((t == 13) || BadReg (m))
6606 return false;
6607 break;
6608
6609 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006610 // if P == '0' && W == '1' then SEE LDRHT;
Caroline Tice0e6bc952011-03-01 18:00:42 +00006611 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6612 t = Bits32 (opcode, 15, 12);
6613 n = Bits32 (opcode, 19, 16);
6614 m = Bits32 (opcode, 3, 0);
6615
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006616 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice0e6bc952011-03-01 18:00:42 +00006617 index = BitIsSet (opcode, 24);
6618 add = BitIsSet (opcode, 23);
6619 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6620
6621 // (shift_t, shift_n) = (SRType_LSL, 0);
6622 shift_t = SRType_LSL;
6623 shift_n = 0;
6624
6625 // if t == 15 || m == 15 then UNPREDICTABLE;
6626 if ((t == 15) || (m == 15))
6627 return false;
6628
6629 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6630 if (wback && ((n == 15) || (n == t)))
6631 return false;
6632
6633 break;
6634
6635 default:
6636 return false;
6637 }
6638
6639 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6640
6641 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6642 if (!success)
6643 return false;
6644
6645 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6646
6647 addr_t offset_addr;
6648 addr_t address;
6649
6650 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6651 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6652 if (!success)
6653 return false;
6654
6655 if (add)
6656 offset_addr = Rn + offset;
6657 else
6658 offset_addr = Rn - offset;
6659
6660 // address = if index then offset_addr else R[n];
6661 if (index)
6662 address = offset_addr;
6663 else
6664 address = Rn;
6665
6666 // data = MemU[address,2];
6667 Register base_reg;
6668 Register offset_reg;
6669 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6670 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6671
6672 EmulateInstruction::Context context;
6673 context.type = eContextRegisterLoad;
6674 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6675 uint64_t data = MemURead (context, address, 2, 0, &success);
6676 if (!success)
6677 return false;
6678
6679 // if wback then R[n] = offset_addr;
6680 if (wback)
6681 {
6682 context.type = eContextAdjustBaseRegister;
6683 context.SetAddress (offset_addr);
6684 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6685 return false;
6686 }
6687
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006688 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice0e6bc952011-03-01 18:00:42 +00006689 if (UnalignedSupport() || BitIsClear (address, 0))
6690 {
6691 // R[t] = ZeroExtend(data, 32);
6692 context.type = eContextRegisterLoad;
6693 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6694 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6695 return false;
6696 }
6697 else // Can only apply before ARMv7
6698 {
6699 // R[t] = bits(32) UNKNOWN;
6700 WriteBits32Unknown (t);
6701 }
6702 }
6703 return true;
6704}
6705
Caroline Ticea5e28af2011-03-01 21:53:03 +00006706// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6707// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6708// or pre-indexed addressing.
6709bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006710EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticea5e28af2011-03-01 21:53:03 +00006711{
6712#if 0
6713 if ConditionPassed() then
6714 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6715 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6716 address = if index then offset_addr else R[n];
6717 R[t] = SignExtend(MemU[address,1], 32);
6718 if wback then R[n] = offset_addr;
6719#endif
6720
6721 bool success = false;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006722
Greg Clayton7bc39082011-03-24 23:53:38 +00006723 if (ConditionPassed(opcode))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006724 {
6725 uint32_t t;
6726 uint32_t n;
6727 uint32_t imm32;
6728 bool index;
6729 bool add;
6730 bool wback;
6731
6732 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6733 switch (encoding)
6734 {
6735 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006736 // if Rt == '1111' then SEE PLI;
6737 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006738 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6739 t = Bits32 (opcode, 15, 12);
6740 n = Bits32 (opcode, 19, 16);
6741 imm32 = Bits32 (opcode, 11, 0);
6742
6743 // index = TRUE; add = TRUE; wback = FALSE;
6744 index = true;
6745 add = true;
6746 wback = false;
6747
6748 // if t == 13 then UNPREDICTABLE;
6749 if (t == 13)
6750 return false;
6751
6752 break;
6753
6754 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006755 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
6756 // if Rn == '1111' then SEE LDRSB (literal);
6757 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
6758 // if P == '0' && W == '0' then UNDEFINED;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006759 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6760 return false;
6761
6762 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6763 t = Bits32 (opcode, 15, 12);
6764 n = Bits32 (opcode, 19, 16);
6765 imm32 = Bits32 (opcode, 7, 0);
6766
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006767 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006768 index = BitIsSet (opcode, 10);
6769 add = BitIsSet (opcode, 9);
6770 wback = BitIsSet (opcode, 8);
6771
6772 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006773 if (((t == 13) || ((t == 15)
6774 && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8))))
6775 || (wback && (n == t)))
Caroline Ticea5e28af2011-03-01 21:53:03 +00006776 return false;
6777
6778 break;
6779
6780 case eEncodingA1:
6781 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006782 // if Rn == '1111' then SEE LDRSB (literal);
6783 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006784 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6785 t = Bits32 (opcode, 15, 12);
6786 n = Bits32 (opcode, 19, 16);
6787
6788 uint32_t imm4H = Bits32 (opcode, 11, 8);
6789 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006790 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006791
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006792 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Ticea5e28af2011-03-01 21:53:03 +00006793 index = BitIsSet (opcode, 24);
6794 add = BitIsSet (opcode, 23);
6795 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6796
6797 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6798 if ((t == 15) || (wback && (n == t)))
6799 return false;
6800
6801 break;
6802 }
6803
6804 default:
6805 return false;
6806 }
6807
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006808 uint64_t Rn = ReadCoreReg (n, &success);
Caroline Ticea5e28af2011-03-01 21:53:03 +00006809 if (!success)
6810 return false;
6811
6812 addr_t offset_addr;
6813 addr_t address;
6814
6815 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6816 if (add)
6817 offset_addr = Rn + imm32;
6818 else
6819 offset_addr = Rn - imm32;
6820
6821 // address = if index then offset_addr else R[n];
6822 if (index)
6823 address = offset_addr;
6824 else
6825 address = Rn;
6826
6827 // R[t] = SignExtend(MemU[address,1], 32);
6828 Register base_reg;
6829 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6830
6831 EmulateInstruction::Context context;
6832 context.type = eContextRegisterLoad;
6833 context.SetRegisterPlusOffset (base_reg, address - Rn);
6834
6835 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6836 if (!success)
6837 return false;
6838
6839 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6840 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6841 return false;
6842
6843 // if wback then R[n] = offset_addr;
6844 if (wback)
6845 {
6846 context.type = eContextAdjustBaseRegister;
6847 context.SetAddress (offset_addr);
6848 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6849 return false;
6850 }
6851 }
6852
6853 return true;
6854}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006855
Caroline Tice5f593912011-03-01 22:25:17 +00006856// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6857// sign-extends it to form a 32-bit word, and writes tit to a register.
6858bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006859EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice5f593912011-03-01 22:25:17 +00006860{
6861#if 0
6862 if ConditionPassed() then
6863 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6864 base = Align(PC,4);
6865 address = if add then (base + imm32) else (base - imm32);
6866 R[t] = SignExtend(MemU[address,1], 32);
6867#endif
6868
6869 bool success = false;
Caroline Tice5f593912011-03-01 22:25:17 +00006870
Greg Clayton7bc39082011-03-24 23:53:38 +00006871 if (ConditionPassed(opcode))
Caroline Tice5f593912011-03-01 22:25:17 +00006872 {
6873 uint32_t t;
6874 uint32_t imm32;
6875 bool add;
6876
6877 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6878 switch (encoding)
6879 {
6880 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006881 // if Rt == '1111' then SEE PLI;
6882 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006883 t = Bits32 (opcode, 15, 12);
6884 imm32 = Bits32 (opcode, 11, 0);
6885 add = BitIsSet (opcode, 23);
6886
6887 // if t == 13 then UNPREDICTABLE;
6888 if (t == 13)
6889 return false;
6890
6891 break;
6892
6893 case eEncodingA1:
6894 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006895 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Tice5f593912011-03-01 22:25:17 +00006896 t = Bits32 (opcode, 15, 12);
6897 uint32_t imm4H = Bits32 (opcode, 11, 8);
6898 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006899 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006900 add = BitIsSet (opcode, 23);
6901
6902 // if t == 15 then UNPREDICTABLE;
6903 if (t == 15)
6904 return false;
6905
6906 break;
6907 }
6908
6909 default:
6910 return false;
6911 }
6912
6913 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006914 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006915 if (!success)
6916 return false;
6917 uint64_t base = AlignPC (pc_value);
6918
6919 // address = if add then (base + imm32) else (base - imm32);
6920 addr_t address;
6921 if (add)
6922 address = base + imm32;
6923 else
6924 address = base - imm32;
6925
6926 // R[t] = SignExtend(MemU[address,1], 32);
6927 Register base_reg;
6928 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6929
6930 EmulateInstruction::Context context;
6931 context.type = eContextRegisterLoad;
6932 context.SetRegisterPlusOffset (base_reg, address - base);
6933
6934 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6935 if (!success)
6936 return false;
6937
6938 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6939 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6940 return false;
6941 }
6942 return true;
6943}
6944
Caroline Tice672f3112011-03-01 23:55:59 +00006945// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6946// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6947// shifted left by 0, 1, 2, or 3 bits.
6948bool
Greg Clayton7bc39082011-03-24 23:53:38 +00006949EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice672f3112011-03-01 23:55:59 +00006950{
6951#if 0
6952 if ConditionPassed() then
6953 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6954 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6955 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6956 address = if index then offset_addr else R[n];
6957 R[t] = SignExtend(MemU[address,1], 32);
6958 if wback then R[n] = offset_addr;
6959#endif
6960
6961 bool success = false;
Caroline Tice672f3112011-03-01 23:55:59 +00006962
Greg Clayton7bc39082011-03-24 23:53:38 +00006963 if (ConditionPassed(opcode))
Caroline Tice672f3112011-03-01 23:55:59 +00006964 {
6965 uint32_t t;
6966 uint32_t n;
6967 uint32_t m;
6968 bool index;
6969 bool add;
6970 bool wback;
6971 ARM_ShifterType shift_t;
6972 uint32_t shift_n;
6973
6974 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6975 switch (encoding)
6976 {
6977 case eEncodingT1:
6978 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6979 t = Bits32 (opcode, 2, 0);
6980 n = Bits32 (opcode, 5, 3);
6981 m = Bits32 (opcode, 8, 6);
6982
6983 // index = TRUE; add = TRUE; wback = FALSE;
6984 index = true;
6985 add = true;
6986 wback = false;
6987
6988 // (shift_t, shift_n) = (SRType_LSL, 0);
6989 shift_t = SRType_LSL;
6990 shift_n = 0;
6991
6992 break;
6993
6994 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00006995 // if Rt == '1111' then SEE PLI;
6996 // if Rn == '1111' then SEE LDRSB (literal);
Caroline Tice672f3112011-03-01 23:55:59 +00006997 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6998 t = Bits32 (opcode, 15, 12);
6999 n = Bits32 (opcode, 19, 16);
7000 m = Bits32 (opcode, 3, 0);
7001
7002 // index = TRUE; add = TRUE; wback = FALSE;
7003 index = true;
7004 add = true;
7005 wback = false;
7006
7007 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7008 shift_t = SRType_LSL;
7009 shift_n = Bits32 (opcode, 5, 4);
7010
7011 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7012 if ((t == 13) || BadReg (m))
7013 return false;
7014 break;
7015
7016 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007017 // if P == '0' && W == '1' then SEE LDRSBT;
Caroline Tice672f3112011-03-01 23:55:59 +00007018 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7019 t = Bits32 (opcode, 15, 12);
7020 n = Bits32 (opcode, 19, 16);
7021 m = Bits32 (opcode, 3, 0);
7022
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007023 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice672f3112011-03-01 23:55:59 +00007024 index = BitIsSet (opcode, 24);
7025 add = BitIsSet (opcode, 23);
7026 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7027
7028 // (shift_t, shift_n) = (SRType_LSL, 0);
7029 shift_t = SRType_LSL;
7030 shift_n = 0;
7031
7032 // if t == 15 || m == 15 then UNPREDICTABLE;
7033 if ((t == 15) || (m == 15))
7034 return false;
7035
7036 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7037 if (wback && ((n == 15) || (n == t)))
7038 return false;
7039 break;
7040
7041 default:
7042 return false;
7043 }
7044
7045 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7046 if (!success)
7047 return false;
7048
7049 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7050 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7051
7052 addr_t offset_addr;
7053 addr_t address;
7054
7055 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7056 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7057 if (!success)
7058 return false;
7059
7060 if (add)
7061 offset_addr = Rn + offset;
7062 else
7063 offset_addr = Rn - offset;
7064
7065 // address = if index then offset_addr else R[n];
7066 if (index)
7067 address = offset_addr;
7068 else
7069 address = Rn;
7070
7071 // R[t] = SignExtend(MemU[address,1], 32);
7072 Register base_reg;
7073 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7074 Register offset_reg;
7075 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7076
7077 EmulateInstruction::Context context;
7078 context.type = eContextRegisterLoad;
7079 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7080
7081 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7082 if (!success)
7083 return false;
7084
7085 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7086 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7087 return false;
7088
7089 // if wback then R[n] = offset_addr;
7090 if (wback)
7091 {
7092 context.type = eContextAdjustBaseRegister;
7093 context.SetAddress (offset_addr);
7094 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7095 return false;
7096 }
7097 }
7098 return true;
7099}
7100
Caroline Tice78fb5632011-03-02 00:39:42 +00007101// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7102// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7103// pre-indexed addressing.
7104bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007105EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice78fb5632011-03-02 00:39:42 +00007106{
7107#if 0
7108 if ConditionPassed() then
7109 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7110 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7111 address = if index then offset_addr else R[n];
7112 data = MemU[address,2];
7113 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007114 if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007115 R[t] = SignExtend(data, 32);
7116 else // Can only apply before ARMv7
7117 R[t] = bits(32) UNKNOWN;
7118#endif
7119
7120 bool success = false;
Caroline Tice78fb5632011-03-02 00:39:42 +00007121
Greg Clayton7bc39082011-03-24 23:53:38 +00007122 if (ConditionPassed(opcode))
Caroline Tice78fb5632011-03-02 00:39:42 +00007123 {
7124 uint32_t t;
7125 uint32_t n;
7126 uint32_t imm32;
7127 bool index;
7128 bool add;
7129 bool wback;
7130
7131 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7132 switch (encoding)
7133 {
7134 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007135 // if Rn == '1111' then SEE LDRSH (literal);
7136 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice78fb5632011-03-02 00:39:42 +00007137 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7138 t = Bits32 (opcode, 15, 12);
7139 n = Bits32 (opcode, 19, 16);
7140 imm32 = Bits32 (opcode, 11, 0);
7141
7142 // index = TRUE; add = TRUE; wback = FALSE;
7143 index = true;
7144 add = true;
7145 wback = false;
7146
7147 // if t == 13 then UNPREDICTABLE;
7148 if (t == 13)
7149 return false;
7150
7151 break;
7152
7153 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007154 // if Rn == '1111' then SEE LDRSH (literal);
7155 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints";
7156 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7157 // if P == '0' && W == '0' then UNDEFINED;
Caroline Tice78fb5632011-03-02 00:39:42 +00007158 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7159 return false;
7160
7161 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7162 t = Bits32 (opcode, 15, 12);
7163 n = Bits32 (opcode, 19, 16);
7164 imm32 = Bits32 (opcode, 7, 0);
7165
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007166 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007167 index = BitIsSet (opcode, 10);
7168 add = BitIsSet (opcode, 9);
7169 wback = BitIsSet (opcode, 8);
7170
7171 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7172 if (BadReg (t) || (wback && (n == t)))
7173 return false;
7174
7175 break;
7176
7177 case eEncodingA1:
7178 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007179 // if Rn == '1111' then SEE LDRSH (literal);
7180 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice78fb5632011-03-02 00:39:42 +00007181 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7182 t = Bits32 (opcode, 15, 12);
7183 n = Bits32 (opcode, 19, 16);
7184 uint32_t imm4H = Bits32 (opcode, 11,8);
7185 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007186 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007187
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007188 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice78fb5632011-03-02 00:39:42 +00007189 index = BitIsSet (opcode, 24);
7190 add = BitIsSet (opcode, 23);
7191 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7192
7193 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7194 if ((t == 15) || (wback && (n == t)))
7195 return false;
7196
7197 break;
7198 }
7199
7200 default:
7201 return false;
7202 }
7203
7204 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7205 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7206 if (!success)
7207 return false;
7208
7209 addr_t offset_addr;
7210 if (add)
7211 offset_addr = Rn + imm32;
7212 else
7213 offset_addr = Rn - imm32;
7214
7215 // address = if index then offset_addr else R[n];
7216 addr_t address;
7217 if (index)
7218 address = offset_addr;
7219 else
7220 address = Rn;
7221
7222 // data = MemU[address,2];
7223 Register base_reg;
7224 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7225
7226 EmulateInstruction::Context context;
7227 context.type = eContextRegisterLoad;
7228 context.SetRegisterPlusOffset (base_reg, address - Rn);
7229
7230 uint64_t data = MemURead (context, address, 2, 0, &success);
7231 if (!success)
7232 return false;
7233
7234 // if wback then R[n] = offset_addr;
7235 if (wback)
7236 {
7237 context.type = eContextAdjustBaseRegister;
7238 context.SetAddress (offset_addr);
7239 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7240 return false;
7241 }
7242
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007243 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice78fb5632011-03-02 00:39:42 +00007244 if (UnalignedSupport() || BitIsClear (address, 0))
7245 {
7246 // R[t] = SignExtend(data, 32);
7247 int64_t signed_data = llvm::SignExtend64<16>(data);
7248 context.type = eContextRegisterLoad;
7249 context.SetRegisterPlusOffset (base_reg, address - Rn);
7250 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7251 return false;
7252 }
7253 else // Can only apply before ARMv7
7254 {
7255 // R[t] = bits(32) UNKNOWN;
7256 WriteBits32Unknown (t);
7257 }
7258 }
7259 return true;
7260}
7261
Caroline Ticed2fac092011-03-02 19:45:34 +00007262// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7263// sign-extends it to from a 32-bit word, and writes it to a register.
7264bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007265EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed2fac092011-03-02 19:45:34 +00007266{
7267#if 0
7268 if ConditionPassed() then
7269 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7270 base = Align(PC,4);
7271 address = if add then (base + imm32) else (base - imm32);
7272 data = MemU[address,2];
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007273 if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007274 R[t] = SignExtend(data, 32);
7275 else // Can only apply before ARMv7
7276 R[t] = bits(32) UNKNOWN;
7277#endif
7278
7279 bool success = false;
Caroline Ticed2fac092011-03-02 19:45:34 +00007280
Greg Clayton7bc39082011-03-24 23:53:38 +00007281 if (ConditionPassed(opcode))
Caroline Ticed2fac092011-03-02 19:45:34 +00007282 {
7283 uint32_t t;
7284 uint32_t imm32;
7285 bool add;
7286
7287 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7288 switch (encoding)
7289 {
7290 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007291 // if Rt == '1111' then SEE "Unallocated memory hints";
7292 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007293 t = Bits32 (opcode, 15, 12);
7294 imm32 = Bits32 (opcode, 11, 0);
7295 add = BitIsSet (opcode, 23);
7296
7297 // if t == 13 then UNPREDICTABLE;
7298 if (t == 13)
7299 return false;
7300
7301 break;
7302
7303 case eEncodingA1:
7304 {
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007305 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
Caroline Ticed2fac092011-03-02 19:45:34 +00007306 t = Bits32 (opcode, 15, 12);
7307 uint32_t imm4H = Bits32 (opcode, 11, 8);
7308 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007309 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007310 add = BitIsSet (opcode, 23);
7311
7312 // if t == 15 then UNPREDICTABLE;
7313 if (t == 15)
7314 return false;
7315
7316 break;
7317 }
7318 default:
7319 return false;
7320 }
7321
7322 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007323 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007324 if (!success)
7325 return false;
7326
7327 uint64_t base = AlignPC (pc_value);
7328
7329 addr_t address;
7330 // address = if add then (base + imm32) else (base - imm32);
7331 if (add)
7332 address = base + imm32;
7333 else
7334 address = base - imm32;
7335
7336 // data = MemU[address,2];
7337 Register base_reg;
7338 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7339
7340 EmulateInstruction::Context context;
7341 context.type = eContextRegisterLoad;
7342 context.SetRegisterPlusOffset (base_reg, imm32);
7343
7344 uint64_t data = MemURead (context, address, 2, 0, &success);
7345 if (!success)
7346 return false;
7347
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007348 // if UnalignedSupport() || address<0> = '0' then
Caroline Ticed2fac092011-03-02 19:45:34 +00007349 if (UnalignedSupport() || BitIsClear (address, 0))
7350 {
7351 // R[t] = SignExtend(data, 32);
7352 int64_t signed_data = llvm::SignExtend64<16>(data);
7353 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7354 return false;
7355 }
7356 else // Can only apply before ARMv7
7357 {
7358 // R[t] = bits(32) UNKNOWN;
7359 WriteBits32Unknown (t);
7360 }
7361 }
7362 return true;
7363}
7364
Caroline Tice291a3e92011-03-02 21:13:44 +00007365// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7366// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7367// shifted left by 0, 1, 2, or 3 bits.
7368bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007369EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice291a3e92011-03-02 21:13:44 +00007370{
7371#if 0
7372 if ConditionPassed() then
7373 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7374 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7375 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7376 address = if index then offset_addr else R[n];
7377 data = MemU[address,2];
7378 if wback then R[n] = offset_addr;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007379 if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007380 R[t] = SignExtend(data, 32);
7381 else // Can only apply before ARMv7
7382 R[t] = bits(32) UNKNOWN;
7383#endif
7384
7385 bool success = false;
Caroline Tice291a3e92011-03-02 21:13:44 +00007386
Greg Clayton7bc39082011-03-24 23:53:38 +00007387 if (ConditionPassed(opcode))
Caroline Tice291a3e92011-03-02 21:13:44 +00007388 {
7389 uint32_t t;
7390 uint32_t n;
7391 uint32_t m;
7392 bool index;
7393 bool add;
7394 bool wback;
7395 ARM_ShifterType shift_t;
7396 uint32_t shift_n;
7397
7398 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7399 switch (encoding)
7400 {
7401 case eEncodingT1:
7402 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7403 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7404 t = Bits32 (opcode, 2, 0);
7405 n = Bits32 (opcode, 5, 3);
7406 m = Bits32 (opcode, 8, 6);
7407
7408 // index = TRUE; add = TRUE; wback = FALSE;
7409 index = true;
7410 add = true;
7411 wback = false;
7412
7413 // (shift_t, shift_n) = (SRType_LSL, 0);
7414 shift_t = SRType_LSL;
7415 shift_n = 0;
7416
7417 break;
7418
7419 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007420 // if Rn == '1111' then SEE LDRSH (literal);
7421 // if Rt == '1111' then SEE "Unallocated memory hints";
Caroline Tice291a3e92011-03-02 21:13:44 +00007422 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7423 t = Bits32 (opcode, 15, 12);
7424 n = Bits32 (opcode, 19, 16);
7425 m = Bits32 (opcode, 3, 0);
7426
7427 // index = TRUE; add = TRUE; wback = FALSE;
7428 index = true;
7429 add = true;
7430 wback = false;
7431
7432 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7433 shift_t = SRType_LSL;
7434 shift_n = Bits32 (opcode, 5, 4);
7435
7436 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7437 if ((t == 13) || BadReg (m))
7438 return false;
7439
7440 break;
7441
7442 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007443 // if P == '0' && W == '1' then SEE LDRSHT;
Caroline Tice291a3e92011-03-02 21:13:44 +00007444 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7445 t = Bits32 (opcode, 15, 12);
7446 n = Bits32 (opcode, 19, 16);
7447 m = Bits32 (opcode, 3, 0);
7448
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007449 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
Caroline Tice291a3e92011-03-02 21:13:44 +00007450 index = BitIsSet (opcode, 24);
7451 add = BitIsSet (opcode, 23);
7452 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7453
7454 // (shift_t, shift_n) = (SRType_LSL, 0);
7455 shift_t = SRType_LSL;
7456 shift_n = 0;
7457
7458 // if t == 15 || m == 15 then UNPREDICTABLE;
7459 if ((t == 15) || (m == 15))
7460 return false;
7461
7462 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7463 if (wback && ((n == 15) || (n == t)))
7464 return false;
7465
7466 break;
7467
7468 default:
7469 break;
7470 }
7471
7472 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7473 if (!success)
7474 return false;
7475
7476 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7477 if (!success)
7478 return false;
7479
7480 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7481 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7482
7483 addr_t offset_addr;
7484 addr_t address;
7485
7486 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7487 if (add)
7488 offset_addr = Rn + offset;
7489 else
7490 offset_addr = Rn - offset;
7491
7492 // address = if index then offset_addr else R[n];
7493 if (index)
7494 address = offset_addr;
7495 else
7496 address = Rn;
7497
7498 // data = MemU[address,2];
7499 Register base_reg;
7500 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7501
7502 Register offset_reg;
7503 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7504
7505 EmulateInstruction::Context context;
7506 context.type = eContextRegisterLoad;
7507 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7508
7509 uint64_t data = MemURead (context, address, 2, 0, &success);
7510 if (!success)
7511 return false;
7512
7513 // if wback then R[n] = offset_addr;
7514 if (wback)
7515 {
7516 context.type = eContextAdjustBaseRegister;
7517 context.SetAddress (offset_addr);
7518 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7519 return false;
7520 }
7521
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007522 // if UnalignedSupport() || address<0> = '0' then
Caroline Tice291a3e92011-03-02 21:13:44 +00007523 if (UnalignedSupport() || BitIsClear (address, 0))
7524 {
7525 // R[t] = SignExtend(data, 32);
7526 context.type = eContextRegisterLoad;
7527 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7528
7529 int64_t signed_data = llvm::SignExtend64<16>(data);
7530 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7531 return false;
7532 }
7533 else // Can only apply before ARMv7
7534 {
7535 // R[t] = bits(32) UNKNOWN;
7536 WriteBits32Unknown (t);
7537 }
7538 }
7539 return true;
7540}
Caroline Tice6bf65162011-03-03 17:42:58 +00007541
7542// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7543// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7544bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007545EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice6bf65162011-03-03 17:42:58 +00007546{
7547#if 0
7548 if ConditionPassed() then
7549 EncodingSpecificOperations();
7550 rotated = ROR(R[m], rotation);
7551 R[d] = SignExtend(rotated<7:0>, 32);
7552#endif
7553
7554 bool success = false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007555
Greg Clayton7bc39082011-03-24 23:53:38 +00007556 if (ConditionPassed(opcode))
Caroline Tice6bf65162011-03-03 17:42:58 +00007557 {
7558 uint32_t d;
7559 uint32_t m;
7560 uint32_t rotation;
7561
7562 // EncodingSpecificOperations();
7563 switch (encoding)
7564 {
7565 case eEncodingT1:
7566 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7567 d = Bits32 (opcode, 2, 0);
7568 m = Bits32 (opcode, 5, 3);
7569 rotation = 0;
7570
7571 break;
7572
7573 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007574 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007575 d = Bits32 (opcode, 11, 8);
7576 m = Bits32 (opcode, 3, 0);
7577 rotation = Bits32 (opcode, 5, 4) << 3;
7578
7579 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7580 if (BadReg (d) || BadReg (m))
7581 return false;
7582
7583 break;
7584
7585 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007586 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice6bf65162011-03-03 17:42:58 +00007587 d = Bits32 (opcode, 15, 12);
7588 m = Bits32 (opcode, 3, 0);
7589 rotation = Bits32 (opcode, 11, 10) << 3;
7590
7591 // if d == 15 || m == 15 then UNPREDICTABLE;
7592 if ((d == 15) || (m == 15))
7593 return false;
7594
7595 break;
7596
7597 default:
7598 return false;
7599 }
7600
Caroline Tice868198b2011-03-03 18:04:49 +00007601 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7602 if (!success)
7603 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007604
7605 // rotated = ROR(R[m], rotation);
7606 uint64_t rotated = ROR (Rm, rotation);
7607
7608 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007609 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007610
7611 Register source_reg;
7612 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7613
7614 EmulateInstruction::Context context;
7615 context.type = eContextRegisterLoad;
7616 context.SetRegister (source_reg);
7617
Caroline Tice8ce96d92011-03-03 18:27:17 +00007618 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007619 return false;
7620 }
7621 return true;
7622}
Caroline Tice291a3e92011-03-02 21:13:44 +00007623
Caroline Tice868198b2011-03-03 18:04:49 +00007624// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7625// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7626bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007627EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice868198b2011-03-03 18:04:49 +00007628{
7629#if 0
7630 if ConditionPassed() then
7631 EncodingSpecificOperations();
7632 rotated = ROR(R[m], rotation);
7633 R[d] = SignExtend(rotated<15:0>, 32);
7634#endif
7635
7636 bool success = false;
Caroline Tice868198b2011-03-03 18:04:49 +00007637
Greg Clayton7bc39082011-03-24 23:53:38 +00007638 if (ConditionPassed(opcode))
Caroline Tice868198b2011-03-03 18:04:49 +00007639 {
7640 uint32_t d;
7641 uint32_t m;
7642 uint32_t rotation;
7643
7644 // EncodingSpecificOperations();
7645 switch (encoding)
7646 {
7647 case eEncodingT1:
7648 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7649 d = Bits32 (opcode, 2, 0);
7650 m = Bits32 (opcode, 5, 3);
7651 rotation = 0;
7652
7653 break;
7654
7655 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007656 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007657 d = Bits32 (opcode, 11, 8);
7658 m = Bits32 (opcode, 3, 0);
7659 rotation = Bits32 (opcode, 5, 4) << 3;
7660
7661 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7662 if (BadReg (d) || BadReg (m))
7663 return false;
7664
7665 break;
7666
7667 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007668 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice868198b2011-03-03 18:04:49 +00007669 d = Bits32 (opcode, 15, 12);
7670 m = Bits32 (opcode, 3, 0);
7671 rotation = Bits32 (opcode, 11, 10) << 3;
7672
7673 // if d == 15 || m == 15 then UNPREDICTABLE;
7674 if ((d == 15) || (m == 15))
7675 return false;
7676
7677 break;
7678
7679 default:
7680 return false;
7681 }
7682
7683 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7684 if (!success)
7685 return false;
7686
7687 // rotated = ROR(R[m], rotation);
7688 uint64_t rotated = ROR (Rm, rotation);
7689
7690 // R[d] = SignExtend(rotated<15:0>, 32);
7691 Register source_reg;
7692 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7693
7694 EmulateInstruction::Context context;
7695 context.type = eContextRegisterLoad;
7696 context.SetRegister (source_reg);
7697
Caroline Tice8ce96d92011-03-03 18:27:17 +00007698 int64_t data = llvm::SignExtend64<16> (rotated);
7699 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007700 return false;
7701 }
7702
7703 return true;
7704}
7705
Caroline Tice8ce96d92011-03-03 18:27:17 +00007706// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7707// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7708bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007709EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice8ce96d92011-03-03 18:27:17 +00007710{
7711#if 0
7712 if ConditionPassed() then
7713 EncodingSpecificOperations();
7714 rotated = ROR(R[m], rotation);
7715 R[d] = ZeroExtend(rotated<7:0>, 32);
7716#endif
7717
7718 bool success = false;
Caroline Tice8ce96d92011-03-03 18:27:17 +00007719
Greg Clayton7bc39082011-03-24 23:53:38 +00007720 if (ConditionPassed(opcode))
Caroline Tice8ce96d92011-03-03 18:27:17 +00007721 {
7722 uint32_t d;
7723 uint32_t m;
7724 uint32_t rotation;
7725
7726 // EncodingSpecificOperations();
7727 switch (encoding)
7728 {
7729 case eEncodingT1:
7730 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7731 d = Bits32 (opcode, 2, 0);
7732 m = Bits32 (opcode, 5, 3);
7733 rotation = 0;
7734
7735 break;
7736
7737 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007738 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007739 d = Bits32 (opcode, 11, 8);
7740 m = Bits32 (opcode, 3, 0);
7741 rotation = Bits32 (opcode, 5, 4) << 3;
7742
7743 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7744 if (BadReg (d) || BadReg (m))
7745 return false;
7746
7747 break;
7748
7749 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007750 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice8ce96d92011-03-03 18:27:17 +00007751 d = Bits32 (opcode, 15, 12);
7752 m = Bits32 (opcode, 3, 0);
7753 rotation = Bits32 (opcode, 11, 10) << 3;
7754
7755 // if d == 15 || m == 15 then UNPREDICTABLE;
7756 if ((d == 15) || (m == 15))
7757 return false;
7758
7759 break;
7760
7761 default:
7762 return false;
7763 }
7764
7765 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7766 if (!success)
7767 return false;
7768
7769 // rotated = ROR(R[m], rotation);
7770 uint64_t rotated = ROR (Rm, rotation);
7771
7772 // R[d] = ZeroExtend(rotated<7:0>, 32);
7773 Register source_reg;
7774 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7775
7776 EmulateInstruction::Context context;
7777 context.type = eContextRegisterLoad;
7778 context.SetRegister (source_reg);
7779
7780 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7781 return false;
7782 }
7783 return true;
7784}
7785
Caroline Tice11555f22011-03-03 18:48:58 +00007786// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7787// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7788bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007789EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
Caroline Tice11555f22011-03-03 18:48:58 +00007790{
7791#if 0
7792 if ConditionPassed() then
7793 EncodingSpecificOperations();
7794 rotated = ROR(R[m], rotation);
7795 R[d] = ZeroExtend(rotated<15:0>, 32);
7796#endif
7797
7798 bool success = false;
Caroline Tice11555f22011-03-03 18:48:58 +00007799
Greg Clayton7bc39082011-03-24 23:53:38 +00007800 if (ConditionPassed(opcode))
Caroline Tice11555f22011-03-03 18:48:58 +00007801 {
7802 uint32_t d;
7803 uint32_t m;
7804 uint32_t rotation;
7805
7806 switch (encoding)
7807 {
7808 case eEncodingT1:
7809 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7810 d = Bits32 (opcode, 2, 0);
7811 m = Bits32 (opcode, 5, 3);
7812 rotation = 0;
7813
7814 break;
7815
7816 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007817 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007818 d = Bits32 (opcode, 11, 8);
7819 m = Bits32 (opcode, 3, 0);
7820 rotation = Bits32 (opcode, 5, 4) << 3;
7821
7822 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7823 if (BadReg (d) || BadReg (m))
7824 return false;
7825
7826 break;
7827
7828 case eEncodingA1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007829 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
Caroline Tice11555f22011-03-03 18:48:58 +00007830 d = Bits32 (opcode, 15, 12);
7831 m = Bits32 (opcode, 3, 0);
7832 rotation = Bits32 (opcode, 11, 10) << 3;
7833
7834 // if d == 15 || m == 15 then UNPREDICTABLE;
7835 if ((d == 15) || (m == 15))
7836 return false;
7837
7838 break;
7839
7840 default:
7841 return false;
7842 }
7843
7844 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7845 if (!success)
7846 return false;
7847
7848 // rotated = ROR(R[m], rotation);
7849 uint64_t rotated = ROR (Rm, rotation);
7850
7851 // R[d] = ZeroExtend(rotated<15:0>, 32);
7852 Register source_reg;
7853 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7854
7855 EmulateInstruction::Context context;
7856 context.type = eContextRegisterLoad;
7857 context.SetRegister (source_reg);
7858
7859 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7860 return false;
7861 }
7862 return true;
7863}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007864
7865// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7866// word respectively.
7867bool
Greg Clayton7bc39082011-03-24 23:53:38 +00007868EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticeb27771d2011-03-03 22:37:46 +00007869{
7870#if 0
7871 if ConditionPassed() then
7872 EncodingSpecificOperations();
7873 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7874 UNPREDICTABLE;
7875 else
7876 address = if increment then R[n] else R[n]-8;
7877 if wordhigher then address = address+4;
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007878 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007879 BranchWritePC(MemA[address,4]);
7880 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7881#endif
7882
7883 bool success = false;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007884
Greg Clayton7bc39082011-03-24 23:53:38 +00007885 if (ConditionPassed(opcode))
Caroline Ticeb27771d2011-03-03 22:37:46 +00007886 {
7887 uint32_t n;
7888 bool wback;
7889 bool increment;
7890 bool wordhigher;
7891
7892 // EncodingSpecificOperations();
7893 switch (encoding)
7894 {
7895 case eEncodingT1:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007896 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007897 n = Bits32 (opcode, 19, 16);
7898 wback = BitIsSet (opcode, 21);
7899 increment = false;
7900 wordhigher = false;
7901
7902 // if n == 15 then UNPREDICTABLE;
7903 if (n == 15)
7904 return false;
7905
7906 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7907 if (InITBlock() && !LastInITBlock())
7908 return false;
7909
7910 break;
7911
7912 case eEncodingT2:
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007913 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
Caroline Ticeb27771d2011-03-03 22:37:46 +00007914 n = Bits32 (opcode, 19, 16);
7915 wback = BitIsSet (opcode, 21);
7916 increment = true;
7917 wordhigher = false;
7918
7919 // if n == 15 then UNPREDICTABLE;
7920 if (n == 15)
7921 return false;
7922
7923 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7924 if (InITBlock() && !LastInITBlock())
7925 return false;
7926
7927 break;
7928
7929 case eEncodingA1:
7930 // n = UInt(Rn);
7931 n = Bits32 (opcode, 19, 16);
7932
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007933 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007934 wback = BitIsSet (opcode, 21);
7935 increment = BitIsSet (opcode, 23);
7936 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
7937
7938 // if n == 15 then UNPREDICTABLE;
7939 if (n == 15)
7940 return false;
7941
7942 break;
7943
7944 default:
7945 return false;
7946 }
7947
7948 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7949 if (!CurrentModeIsPrivileged ())
7950 // UNPREDICTABLE;
7951 return false;
7952 else
7953 {
7954 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7955 if (!success)
7956 return false;
7957
7958 addr_t address;
7959 // address = if increment then R[n] else R[n]-8;
7960 if (increment)
7961 address = Rn;
7962 else
7963 address = Rn - 8;
7964
7965 // if wordhigher then address = address+4;
7966 if (wordhigher)
7967 address = address + 4;
7968
Caroline Ticebb48f0b2011-03-28 16:10:45 +00007969 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
Caroline Ticeb27771d2011-03-03 22:37:46 +00007970 Register base_reg;
7971 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7972
7973 EmulateInstruction::Context context;
7974 context.type = eContextReturnFromException;
7975 context.SetRegisterPlusOffset (base_reg, address - Rn);
7976
7977 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
7978 if (!success)
7979 return false;
7980
7981 CPSRWriteByInstr (data, 15, true);
7982
7983 // BranchWritePC(MemA[address,4]);
7984 uint64_t data2 = MemARead (context, address, 4, 0, &success);
7985 if (!success)
7986 return false;
7987
7988 BranchWritePC (context, data2);
7989
7990 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7991 if (wback)
7992 {
7993 context.type = eContextAdjustBaseRegister;
7994 if (increment)
7995 {
7996 context.SetOffset (8);
7997 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
7998 return false;
7999 }
8000 else
8001 {
8002 context.SetOffset (-8);
8003 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8004 return false;
8005 }
8006 } // if wback
8007 }
8008 } // if ConditionPassed()
8009 return true;
8010}
Caroline Tice11555f22011-03-03 18:48:58 +00008011
Johnny Chen2115b412011-02-21 23:42:44 +00008012// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8013// and writes the result to the destination register. It can optionally update the condition flags based on
8014// the result.
8015bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008016EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008017{
8018#if 0
8019 // ARM pseudo code...
8020 if ConditionPassed() then
8021 EncodingSpecificOperations();
8022 result = R[n] EOR imm32;
8023 if d == 15 then // Can only occur for ARM encoding
8024 ALUWritePC(result); // setflags is always FALSE here
8025 else
8026 R[d] = result;
8027 if setflags then
8028 APSR.N = result<31>;
8029 APSR.Z = IsZeroBit(result);
8030 APSR.C = carry;
8031 // APSR.V unchanged
8032#endif
8033
8034 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008035
Greg Clayton7bc39082011-03-24 23:53:38 +00008036 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008037 {
8038 uint32_t Rd, Rn;
8039 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8040 bool setflags;
8041 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8042 switch (encoding)
8043 {
8044 case eEncodingT1:
8045 Rd = Bits32(opcode, 11, 8);
8046 Rn = Bits32(opcode, 19, 16);
8047 setflags = BitIsSet(opcode, 20);
8048 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8049 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8050 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008051 return EmulateTEQImm (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008052 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8053 return false;
8054 break;
8055 case eEncodingA1:
8056 Rd = Bits32(opcode, 15, 12);
8057 Rn = Bits32(opcode, 19, 16);
8058 setflags = BitIsSet(opcode, 20);
8059 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8060 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8061 // TODO: Emulate SUBS PC, LR and related instructions.
8062 if (Rd == 15 && setflags)
8063 return false;
8064 break;
8065 default:
8066 return false;
8067 }
8068
8069 // Read the first operand.
8070 uint32_t val1 = ReadCoreReg(Rn, &success);
8071 if (!success)
8072 return false;
8073
8074 uint32_t result = val1 ^ imm32;
8075
8076 EmulateInstruction::Context context;
8077 context.type = EmulateInstruction::eContextImmediate;
8078 context.SetNoArgs ();
8079
8080 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8081 return false;
8082 }
8083 return true;
8084}
8085
8086// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8087// optionally-shifted register value, and writes the result to the destination register.
8088// It can optionally update the condition flags based on the result.
8089bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008090EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008091{
8092#if 0
8093 // ARM pseudo code...
8094 if ConditionPassed() then
8095 EncodingSpecificOperations();
8096 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8097 result = R[n] EOR shifted;
8098 if d == 15 then // Can only occur for ARM encoding
8099 ALUWritePC(result); // setflags is always FALSE here
8100 else
8101 R[d] = result;
8102 if setflags then
8103 APSR.N = result<31>;
8104 APSR.Z = IsZeroBit(result);
8105 APSR.C = carry;
8106 // APSR.V unchanged
8107#endif
8108
8109 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008110
Greg Clayton7bc39082011-03-24 23:53:38 +00008111 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008112 {
8113 uint32_t Rd, Rn, Rm;
8114 ARM_ShifterType shift_t;
8115 uint32_t shift_n; // the shift applied to the value read from Rm
8116 bool setflags;
8117 uint32_t carry;
8118 switch (encoding)
8119 {
8120 case eEncodingT1:
8121 Rd = Rn = Bits32(opcode, 2, 0);
8122 Rm = Bits32(opcode, 5, 3);
8123 setflags = !InITBlock();
8124 shift_t = SRType_LSL;
8125 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008126 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008127 case eEncodingT2:
8128 Rd = Bits32(opcode, 11, 8);
8129 Rn = Bits32(opcode, 19, 16);
8130 Rm = Bits32(opcode, 3, 0);
8131 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008132 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8133 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008134 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008135 return EmulateTEQReg (opcode, eEncodingT1);
Johnny Chen2115b412011-02-21 23:42:44 +00008136 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8137 return false;
8138 break;
8139 case eEncodingA1:
8140 Rd = Bits32(opcode, 15, 12);
8141 Rn = Bits32(opcode, 19, 16);
8142 Rm = Bits32(opcode, 3, 0);
8143 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008144 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008145 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8146 // TODO: Emulate SUBS PC, LR and related instructions.
8147 if (Rd == 15 && setflags)
8148 return false;
8149 break;
8150 default:
8151 return false;
8152 }
8153
8154 // Read the first operand.
8155 uint32_t val1 = ReadCoreReg(Rn, &success);
8156 if (!success)
8157 return false;
8158
8159 // Read the second operand.
8160 uint32_t val2 = ReadCoreReg(Rm, &success);
8161 if (!success)
8162 return false;
8163
8164 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8165 uint32_t result = val1 ^ shifted;
8166
8167 EmulateInstruction::Context context;
8168 context.type = EmulateInstruction::eContextImmediate;
8169 context.SetNoArgs ();
8170
8171 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8172 return false;
8173 }
8174 return true;
8175}
8176
Johnny Chen7c5234d2011-02-18 23:41:11 +00008177// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8178// writes the result to the destination register. It can optionally update the condition flags based
8179// on the result.
8180bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008181EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008182{
8183#if 0
8184 // ARM pseudo code...
8185 if ConditionPassed() then
8186 EncodingSpecificOperations();
8187 result = R[n] OR imm32;
8188 if d == 15 then // Can only occur for ARM encoding
8189 ALUWritePC(result); // setflags is always FALSE here
8190 else
8191 R[d] = result;
8192 if setflags then
8193 APSR.N = result<31>;
8194 APSR.Z = IsZeroBit(result);
8195 APSR.C = carry;
8196 // APSR.V unchanged
8197#endif
8198
8199 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008200
Greg Clayton7bc39082011-03-24 23:53:38 +00008201 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008202 {
8203 uint32_t Rd, Rn;
8204 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8205 bool setflags;
8206 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8207 switch (encoding)
8208 {
8209 case eEncodingT1:
8210 Rd = Bits32(opcode, 11, 8);
8211 Rn = Bits32(opcode, 19, 16);
8212 setflags = BitIsSet(opcode, 20);
8213 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008214 // if Rn == '1111' then SEE MOV (immediate);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008215 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008216 return EmulateMOVRdImm (opcode, eEncodingT2);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008217 if (BadReg(Rd) || Rn == 13)
8218 return false;
8219 break;
8220 case eEncodingA1:
8221 Rd = Bits32(opcode, 15, 12);
8222 Rn = Bits32(opcode, 19, 16);
8223 setflags = BitIsSet(opcode, 20);
8224 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8225 // TODO: Emulate SUBS PC, LR and related instructions.
8226 if (Rd == 15 && setflags)
8227 return false;
8228 break;
8229 default:
8230 return false;
8231 }
8232
8233 // Read the first operand.
8234 uint32_t val1 = ReadCoreReg(Rn, &success);
8235 if (!success)
8236 return false;
8237
8238 uint32_t result = val1 | imm32;
8239
8240 EmulateInstruction::Context context;
8241 context.type = EmulateInstruction::eContextImmediate;
8242 context.SetNoArgs ();
8243
8244 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8245 return false;
8246 }
8247 return true;
8248}
8249
8250// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8251// value, and writes the result to the destination register. It can optionally update the condition flags based
8252// on the result.
8253bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008254EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen7c5234d2011-02-18 23:41:11 +00008255{
8256#if 0
8257 // ARM pseudo code...
8258 if ConditionPassed() then
8259 EncodingSpecificOperations();
8260 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8261 result = R[n] OR shifted;
8262 if d == 15 then // Can only occur for ARM encoding
8263 ALUWritePC(result); // setflags is always FALSE here
8264 else
8265 R[d] = result;
8266 if setflags then
8267 APSR.N = result<31>;
8268 APSR.Z = IsZeroBit(result);
8269 APSR.C = carry;
8270 // APSR.V unchanged
8271#endif
8272
8273 bool success = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008274
Greg Clayton7bc39082011-03-24 23:53:38 +00008275 if (ConditionPassed(opcode))
Johnny Chen7c5234d2011-02-18 23:41:11 +00008276 {
8277 uint32_t Rd, Rn, Rm;
8278 ARM_ShifterType shift_t;
8279 uint32_t shift_n; // the shift applied to the value read from Rm
8280 bool setflags;
8281 uint32_t carry;
8282 switch (encoding)
8283 {
8284 case eEncodingT1:
8285 Rd = Rn = Bits32(opcode, 2, 0);
8286 Rm = Bits32(opcode, 5, 3);
8287 setflags = !InITBlock();
8288 shift_t = SRType_LSL;
8289 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008290 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008291 case eEncodingT2:
8292 Rd = Bits32(opcode, 11, 8);
8293 Rn = Bits32(opcode, 19, 16);
8294 Rm = Bits32(opcode, 3, 0);
8295 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008296 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8297 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008298 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008299 return EmulateMOVRdRm (opcode, eEncodingT3);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008300 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8301 return false;
8302 break;
8303 case eEncodingA1:
8304 Rd = Bits32(opcode, 15, 12);
8305 Rn = Bits32(opcode, 19, 16);
8306 Rm = Bits32(opcode, 3, 0);
8307 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008308 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008309 // TODO: Emulate SUBS PC, LR and related instructions.
8310 if (Rd == 15 && setflags)
8311 return false;
8312 break;
8313 default:
8314 return false;
8315 }
8316
8317 // Read the first operand.
8318 uint32_t val1 = ReadCoreReg(Rn, &success);
8319 if (!success)
8320 return false;
8321
8322 // Read the second operand.
8323 uint32_t val2 = ReadCoreReg(Rm, &success);
8324 if (!success)
8325 return false;
8326
8327 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008328 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008329
8330 EmulateInstruction::Context context;
8331 context.type = EmulateInstruction::eContextImmediate;
8332 context.SetNoArgs ();
8333
8334 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8335 return false;
8336 }
8337 return true;
8338}
8339
Johnny Chened32e7c2011-02-22 23:42:58 +00008340// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8341// the destination register. It can optionally update the condition flags based on the result.
8342bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008343EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008344{
8345#if 0
8346 // ARM pseudo code...
8347 if ConditionPassed() then
8348 EncodingSpecificOperations();
8349 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8350 if d == 15 then // Can only occur for ARM encoding
8351 ALUWritePC(result); // setflags is always FALSE here
8352 else
8353 R[d] = result;
8354 if setflags then
8355 APSR.N = result<31>;
8356 APSR.Z = IsZeroBit(result);
8357 APSR.C = carry;
8358 APSR.V = overflow;
8359#endif
8360
8361 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008362
8363 uint32_t Rd; // the destination register
8364 uint32_t Rn; // the first operand
8365 bool setflags;
8366 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8367 switch (encoding) {
8368 case eEncodingT1:
8369 Rd = Bits32(opcode, 2, 0);
8370 Rn = Bits32(opcode, 5, 3);
8371 setflags = !InITBlock();
8372 imm32 = 0;
8373 break;
8374 case eEncodingT2:
8375 Rd = Bits32(opcode, 11, 8);
8376 Rn = Bits32(opcode, 19, 16);
8377 setflags = BitIsSet(opcode, 20);
8378 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8379 if (BadReg(Rd) || BadReg(Rn))
8380 return false;
8381 break;
8382 case eEncodingA1:
8383 Rd = Bits32(opcode, 15, 12);
8384 Rn = Bits32(opcode, 19, 16);
8385 setflags = BitIsSet(opcode, 20);
8386 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8387 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8388 // TODO: Emulate SUBS PC, LR and related instructions.
8389 if (Rd == 15 && setflags)
8390 return false;
8391 break;
8392 default:
8393 return false;
8394 }
8395 // Read the register value from the operand register Rn.
8396 uint32_t reg_val = ReadCoreReg(Rn, &success);
8397 if (!success)
8398 return false;
8399
8400 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8401
8402 EmulateInstruction::Context context;
8403 context.type = EmulateInstruction::eContextImmediate;
8404 context.SetNoArgs ();
8405
8406 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8407 return false;
8408
8409 return true;
8410}
8411
8412// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8413// result to the destination register. It can optionally update the condition flags based on the result.
8414bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008415EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chened32e7c2011-02-22 23:42:58 +00008416{
8417#if 0
8418 // ARM pseudo code...
8419 if ConditionPassed() then
8420 EncodingSpecificOperations();
8421 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8422 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8423 if d == 15 then // Can only occur for ARM encoding
8424 ALUWritePC(result); // setflags is always FALSE here
8425 else
8426 R[d] = result;
8427 if setflags then
8428 APSR.N = result<31>;
8429 APSR.Z = IsZeroBit(result);
8430 APSR.C = carry;
8431 APSR.V = overflow;
8432#endif
8433
8434 bool success = false;
Johnny Chened32e7c2011-02-22 23:42:58 +00008435
8436 uint32_t Rd; // the destination register
8437 uint32_t Rn; // the first operand
8438 uint32_t Rm; // the second operand
8439 bool setflags;
8440 ARM_ShifterType shift_t;
8441 uint32_t shift_n; // the shift applied to the value read from Rm
8442 switch (encoding) {
8443 case eEncodingT1:
8444 Rd = Bits32(opcode, 11, 8);
8445 Rn = Bits32(opcode, 19, 16);
8446 Rm = Bits32(opcode, 3, 0);
8447 setflags = BitIsSet(opcode, 20);
8448 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8449 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8450 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8451 return false;
8452 break;
8453 case eEncodingA1:
8454 Rd = Bits32(opcode, 15, 12);
8455 Rn = Bits32(opcode, 19, 16);
8456 Rm = Bits32(opcode, 3, 0);
8457 setflags = BitIsSet(opcode, 20);
8458 shift_n = DecodeImmShiftARM(opcode, shift_t);
8459 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8460 // TODO: Emulate SUBS PC, LR and related instructions.
8461 if (Rd == 15 && setflags)
8462 return false;
8463 break;
8464 default:
8465 return false;
8466 }
8467 // Read the register value from register Rn.
8468 uint32_t val1 = ReadCoreReg(Rn, &success);
8469 if (!success)
8470 return false;
8471
8472 // Read the register value from register Rm.
8473 uint32_t val2 = ReadCoreReg(Rm, &success);
8474 if (!success)
8475 return false;
8476
8477 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8478 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8479
8480 EmulateInstruction::Context context;
8481 context.type = EmulateInstruction::eContextImmediate;
8482 context.SetNoArgs();
8483 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8484 return false;
8485
8486 return true;
8487}
8488
Johnny Chen90e607b2011-02-23 00:07:09 +00008489// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8490// an immediate value, and writes the result to the destination register. It can optionally update the condition
8491// flags based on the result.
8492bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008493EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008494{
8495#if 0
8496 // ARM pseudo code...
8497 if ConditionPassed() then
8498 EncodingSpecificOperations();
8499 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8500 if d == 15 then
8501 ALUWritePC(result); // setflags is always FALSE here
8502 else
8503 R[d] = result;
8504 if setflags then
8505 APSR.N = result<31>;
8506 APSR.Z = IsZeroBit(result);
8507 APSR.C = carry;
8508 APSR.V = overflow;
8509#endif
8510
8511 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008512
8513 uint32_t Rd; // the destination register
8514 uint32_t Rn; // the first operand
8515 bool setflags;
8516 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8517 switch (encoding) {
8518 case eEncodingA1:
8519 Rd = Bits32(opcode, 15, 12);
8520 Rn = Bits32(opcode, 19, 16);
8521 setflags = BitIsSet(opcode, 20);
8522 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8523 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8524 // TODO: Emulate SUBS PC, LR and related instructions.
8525 if (Rd == 15 && setflags)
8526 return false;
8527 break;
8528 default:
8529 return false;
8530 }
8531 // Read the register value from the operand register Rn.
8532 uint32_t reg_val = ReadCoreReg(Rn, &success);
8533 if (!success)
8534 return false;
8535
8536 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8537
8538 EmulateInstruction::Context context;
8539 context.type = EmulateInstruction::eContextImmediate;
8540 context.SetNoArgs ();
8541
8542 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8543 return false;
8544
8545 return true;
8546}
8547
8548// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8549// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8550// condition flags based on the result.
8551bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008552EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen90e607b2011-02-23 00:07:09 +00008553{
8554#if 0
8555 // ARM pseudo code...
8556 if ConditionPassed() then
8557 EncodingSpecificOperations();
8558 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8559 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8560 if d == 15 then
8561 ALUWritePC(result); // setflags is always FALSE here
8562 else
8563 R[d] = result;
8564 if setflags then
8565 APSR.N = result<31>;
8566 APSR.Z = IsZeroBit(result);
8567 APSR.C = carry;
8568 APSR.V = overflow;
8569#endif
8570
8571 bool success = false;
Johnny Chen90e607b2011-02-23 00:07:09 +00008572
8573 uint32_t Rd; // the destination register
8574 uint32_t Rn; // the first operand
8575 uint32_t Rm; // the second operand
8576 bool setflags;
8577 ARM_ShifterType shift_t;
8578 uint32_t shift_n; // the shift applied to the value read from Rm
8579 switch (encoding) {
8580 case eEncodingA1:
8581 Rd = Bits32(opcode, 15, 12);
8582 Rn = Bits32(opcode, 19, 16);
8583 Rm = Bits32(opcode, 3, 0);
8584 setflags = BitIsSet(opcode, 20);
8585 shift_n = DecodeImmShiftARM(opcode, shift_t);
8586 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8587 // TODO: Emulate SUBS PC, LR and related instructions.
8588 if (Rd == 15 && setflags)
8589 return false;
8590 break;
8591 default:
8592 return false;
8593 }
8594 // Read the register value from register Rn.
8595 uint32_t val1 = ReadCoreReg(Rn, &success);
8596 if (!success)
8597 return false;
8598
8599 // Read the register value from register Rm.
8600 uint32_t val2 = ReadCoreReg(Rm, &success);
8601 if (!success)
8602 return false;
8603
8604 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8605 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8606
8607 EmulateInstruction::Context context;
8608 context.type = EmulateInstruction::eContextImmediate;
8609 context.SetNoArgs();
8610 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8611 return false;
8612
8613 return true;
8614}
8615
Johnny Chen9b381772011-02-23 01:01:21 +00008616// Subtract with Carry (immediate) subtracts an immediate value and the value of
8617// NOT (Carry flag) from a register value, and writes the result to the destination register.
8618// It can optionally update the condition flags based on the result.
8619bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008620EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008621{
8622#if 0
8623 // ARM pseudo code...
8624 if ConditionPassed() then
8625 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008626 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008627 if d == 15 then // Can only occur for ARM encoding
8628 ALUWritePC(result); // setflags is always FALSE here
8629 else
8630 R[d] = result;
8631 if setflags then
8632 APSR.N = result<31>;
8633 APSR.Z = IsZeroBit(result);
8634 APSR.C = carry;
8635 APSR.V = overflow;
8636#endif
8637
8638 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008639
8640 uint32_t Rd; // the destination register
8641 uint32_t Rn; // the first operand
8642 bool setflags;
8643 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8644 switch (encoding) {
8645 case eEncodingT1:
8646 Rd = Bits32(opcode, 11, 8);
8647 Rn = Bits32(opcode, 19, 16);
8648 setflags = BitIsSet(opcode, 20);
8649 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8650 if (BadReg(Rd) || BadReg(Rn))
8651 return false;
8652 break;
8653 case eEncodingA1:
8654 Rd = Bits32(opcode, 15, 12);
8655 Rn = Bits32(opcode, 19, 16);
8656 setflags = BitIsSet(opcode, 20);
8657 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8658 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8659 // TODO: Emulate SUBS PC, LR and related instructions.
8660 if (Rd == 15 && setflags)
8661 return false;
8662 break;
8663 default:
8664 return false;
8665 }
8666 // Read the register value from the operand register Rn.
8667 uint32_t reg_val = ReadCoreReg(Rn, &success);
8668 if (!success)
8669 return false;
8670
8671 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8672
8673 EmulateInstruction::Context context;
8674 context.type = EmulateInstruction::eContextImmediate;
8675 context.SetNoArgs ();
8676
8677 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8678 return false;
8679
8680 return true;
8681}
8682
8683// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8684// NOT (Carry flag) from a register value, and writes the result to the destination register.
8685// It can optionally update the condition flags based on the result.
8686bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008687EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen9b381772011-02-23 01:01:21 +00008688{
8689#if 0
8690 // ARM pseudo code...
8691 if ConditionPassed() then
8692 EncodingSpecificOperations();
8693 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8694 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8695 if d == 15 then // Can only occur for ARM encoding
8696 ALUWritePC(result); // setflags is always FALSE here
8697 else
8698 R[d] = result;
8699 if setflags then
8700 APSR.N = result<31>;
8701 APSR.Z = IsZeroBit(result);
8702 APSR.C = carry;
8703 APSR.V = overflow;
8704#endif
8705
8706 bool success = false;
Johnny Chen9b381772011-02-23 01:01:21 +00008707
8708 uint32_t Rd; // the destination register
8709 uint32_t Rn; // the first operand
8710 uint32_t Rm; // the second operand
8711 bool setflags;
8712 ARM_ShifterType shift_t;
8713 uint32_t shift_n; // the shift applied to the value read from Rm
8714 switch (encoding) {
8715 case eEncodingT1:
8716 Rd = Rn = Bits32(opcode, 2, 0);
8717 Rm = Bits32(opcode, 5, 3);
8718 setflags = !InITBlock();
8719 shift_t = SRType_LSL;
8720 shift_n = 0;
8721 break;
8722 case eEncodingT2:
8723 Rd = Bits32(opcode, 11, 8);
8724 Rn = Bits32(opcode, 19, 16);
8725 Rm = Bits32(opcode, 3, 0);
8726 setflags = BitIsSet(opcode, 20);
8727 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8728 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8729 return false;
8730 break;
8731 case eEncodingA1:
8732 Rd = Bits32(opcode, 15, 12);
8733 Rn = Bits32(opcode, 19, 16);
8734 Rm = Bits32(opcode, 3, 0);
8735 setflags = BitIsSet(opcode, 20);
8736 shift_n = DecodeImmShiftARM(opcode, shift_t);
8737 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8738 // TODO: Emulate SUBS PC, LR and related instructions.
8739 if (Rd == 15 && setflags)
8740 return false;
8741 break;
8742 default:
8743 return false;
8744 }
8745 // Read the register value from register Rn.
8746 uint32_t val1 = ReadCoreReg(Rn, &success);
8747 if (!success)
8748 return false;
8749
8750 // Read the register value from register Rm.
8751 uint32_t val2 = ReadCoreReg(Rm, &success);
8752 if (!success)
8753 return false;
8754
8755 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8756 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8757
8758 EmulateInstruction::Context context;
8759 context.type = EmulateInstruction::eContextImmediate;
8760 context.SetNoArgs();
8761 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8762 return false;
8763
8764 return true;
8765}
8766
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008767// This instruction subtracts an immediate value from a register value, and writes the result
8768// to the destination register. It can optionally update the condition flags based on the result.
8769bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008770EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008771{
8772#if 0
8773 // ARM pseudo code...
8774 if ConditionPassed() then
8775 EncodingSpecificOperations();
8776 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8777 R[d] = result;
8778 if setflags then
8779 APSR.N = result<31>;
8780 APSR.Z = IsZeroBit(result);
8781 APSR.C = carry;
8782 APSR.V = overflow;
8783#endif
8784
8785 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008786
8787 uint32_t Rd; // the destination register
8788 uint32_t Rn; // the first operand
8789 bool setflags;
8790 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8791 switch (encoding) {
8792 case eEncodingT1:
8793 Rd = Bits32(opcode, 2, 0);
8794 Rn = Bits32(opcode, 5, 3);
8795 setflags = !InITBlock();
8796 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8797 break;
8798 case eEncodingT2:
8799 Rd = Rn = Bits32(opcode, 10, 8);
8800 setflags = !InITBlock();
8801 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8802 break;
8803 case eEncodingT3:
8804 Rd = Bits32(opcode, 11, 8);
8805 Rn = Bits32(opcode, 19, 16);
8806 setflags = BitIsSet(opcode, 20);
8807 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8808
8809 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8810 if (Rd == 15 && setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008811 return EmulateCMPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008812
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008813 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008814 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008815 return EmulateSUBSPImm (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008816
8817 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8818 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8819 return false;
8820 break;
8821 case eEncodingT4:
8822 Rd = Bits32(opcode, 11, 8);
8823 Rn = Bits32(opcode, 19, 16);
8824 setflags = BitIsSet(opcode, 20);
8825 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8826
8827 // if Rn == '1111' then SEE ADR;
8828 if (Rn == 15)
Greg Clayton7bc39082011-03-24 23:53:38 +00008829 return EmulateADR (opcode, eEncodingT2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008830
8831 // if Rn == '1101' then SEE SUB (SP minus immediate);
8832 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008833 return EmulateSUBSPImm (opcode, eEncodingT3);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008834
8835 if (BadReg(Rd))
8836 return false;
8837 break;
8838 default:
8839 return false;
8840 }
8841 // Read the register value from the operand register Rn.
8842 uint32_t reg_val = ReadCoreReg(Rn, &success);
8843 if (!success)
8844 return false;
8845
8846 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8847
8848 EmulateInstruction::Context context;
8849 context.type = EmulateInstruction::eContextImmediate;
8850 context.SetNoArgs ();
8851
8852 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8853 return false;
8854
8855 return true;
8856}
8857
8858// This instruction subtracts an immediate value from a register value, and writes the result
8859// to the destination register. It can optionally update the condition flags based on the result.
8860bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008861EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008862{
8863#if 0
8864 // ARM pseudo code...
8865 if ConditionPassed() then
8866 EncodingSpecificOperations();
8867 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8868 if d == 15 then
8869 ALUWritePC(result); // setflags is always FALSE here
8870 else
8871 R[d] = result;
8872 if setflags then
8873 APSR.N = result<31>;
8874 APSR.Z = IsZeroBit(result);
8875 APSR.C = carry;
8876 APSR.V = overflow;
8877#endif
8878
8879 bool success = false;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008880
8881 uint32_t Rd; // the destination register
8882 uint32_t Rn; // the first operand
8883 bool setflags;
8884 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8885 switch (encoding) {
8886 case eEncodingA1:
8887 Rd = Bits32(opcode, 15, 12);
8888 Rn = Bits32(opcode, 19, 16);
8889 setflags = BitIsSet(opcode, 20);
8890 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8891
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008892 // if Rn == '1111' && S == '0' then SEE ADR;
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008893 if (Rn == 15 && !setflags)
Greg Clayton7bc39082011-03-24 23:53:38 +00008894 return EmulateADR (opcode, eEncodingA2);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008895
Caroline Ticebb48f0b2011-03-28 16:10:45 +00008896 // if Rn == '1101' then SEE SUB (SP minus immediate);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008897 if (Rn == 13)
Greg Clayton7bc39082011-03-24 23:53:38 +00008898 return EmulateSUBSPImm (opcode, eEncodingA1);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008899
8900 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8901 // TODO: Emulate SUBS PC, LR and related instructions.
8902 if (Rd == 15 && setflags)
8903 return false;
8904 break;
8905 default:
8906 return false;
8907 }
8908 // Read the register value from the operand register Rn.
8909 uint32_t reg_val = ReadCoreReg(Rn, &success);
8910 if (!success)
8911 return false;
8912
8913 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8914
8915 EmulateInstruction::Context context;
8916 context.type = EmulateInstruction::eContextImmediate;
8917 context.SetNoArgs ();
8918
8919 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8920 return false;
8921
8922 return true;
8923}
8924
Johnny Chen2115b412011-02-21 23:42:44 +00008925// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8926// immediate value. It updates the condition flags based on the result, and discards the result.
8927bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008928EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008929{
8930#if 0
8931 // ARM pseudo code...
8932 if ConditionPassed() then
8933 EncodingSpecificOperations();
8934 result = R[n] EOR imm32;
8935 APSR.N = result<31>;
8936 APSR.Z = IsZeroBit(result);
8937 APSR.C = carry;
8938 // APSR.V unchanged
8939#endif
8940
8941 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00008942
Greg Clayton7bc39082011-03-24 23:53:38 +00008943 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00008944 {
8945 uint32_t Rn;
8946 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8947 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8948 switch (encoding)
8949 {
8950 case eEncodingT1:
8951 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008952 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008953 if (BadReg(Rn))
8954 return false;
8955 break;
8956 case eEncodingA1:
8957 Rn = Bits32(opcode, 19, 16);
Greg Clayton7bc39082011-03-24 23:53:38 +00008958 imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
Johnny Chen2115b412011-02-21 23:42:44 +00008959 break;
8960 default:
8961 return false;
8962 }
8963
8964 // Read the first operand.
8965 uint32_t val1 = ReadCoreReg(Rn, &success);
8966 if (!success)
8967 return false;
8968
8969 uint32_t result = val1 ^ imm32;
8970
8971 EmulateInstruction::Context context;
8972 context.type = EmulateInstruction::eContextImmediate;
8973 context.SetNoArgs ();
8974
8975 if (!WriteFlags(context, result, carry))
8976 return false;
8977 }
8978 return true;
8979}
8980
8981// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8982// optionally-shifted register value. It updates the condition flags based on the result, and discards
8983// the result.
8984bool
Greg Clayton7bc39082011-03-24 23:53:38 +00008985EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chen2115b412011-02-21 23:42:44 +00008986{
8987#if 0
8988 // ARM pseudo code...
8989 if ConditionPassed() then
8990 EncodingSpecificOperations();
8991 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8992 result = R[n] EOR shifted;
8993 APSR.N = result<31>;
8994 APSR.Z = IsZeroBit(result);
8995 APSR.C = carry;
8996 // APSR.V unchanged
8997#endif
8998
8999 bool success = false;
Johnny Chen2115b412011-02-21 23:42:44 +00009000
Greg Clayton7bc39082011-03-24 23:53:38 +00009001 if (ConditionPassed(opcode))
Johnny Chen2115b412011-02-21 23:42:44 +00009002 {
9003 uint32_t Rn, Rm;
9004 ARM_ShifterType shift_t;
9005 uint32_t shift_n; // the shift applied to the value read from Rm
9006 uint32_t carry;
9007 switch (encoding)
9008 {
9009 case eEncodingT1:
9010 Rn = Bits32(opcode, 19, 16);
9011 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009012 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009013 if (BadReg(Rn) || BadReg(Rm))
9014 return false;
9015 break;
9016 case eEncodingA1:
9017 Rn = Bits32(opcode, 19, 16);
9018 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009019 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009020 break;
9021 default:
9022 return false;
9023 }
9024
9025 // Read the first operand.
9026 uint32_t val1 = ReadCoreReg(Rn, &success);
9027 if (!success)
9028 return false;
9029
9030 // Read the second operand.
9031 uint32_t val2 = ReadCoreReg(Rm, &success);
9032 if (!success)
9033 return false;
9034
9035 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9036 uint32_t result = val1 ^ shifted;
9037
9038 EmulateInstruction::Context context;
9039 context.type = EmulateInstruction::eContextImmediate;
9040 context.SetNoArgs ();
9041
9042 if (!WriteFlags(context, result, carry))
9043 return false;
9044 }
9045 return true;
9046}
9047
Johnny Chende3cce32011-02-21 21:24:49 +00009048// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9049// It updates the condition flags based on the result, and discards the result.
9050bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009051EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009052{
9053#if 0
9054 // ARM pseudo code...
9055 if ConditionPassed() then
9056 EncodingSpecificOperations();
9057 result = R[n] AND imm32;
9058 APSR.N = result<31>;
9059 APSR.Z = IsZeroBit(result);
9060 APSR.C = carry;
9061 // APSR.V unchanged
9062#endif
9063
9064 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009065
Greg Clayton7bc39082011-03-24 23:53:38 +00009066 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009067 {
9068 uint32_t Rn;
9069 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9070 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9071 switch (encoding)
9072 {
9073 case eEncodingT1:
9074 Rn = Bits32(opcode, 19, 16);
9075 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9076 if (BadReg(Rn))
9077 return false;
9078 break;
9079 case eEncodingA1:
9080 Rn = Bits32(opcode, 19, 16);
9081 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9082 break;
9083 default:
9084 return false;
9085 }
9086
9087 // Read the first operand.
9088 uint32_t val1 = ReadCoreReg(Rn, &success);
9089 if (!success)
9090 return false;
9091
9092 uint32_t result = val1 & imm32;
9093
9094 EmulateInstruction::Context context;
9095 context.type = EmulateInstruction::eContextImmediate;
9096 context.SetNoArgs ();
9097
9098 if (!WriteFlags(context, result, carry))
9099 return false;
9100 }
9101 return true;
9102}
9103
9104// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9105// It updates the condition flags based on the result, and discards the result.
9106bool
Greg Clayton7bc39082011-03-24 23:53:38 +00009107EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
Johnny Chende3cce32011-02-21 21:24:49 +00009108{
9109#if 0
9110 // ARM pseudo code...
9111 if ConditionPassed() then
9112 EncodingSpecificOperations();
9113 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9114 result = R[n] AND shifted;
9115 APSR.N = result<31>;
9116 APSR.Z = IsZeroBit(result);
9117 APSR.C = carry;
9118 // APSR.V unchanged
9119#endif
9120
9121 bool success = false;
Johnny Chende3cce32011-02-21 21:24:49 +00009122
Greg Clayton7bc39082011-03-24 23:53:38 +00009123 if (ConditionPassed(opcode))
Johnny Chende3cce32011-02-21 21:24:49 +00009124 {
9125 uint32_t Rn, Rm;
9126 ARM_ShifterType shift_t;
9127 uint32_t shift_n; // the shift applied to the value read from Rm
9128 uint32_t carry;
9129 switch (encoding)
9130 {
9131 case eEncodingT1:
9132 Rn = Bits32(opcode, 2, 0);
9133 Rm = Bits32(opcode, 5, 3);
9134 shift_t = SRType_LSL;
9135 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009136 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009137 case eEncodingT2:
9138 Rn = Bits32(opcode, 19, 16);
9139 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009140 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009141 if (BadReg(Rn) || BadReg(Rm))
9142 return false;
9143 break;
9144 case eEncodingA1:
9145 Rn = Bits32(opcode, 19, 16);
9146 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009147 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009148 break;
9149 default:
9150 return false;
9151 }
9152
9153 // Read the first operand.
9154 uint32_t val1 = ReadCoreReg(Rn, &success);
9155 if (!success)
9156 return false;
9157
9158 // Read the second operand.
9159 uint32_t val2 = ReadCoreReg(Rm, &success);
9160 if (!success)
9161 return false;
9162
9163 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9164 uint32_t result = val1 & shifted;
9165
9166 EmulateInstruction::Context context;
9167 context.type = EmulateInstruction::eContextImmediate;
9168 context.SetNoArgs ();
9169
9170 if (!WriteFlags(context, result, carry))
9171 return false;
9172 }
9173 return true;
9174}
Caroline Ticed05b4902011-03-29 21:24:06 +00009175
9176// A8.6.216 SUB (SP minus register)
9177bool
9178EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
9179{
9180#if 0
9181 if ConditionPassed() then
9182 EncodingSpecificOperations();
9183 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9184 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), 1’);
9185 if d == 15 then // Can only occur for ARM encoding
9186 ALUWritePC(result); // setflags is always FALSE here
9187 else
9188 R[d] = result;
9189 if setflags then
9190 APSR.N = result<31>;
9191 APSR.Z = IsZeroBit(result);
9192 APSR.C = carry;
9193 APSR.V = overflow;
9194#endif
9195
9196 bool success = false;
9197
9198 if (ConditionPassed(opcode))
9199 {
9200 uint32_t d;
9201 uint32_t m;
9202 bool setflags;
9203 ARM_ShifterType shift_t;
9204 uint32_t shift_n;
9205
9206 switch (encoding)
9207 {
9208 case eEncodingT1:
9209 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9210 d = Bits32 (opcode, 11, 8);
9211 m = Bits32 (opcode, 3, 0);
9212 setflags = BitIsSet (opcode, 20);
9213
9214 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9215 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9216
9217 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
9218 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
9219 return false;
9220
9221 // if d == 15 || BadReg(m) then UNPREDICTABLE;
9222 if ((d == 15) || BadReg (m))
9223 return false;
9224 break;
9225
9226 case eEncodingA1:
9227 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9228 // d = UInt(Rd); m = UInt(Rm); setflags = (S == ‘1’);
9229 d = Bits32 (opcode, 15, 12);
9230 m = Bits32 (opcode, 3, 0);
9231 setflags = BitIsSet (opcode, 20);
9232
9233 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9234 shift_n = DecodeImmShiftARM (opcode, shift_t);
9235 break;
9236
9237 default:
9238 return false;
9239 }
9240
9241 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9242 uint32_t Rm = ReadCoreReg (m, &success);
9243 if (!success)
9244 return false;
9245
9246 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9247
9248 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), ‘1’);
9249 uint32_t sp_val = ReadCoreReg (SP_REG, &success);
9250 if (!success)
9251 return false;
9252
9253 AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
9254
9255 EmulateInstruction::Context context;
9256 context.type = eContextSubtraction;
9257 Register sp_reg;
9258 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
9259 Register dwarf_reg;
9260 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
9261 context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
9262
Caroline Ticeef440002011-03-30 05:40:56 +00009263 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Ticed05b4902011-03-29 21:24:06 +00009264 return false;
9265 }
9266 return true;
9267}
9268
9269
9270// A8.6.7 ADD (register-shifted register)
9271bool
Caroline Ticec08ed382011-03-29 23:03:16 +00009272EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
Caroline Ticed05b4902011-03-29 21:24:06 +00009273{
9274#if 0
Caroline Ticec08ed382011-03-29 23:03:16 +00009275 if ConditionPassed() then
9276 EncodingSpecificOperations();
9277 shift_n = UInt(R[s]<7:0>);
9278 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9279 (result, carry, overflow) = AddWithCarry(R[n], shifted, 0’);
9280 R[d] = result;
9281 if setflags then
9282 APSR.N = result<31>;
9283 APSR.Z = IsZeroBit(result);
9284 APSR.C = carry;
9285 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009286#endif
9287
Caroline Ticec08ed382011-03-29 23:03:16 +00009288 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009289
9290 if (ConditionPassed(opcode))
9291 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009292 uint32_t d;
9293 uint32_t n;
9294 uint32_t m;
9295 uint32_t s;
9296 bool setflags;
9297 ARM_ShifterType shift_t;
9298
Caroline Ticed05b4902011-03-29 21:24:06 +00009299 switch (encoding)
9300 {
Caroline Ticec08ed382011-03-29 23:03:16 +00009301 case eEncodingA1:
9302 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
9303 d = Bits32 (opcode, 15, 12);
9304 n = Bits32 (opcode, 19, 16);
9305 m = Bits32 (opcode, 3, 0);
9306 s = Bits32 (opcode, 11, 8);
9307
9308 // setflags = (S == ‘1’); shift_t = DecodeRegShift(type);
9309 setflags = BitIsSet (opcode, 20);
9310 shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
9311
9312 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
9313 if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
9314 return false;
9315 break;
9316
9317 default:
9318 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009319 }
Caroline Ticec08ed382011-03-29 23:03:16 +00009320
9321 // shift_n = UInt(R[s]<7:0>);
9322 uint32_t Rs = ReadCoreReg (s, &success);
9323 if (!success)
9324 return false;
9325
9326 uint32_t shift_n = Bits32 (Rs, 7, 0);
9327
9328 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9329 uint32_t Rm = ReadCoreReg (m, &success);
9330 if (!success)
9331 return false;
9332
9333 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9334
9335 // (result, carry, overflow) = AddWithCarry(R[n], shifted, ‘0’);
9336 uint32_t Rn = ReadCoreReg (n, &success);
9337 if (!success)
9338 return false;
9339
9340 AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
9341
9342 // R[d] = result;
9343 EmulateInstruction::Context context;
9344 context.type = eContextAddition;
9345 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009346 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 +n);
Caroline Ticec08ed382011-03-29 23:03:16 +00009347 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009348 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Ticec08ed382011-03-29 23:03:16 +00009349
9350 context.SetRegisterRegisterOperands (reg_n, reg_m);
9351
9352 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
9353 return false;
9354
9355 // if setflags then
9356 // APSR.N = result<31>;
9357 // APSR.Z = IsZeroBit(result);
9358 // APSR.C = carry;
9359 // APSR.V = overflow;
9360 if (setflags)
9361 return WriteFlags (context, res.result, res.carry_out, res.overflow);
Caroline Ticed05b4902011-03-29 21:24:06 +00009362 }
9363 return true;
9364}
9365
9366// A8.6.213 SUB (register)
9367bool
9368EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
9369{
9370#if 0
Caroline Tice4cccd532011-03-29 23:44:20 +00009371 if ConditionPassed() then
9372 EncodingSpecificOperations();
9373 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9374 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), 1’);
9375 if d == 15 then // Can only occur for ARM encoding
9376 ALUWritePC(result); // setflags is always FALSE here
9377 else
9378 R[d] = result;
9379 if setflags then
9380 APSR.N = result<31>;
9381 APSR.Z = IsZeroBit(result);
9382 APSR.C = carry;
9383 APSR.V = overflow;
Caroline Ticed05b4902011-03-29 21:24:06 +00009384#endif
9385
Caroline Tice4cccd532011-03-29 23:44:20 +00009386 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009387
9388 if (ConditionPassed(opcode))
9389 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009390 uint32_t d;
9391 uint32_t n;
9392 uint32_t m;
9393 bool setflags;
9394 ARM_ShifterType shift_t;
9395 uint32_t shift_n;
9396
Caroline Ticed05b4902011-03-29 21:24:06 +00009397 switch (encoding)
9398 {
Caroline Tice4cccd532011-03-29 23:44:20 +00009399 case eEncodingT1:
9400 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
9401 d = Bits32 (opcode, 2, 0);
9402 n = Bits32 (opcode, 5, 3);
9403 m = Bits32 (opcode, 8, 6);
9404 setflags = !InITBlock();
9405
9406 // (shift_t, shift_n) = (SRType_LSL, 0);
9407 shift_t = SRType_LSL;
9408 shift_n = 0;
9409
9410 break;
9411
9412 case eEncodingT2:
9413 // if Rd == ‘1111’ && S == ‘1’ then SEE CMP (register);
9414 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9415 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9416 d = Bits32 (opcode, 11, 8);
9417 n = Bits32 (opcode, 19, 16);
9418 m = Bits32 (opcode, 3, 0);
9419 setflags = BitIsSet (opcode, 20);
9420
9421 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
9422 shift_n = DecodeImmShiftThumb (opcode, shift_t);
9423
9424 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
9425 if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
9426 return false;
9427
9428 break;
9429
9430 case eEncodingA1:
9431 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
9432 // if Rn == ‘1101’ then SEE SUB (SP minus register);
9433 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ‘1’);
9434 d = Bits32 (opcode, 15, 12);
9435 n = Bits32 (opcode, 19, 16);
9436 m = Bits32 (opcode, 3, 0);
9437 setflags = BitIsSet (opcode, 20);
9438
9439 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
9440 shift_n = DecodeImmShiftARM (opcode, shift_t);
9441
9442 break;
9443
9444 default:
9445 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009446 }
Caroline Tice4cccd532011-03-29 23:44:20 +00009447
9448 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9449 uint32_t Rm = ReadCoreReg (m, &success);
9450 if (!success)
9451 return false;
9452
9453 uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C);
9454
9455 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), ‘1’);
9456 uint32_t Rn = ReadCoreReg (n, &success);
9457 if (!success)
9458 return false;
9459
9460 AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
9461
9462 // if d == 15 then // Can only occur for ARM encoding
9463 // ALUWritePC(result); // setflags is always FALSE here
9464 // else
9465 // R[d] = result;
9466 // if setflags then
9467 // APSR.N = result<31>;
9468 // APSR.Z = IsZeroBit(result);
9469 // APSR.C = carry;
9470 // APSR.V = overflow;
9471
9472 EmulateInstruction::Context context;
9473 context.type = eContextSubtraction;
9474 Register reg_n;
Caroline Tice1697dd72011-03-30 17:11:45 +00009475 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Tice4cccd532011-03-29 23:44:20 +00009476 Register reg_m;
Caroline Tice1697dd72011-03-30 17:11:45 +00009477 reg_m.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
Caroline Tice4cccd532011-03-29 23:44:20 +00009478 context.SetRegisterRegisterOperands (reg_n, reg_m);
9479
Caroline Ticeef440002011-03-30 05:40:56 +00009480 if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
Caroline Tice4cccd532011-03-29 23:44:20 +00009481 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009482 }
9483 return true;
9484}
Caroline Tice4cccd532011-03-29 23:44:20 +00009485
Caroline Ticed05b4902011-03-29 21:24:06 +00009486// A8.6.202 STREX
Caroline Tice5168b6c2011-03-30 05:15:46 +00009487// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a
9488// word from a register to memory if the executing processor has exclusive access to the memory addressed.
Caroline Ticed05b4902011-03-29 21:24:06 +00009489bool
9490EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
9491{
9492#if 0
Caroline Tice5168b6c2011-03-30 05:15:46 +00009493 if ConditionPassed() then
9494 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9495 address = R[n] + imm32;
9496 if ExclusiveMonitorsPass(address,4) then
9497 MemA[address,4] = R[t];
9498 R[d] = 0;
9499 else
9500 R[d] = 1;
Caroline Ticed05b4902011-03-29 21:24:06 +00009501#endif
9502
Caroline Tice5168b6c2011-03-30 05:15:46 +00009503 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009504
9505 if (ConditionPassed(opcode))
9506 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009507 uint32_t d;
9508 uint32_t t;
9509 uint32_t n;
9510 uint32_t imm32;
9511 const uint32_t addr_byte_size = GetAddressByteSize();
9512
Caroline Ticed05b4902011-03-29 21:24:06 +00009513 switch (encoding)
9514 {
Caroline Tice5168b6c2011-03-30 05:15:46 +00009515 case eEncodingT1:
9516 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9517 d = Bits32 (opcode, 11, 8);
9518 t = Bits32 (opcode, 15, 12);
9519 n = Bits32 (opcode, 19, 16);
9520 imm32 = Bits32 (opcode, 7, 0) << 2;
9521
9522 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
9523 if (BadReg (d) || BadReg (t) || (n == 15))
9524 return false;
9525
9526 // if d == n || d == t then UNPREDICTABLE;
9527 if ((d == n) || (d == t))
9528 return false;
9529
9530 break;
9531
9532 case eEncodingA1:
9533 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
9534 d = Bits32 (opcode, 15, 12);
9535 t = Bits32 (opcode, 3, 0);
9536 n = Bits32 (opcode, 19, 16);
9537 imm32 = 0;
9538
9539 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
9540 if ((d == 15) || (t == 15) || (n == 15))
9541 return false;
9542
9543 // if d == n || d == t then UNPREDICTABLE;
9544 if ((d == n) || (d == t))
9545 return false;
9546
9547 break;
9548
9549 default:
9550 return false;
9551 }
9552
9553 // address = R[n] + imm32;
9554 uint32_t Rn = ReadCoreReg (n, &success);
9555 if (!success)
9556 return false;
9557
9558 addr_t address = Rn + imm32;
9559
9560 Register base_reg;
9561 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
9562 Register data_reg;
9563 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
9564 EmulateInstruction::Context context;
9565 context.type = eContextRegisterStore;
9566 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
9567
9568 // if ExclusiveMonitorsPass(address,4) then
9569 // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
9570 // always return true.
9571 if (true)
9572 {
9573 // MemA[address,4] = R[t];
9574 uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
9575 if (!success)
9576 return false;
9577
9578 if (!MemAWrite (context, address, Rt, addr_byte_size))
9579 return false;
9580
9581 // R[d] = 0;
9582 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
9583 return false;
9584 }
9585 else
9586 {
9587 // R[d] = 1;
9588 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
9589 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009590 }
9591 }
9592 return true;
9593}
9594
9595// A8.6.197 STRB (immediate, ARM)
9596bool
9597EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
9598{
9599#if 0
Caroline Ticeef440002011-03-30 05:40:56 +00009600 if ConditionPassed() then
9601 EncodingSpecificOperations();
9602 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9603 address = if index then offset_addr else R[n];
9604 MemU[address,1] = R[t]<7:0>;
9605 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009606#endif
9607
Caroline Ticeef440002011-03-30 05:40:56 +00009608 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009609
9610 if (ConditionPassed(opcode))
9611 {
Caroline Ticeef440002011-03-30 05:40:56 +00009612 uint32_t t;
9613 uint32_t n;
9614 uint32_t imm32;
9615 bool index;
9616 bool add;
9617 bool wback;
9618
Caroline Ticed05b4902011-03-29 21:24:06 +00009619 switch (encoding)
9620 {
Caroline Ticeef440002011-03-30 05:40:56 +00009621 case eEncodingA1:
9622 // if P == ‘0’ && W == ‘1’ then SEE STRBT;
9623 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9624 t = Bits32 (opcode, 15, 12);
9625 n = Bits32 (opcode, 19, 16);
9626 imm32 = Bits32 (opcode, 11, 0);
9627
9628 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9629 index = BitIsSet (opcode, 24);
9630 add = BitIsSet (opcode, 23);
9631 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9632
9633 // if t == 15 then UNPREDICTABLE;
9634 if (t == 15)
9635 return false;
9636
9637 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9638 if (wback && ((n == 15) || (n == t)))
9639 return false;
9640
9641 break;
9642
9643 default:
9644 return false;
9645 }
9646
9647 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9648 uint32_t Rn = ReadCoreReg (n, &success);
9649 if (!success)
9650 return false;
9651
9652 addr_t offset_addr;
9653 if (add)
9654 offset_addr = Rn + imm32;
9655 else
9656 offset_addr = Rn - imm32;
9657
9658 // address = if index then offset_addr else R[n];
9659 addr_t address;
9660 if (index)
9661 address = offset_addr;
9662 else
9663 address = Rn;
9664
9665 // MemU[address,1] = R[t]<7:0>;
9666 uint32_t Rt = ReadCoreReg (t, &success);
9667 if (!success)
9668 return false;
9669
9670 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009671 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticeef440002011-03-30 05:40:56 +00009672 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009673 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticeef440002011-03-30 05:40:56 +00009674 EmulateInstruction::Context context;
9675 context.type = eContextRegisterStore;
9676 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9677
9678 if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
9679 return false;
9680
9681 // if wback then R[n] = offset_addr;
9682 if (wback)
9683 {
9684 if (WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9685 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009686 }
9687 }
9688 return true;
9689}
9690
9691// A8.6.194 STR (immediate, ARM)
9692bool
9693EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
9694{
9695#if 0
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009696 if ConditionPassed() then
9697 EncodingSpecificOperations();
9698 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9699 address = if index then offset_addr else R[n];
9700 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9701 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009702#endif
9703
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009704 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009705
9706 if (ConditionPassed(opcode))
9707 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009708 uint32_t t;
9709 uint32_t n;
9710 uint32_t imm32;
9711 bool index;
9712 bool add;
9713 bool wback;
9714
9715 const uint32_t addr_byte_size = GetAddressByteSize();
9716
Caroline Ticed05b4902011-03-29 21:24:06 +00009717 switch (encoding)
9718 {
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009719 case eEncodingA1:
9720 // if P == ‘0’ && W == ‘1’ then SEE STRT;
9721 // if Rn == ‘1101’ && P == ‘1’ && U == ‘0’ && W == ‘1’ && imm12 == ‘000000000100’ then SEE PUSH;
9722 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
9723 t = Bits32 (opcode, 15, 12);
9724 n = Bits32 (opcode, 19, 16);
9725 imm32 = Bits32 (opcode, 11, 0);
9726
9727 // index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9728 index = BitIsSet (opcode, 24);
9729 add = BitIsSet (opcode, 23);
9730 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9731
9732 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
9733 if (wback && ((n == 15) || (n == t)))
9734 return false;
9735
9736 break;
9737
9738 default:
9739 return false;
9740 }
9741
9742 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9743 uint32_t Rn = ReadCoreReg (n, &success);
9744 if (!success)
9745 return false;
9746
9747 addr_t offset_addr;
9748 if (add)
9749 offset_addr = Rn + imm32;
9750 else
9751 offset_addr = Rn - imm32;
9752
9753 // address = if index then offset_addr else R[n];
9754 addr_t address;
9755 if (index)
9756 address = offset_addr;
9757 else
9758 address = Rn;
9759
9760 Register base_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009761 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009762 Register data_reg;
Caroline Tice1697dd72011-03-30 17:11:45 +00009763 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009764 EmulateInstruction::Context context;
9765 context.type = eContextRegisterStore;
9766 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
9767
9768 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
9769 uint32_t Rt = ReadCoreReg (t, &success);
9770 if (!success)
9771 return false;
9772
9773 if (t == 15)
9774 {
Caroline Ticee98b9582011-03-30 16:05:23 +00009775 uint32_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed42b3cc2011-03-30 06:03:24 +00009776 if (!success)
9777 return false;
9778
9779 if (!MemUWrite (context, address, pc_value, addr_byte_size))
9780 return false;
9781 }
9782 else
9783 {
9784 if (!MemUWrite (context, address, Rt, addr_byte_size))
9785 return false;
9786 }
9787
9788 // if wback then R[n] = offset_addr;
9789 if (wback)
9790 {
9791 context.type = eContextAdjustBaseRegister;
9792 context.SetImmediate (offset_addr);
9793
9794 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
9795 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009796 }
9797 }
9798 return true;
9799}
9800
9801// A8.6.74 LDRH (immediate, ARM)
9802bool
9803EmulateInstructionARM::EmulateLDRHImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
9804{
9805#if 0
9806#endif
9807
9808 //bool success = false;
9809
9810 if (ConditionPassed(opcode))
9811 {
9812 switch (encoding)
9813 {
9814 }
9815 }
9816 return true;
9817}
9818
9819// A8.6.69 LDREX
9820bool
9821EmulateInstructionARM::EmulateLDREX (const uint32_t opcode, const ARMEncoding encoding)
9822{
9823#if 0
9824#endif
9825
9826 //bool success = false;
9827
9828 if (ConditionPassed(opcode))
9829 {
9830 switch (encoding)
9831 {
9832 }
9833 }
9834 return true;
9835}
9836
9837// A8.6.62 LDRB (immediate, ARM)
9838bool
9839EmulateInstructionARM::EmulateLDRBImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
9840{
9841#if 0
9842#endif
9843
9844 //bool success = false;
9845
9846 if (ConditionPassed(opcode))
9847 {
9848 switch (encoding)
9849 {
9850 }
9851 }
9852 return true;
9853}
9854
9855// A8.6.59 LDR (literal)
9856bool
9857EmulateInstructionARM::EmulateLDRLiteral (const uint32_t opcode, const ARMEncoding encoding)
9858{
9859#if 0
9860#endif
9861
9862 //bool success = false;
9863
9864 if (ConditionPassed(opcode))
9865 {
9866 switch (encoding)
9867 {
9868 }
9869 }
9870 return true;
9871}
9872
9873
9874
9875// A8.6.65 LDRBT
9876bool
9877EmulateInstructionARM::EmulateLDRBT (const uint32_t opcode, const ARMEncoding encoding)
9878{
9879#if 0
9880#endif
9881
9882 //bool success = false;
9883
9884 if (ConditionPassed(opcode))
9885 {
9886 switch (encoding)
9887 {
9888 }
9889 }
9890 return true;
9891}
9892
9893
9894// A8.6.66 LDRD (immediate)
Caroline Tice1697dd72011-03-30 17:11:45 +00009895// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
9896// words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing.
Caroline Ticed05b4902011-03-29 21:24:06 +00009897bool
9898EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
9899{
9900#if 0
Caroline Tice1697dd72011-03-30 17:11:45 +00009901 if ConditionPassed() then
9902 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
9903 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9904 address = if index then offset_addr else R[n];
9905 R[t] = MemA[address,4];
9906 R[t2] = MemA[address+4,4];
9907 if wback then R[n] = offset_addr;
Caroline Ticed05b4902011-03-29 21:24:06 +00009908#endif
9909
Caroline Tice1697dd72011-03-30 17:11:45 +00009910 bool success = false;
Caroline Ticed05b4902011-03-29 21:24:06 +00009911
9912 if (ConditionPassed(opcode))
9913 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009914 uint32_t t;
9915 uint32_t t2;
9916 uint32_t n;
9917 uint32_t imm32;
9918 bool index;
9919 bool add;
9920 bool wback;
9921
Caroline Ticed05b4902011-03-29 21:24:06 +00009922 switch (encoding)
9923 {
Caroline Tice1697dd72011-03-30 17:11:45 +00009924 case eEncodingT1:
9925 //if P == ‘0’ && W == ‘0’ then SEE “Related encodings”;
9926 //if Rn == ‘1111’ then SEE LDRD (literal);
9927 //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:’00’, 32);
9928 t = Bits32 (opcode, 15, 12);
9929 t2 = Bits32 (opcode, 11, 8);
9930 n = Bits32 (opcode, 19, 16);
9931 imm32 = Bits32 (opcode, 7, 0) << 2;
9932
9933 //index = (P == ‘1’); add = (U == ‘1’); wback = (W == ‘1’);
9934 index = BitIsSet (opcode, 24);
9935 add = BitIsSet (opcode, 23);
9936 wback = BitIsSet (opcode, 21);
9937
9938 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9939 if (wback && ((n == t) || (n == t2)))
9940 return false;
9941
9942 //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
9943 if (BadReg (t) || BadReg (t2) || (t == t2))
9944 return false;
9945
9946 break;
9947
9948 case eEncodingA1:
9949 //if Rn == ‘1111’ then SEE LDRD (literal);
9950 //if Rt<0> == ‘1’ then UNPREDICTABLE;
9951 //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
9952 t = Bits32 (opcode, 15, 12);
9953 t2 = t + 1;
9954 n = Bits32 (opcode, 19, 16);
9955 imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
9956
9957 //index = (P == ‘1’); add = (U == ‘1’); wback = (P == ‘0’) || (W == ‘1’);
9958 index = BitIsSet (opcode, 24);
9959 add = BitIsSet (opcode, 23);
9960 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
9961
9962 //if P == ‘0’ && W == ‘1’ then UNPREDICTABLE;
9963 if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
9964 return false;
9965
9966 //if wback && (n == t || n == t2) then UNPREDICTABLE;
9967 if (wback && ((n == t) || (n == t2)))
9968 return false;
9969
9970 //if t2 == 15 then UNPREDICTABLE;
9971 if (t2 == 15)
9972 return false;
9973
9974 break;
9975
9976 default:
9977 return false;
9978 }
9979
9980 //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
9981 uint32_t Rn = ReadCoreReg (n, &success);
9982 if (!success)
9983 return false;
9984
9985 addr_t offset_addr;
9986 if (add)
9987 offset_addr = Rn + imm32;
9988 else
9989 offset_addr = Rn - imm32;
9990
9991 //address = if index then offset_addr else R[n];
9992 addr_t address;
9993 if (index)
9994 address = offset_addr;
9995 else
9996 address = Rn;
9997
9998 //R[t] = MemA[address,4];
9999 Register base_reg;
10000 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
10001
10002 EmulateInstruction::Context context;
10003 context.type = eContextRegisterLoad;
10004 context.SetRegisterPlusOffset (base_reg, address - Rn);
10005
10006 const uint32_t addr_byte_size = GetAddressByteSize();
10007 uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
10008 if (!success)
10009 return false;
10010
10011 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
10012 return false;
10013
10014 //R[t2] = MemA[address+4,4];
10015
10016 context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
10017 data = MemARead (context, address + 4, addr_byte_size, 0, &success);
10018 if (!success)
10019 return false;
10020
10021 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
10022 return false;
10023
10024 //if wback then R[n] = offset_addr;
10025 if (wback)
10026 {
10027 context.type = eContextAdjustBaseRegister;
10028 context.SetAddress (offset_addr);
10029
10030 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
10031 return false;
Caroline Ticed05b4902011-03-29 21:24:06 +000010032 }
10033 }
10034 return true;
10035}
10036
10037
10038// A8.6.67 LDRD (literal)
10039bool
10040EmulateInstructionARM::EmulateLDRDLiteral (const uint32_t opcode, const ARMEncoding encoding)
10041{
10042#if 0
10043#endif
10044
10045 //bool success = false;
10046
10047 if (ConditionPassed(opcode))
10048 {
10049 switch (encoding)
10050 {
10051 }
10052 }
10053 return true;
10054}
10055
10056
10057// A8.6.68 LDRD (register)
10058bool
10059EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
10060{
10061#if 0
10062#endif
10063
10064 //bool success = false;
10065
10066 if (ConditionPassed(opcode))
10067 {
10068 switch (encoding)
10069 {
10070 }
10071 }
10072 return true;
10073}
10074
10075
10076// A8.6.70 LDREXB
10077bool
10078EmulateInstructionARM::EmulateLDREXB (const uint32_t opcode, const ARMEncoding encoding)
10079{
10080#if 0
10081#endif
10082
10083 //bool success = false;
10084
10085 if (ConditionPassed(opcode))
10086 {
10087 switch (encoding)
10088 {
10089 }
10090 }
10091 return true;
10092}
10093
10094
10095// A8.6.71 LDREXD
10096bool
10097EmulateInstructionARM::EmulateLDREXD (const uint32_t opcode, const ARMEncoding encoding)
10098{
10099#if 0
10100#endif
10101
10102 //bool success = false;
10103
10104 if (ConditionPassed(opcode))
10105 {
10106 switch (encoding)
10107 {
10108 }
10109 }
10110 return true;
10111}
10112
10113
10114// A8.6.72 LDREXH
10115bool
10116EmulateInstructionARM::EmulateLDREXH (const uint32_t opcode, const ARMEncoding encoding)
10117{
10118#if 0
10119#endif
10120
10121 //bool success = false;
10122
10123 if (ConditionPassed(opcode))
10124 {
10125 switch (encoding)
10126 {
10127 }
10128 }
10129 return true;
10130}
10131
10132
10133
10134// A8.6.77 LDRHT
10135bool
10136EmulateInstructionARM::EmulateLDRHT (const uint32_t opcode, const ARMEncoding encoding)
10137{
10138#if 0
10139#endif
10140
10141 //bool success = false;
10142
10143 if (ConditionPassed(opcode))
10144 {
10145 switch (encoding)
10146 {
10147 }
10148 }
10149 return true;
10150}
10151
10152
10153// A8.6.81 LDRSBT
10154bool
10155EmulateInstructionARM::EmulateLDRSBT (const uint32_t opcode, const ARMEncoding encoding)
10156{
10157#if 0
10158#endif
10159
10160 //bool success = false;
10161
10162 if (ConditionPassed(opcode))
10163 {
10164 switch (encoding)
10165 {
10166 }
10167 }
10168 return true;
10169}
10170
10171
10172// A8.6.85 LDRSHT
10173bool
10174EmulateInstructionARM::EmulateLDRSHT (const uint32_t opcode, const ARMEncoding encoding)
10175{
10176#if 0
10177#endif
10178
10179 //bool success = false;
10180
10181 if (ConditionPassed(opcode))
10182 {
10183 switch (encoding)
10184 {
10185 }
10186 }
10187 return true;
10188}
10189
10190
10191// A8.6.86 LDRT
10192bool
10193EmulateInstructionARM::EmulateLDRT (const uint32_t opcode, const ARMEncoding encoding)
10194{
10195#if 0
10196#endif
10197
10198 //bool success = false;
10199
10200 if (ConditionPassed(opcode))
10201 {
10202 switch (encoding)
10203 {
10204 }
10205 }
10206 return true;
10207}
10208
10209
10210
10211// A8.6.198 STRB (register)
10212bool
10213EmulateInstructionARM::EmulateSTRBReg (const uint32_t opcode, const ARMEncoding encoding)
10214{
10215#if 0
10216#endif
10217
10218 //bool success = false;
10219
10220 if (ConditionPassed(opcode))
10221 {
10222 switch (encoding)
10223 {
10224 }
10225 }
10226 return true;
10227}
10228
10229
10230// A8.6.199 STRBT
10231bool
10232EmulateInstructionARM::EmulateSTRBT (const uint32_t opcode, const ARMEncoding encoding)
10233{
10234#if 0
10235#endif
10236
10237 //bool success = false;
10238
10239 if (ConditionPassed(opcode))
10240 {
10241 switch (encoding)
10242 {
10243 }
10244 }
10245 return true;
10246}
10247
10248
10249// A8.6.200 STRD (immediate)
10250bool
10251EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
10252{
10253#if 0
10254#endif
10255
10256 //bool success = false;
10257
10258 if (ConditionPassed(opcode))
10259 {
10260 switch (encoding)
10261 {
10262 }
10263 }
10264 return true;
10265}
10266
10267
10268// A8.6.201 STRD (register)
10269bool
10270EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
10271{
10272#if 0
10273#endif
10274
10275 //bool success = false;
10276
10277 if (ConditionPassed(opcode))
10278 {
10279 switch (encoding)
10280 {
10281 }
10282 }
10283 return true;
10284}
10285
10286
10287// A8.6.203 STREXB
10288bool
10289EmulateInstructionARM::EmulateSTREXB (const uint32_t opcode, const ARMEncoding encoding)
10290{
10291#if 0
10292#endif
10293
10294 //bool success = false;
10295
10296 if (ConditionPassed(opcode))
10297 {
10298 switch (encoding)
10299 {
10300 }
10301 }
10302 return true;
10303}
10304
10305
10306// A8.6.204 STREXD
10307bool
10308EmulateInstructionARM::EmulateSTREXD (const uint32_t opcode, const ARMEncoding encoding)
10309{
10310#if 0
10311#endif
10312
10313 //bool success = false;
10314
10315 if (ConditionPassed(opcode))
10316 {
10317 switch (encoding)
10318 {
10319 }
10320 }
10321 return true;
10322}
10323
10324
10325// A8.6.205 STREXH
10326bool
10327EmulateInstructionARM::EmulateSTREXH (const uint32_t opcode, const ARMEncoding encoding)
10328{
10329#if 0
10330#endif
10331
10332 //bool success = false;
10333
10334 if (ConditionPassed(opcode))
10335 {
10336 switch (encoding)
10337 {
10338 }
10339 }
10340 return true;
10341}
10342
10343
10344// A8.6.206 STRH (immediate, Thumb)
10345bool
10346EmulateInstructionARM::EmulateSTRHImmThumb (const uint32_t opcode, const ARMEncoding encoding)
10347{
10348#if 0
10349#endif
10350
10351 //bool success = false;
10352
10353 if (ConditionPassed(opcode))
10354 {
10355 switch (encoding)
10356 {
10357 }
10358 }
10359 return true;
10360}
10361
10362
10363// A8.6.207 STRH (immediate, ARM)
10364bool
10365EmulateInstructionARM::EmulateSTRHImmARM (const uint32_t opcode, const ARMEncoding encoding)
10366{
10367#if 0
10368#endif
10369
10370 //bool success = false;
10371
10372 if (ConditionPassed(opcode))
10373 {
10374 switch (encoding)
10375 {
10376 }
10377 }
10378 return true;
10379}
10380
10381
10382
10383// A8.6.209 STRHT
10384bool
10385EmulateInstructionARM::EmulateSTRHT (const uint32_t opcode, const ARMEncoding encoding)
10386{
10387#if 0
10388#endif
10389
10390 //bool success = false;
10391
10392 if (ConditionPassed(opcode))
10393 {
10394 switch (encoding)
10395 {
10396 }
10397 }
10398 return true;
10399}
10400
10401
10402// A8.6.210 STRT
10403bool
10404EmulateInstructionARM::EmulateSTRT (const uint32_t opcode, const ARMEncoding encoding)
10405{
10406#if 0
10407#endif
10408
10409 // bool success = false;
10410
10411 if (ConditionPassed(opcode))
10412 {
10413 switch (encoding)
10414 {
10415 }
10416 }
10417 return true;
10418}
10419
10420
10421
Johnny Chende3cce32011-02-21 21:24:49 +000010422
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010423EmulateInstructionARM::ARMOpcode*
10424EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000010425{
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010426 static ARMOpcode
10427 g_arm_opcodes[] =
10428 {
10429 //----------------------------------------------------------------------
10430 // Prologue instructions
10431 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +000010432
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010433 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +000010434 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
10435 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +000010436
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010437 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +000010438 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +000010439 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +000010440 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +000010441 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
10442 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +000010443 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +000010444
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010445 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +000010446 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Caroline Ticed05b4902011-03-29 21:24:06 +000010447 { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chence1ca772011-01-25 01:13:00 +000010448
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010449 // push one register
10450 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice3e407972011-03-18 19:41:00 +000010451 { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +000010452
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010453 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +000010454 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
10455 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +000010456
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010457 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +000010458 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010459 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +000010460
Johnny Chen9f687722011-02-18 00:02:28 +000010461 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
10462 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +000010463 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000010464 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
10465
10466 //----------------------------------------------------------------------
10467 // Supervisor Call (previously Software Interrupt)
10468 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +000010469 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
10470
10471 //----------------------------------------------------------------------
10472 // Branch instructions
10473 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +000010474 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +000010475 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
10476 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
10477 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
10478 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000010479 // for example, "bx lr"
10480 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000010481 // bxj
10482 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +000010483
Caroline Ticeb9f76c32011-02-08 22:24:38 +000010484 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +000010485 // Data-processing instructions
10486 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000010487 // adc (immediate)
10488 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
10489 // adc (register)
10490 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +000010491 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +000010492 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +000010493 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +000010494 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticec08ed382011-03-29 23:03:16 +000010495 // add (register-shifted register)
10496 { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>m, <Rm>, <type> <RS>"},
Johnny Chena695f952011-02-23 21:24:25 +000010497 // adr
10498 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
10499 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000010500 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +000010501 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +000010502 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +000010503 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000010504 // bic (immediate)
10505 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
10506 // bic (register)
10507 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000010508 // eor (immediate)
10509 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
10510 // eor (register)
10511 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000010512 // orr (immediate)
10513 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
10514 // orr (register)
10515 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000010516 // rsb (immediate)
10517 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
10518 // rsb (register)
10519 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +000010520 // rsc (immediate)
10521 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
10522 // rsc (register)
10523 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000010524 // sbc (immediate)
10525 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
10526 // sbc (register)
10527 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +000010528 // sub (immediate, ARM)
10529 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000010530 // sub (sp minus immediate)
10531 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Caroline Tice4cccd532011-03-29 23:44:20 +000010532 // sub (register)
10533 { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000010534 // teq (immediate)
10535 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
10536 // teq (register)
10537 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000010538 // tst (immediate)
10539 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
10540 // tst (register)
10541 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
10542
Caroline Tice89c6d582011-03-29 19:53:44 +000010543 // mov (immediate)
10544 { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
10545 { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
Johnny Chen01d61572011-02-25 00:23:25 +000010546 // mov (register)
10547 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000010548 // mvn (immediate)
10549 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
10550 // mvn (register)
10551 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +000010552 // cmn (immediate)
10553 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
10554 // cmn (register)
10555 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010556 // cmp (immediate)
10557 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
10558 // cmp (register)
10559 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000010560 // asr (immediate)
10561 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010562 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +000010563 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010564 // lsl (immediate)
10565 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
10566 // lsl (register)
10567 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
10568 // lsr (immediate)
10569 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
10570 // lsr (register)
10571 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000010572 // rrx is a special case encoding of ror (immediate)
10573 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
10574 // ror (immediate)
10575 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
10576 // ror (register)
10577 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000010578 // mul
10579 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +000010580
10581 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000010582 // Load instructions
10583 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +000010584 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +000010585 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +000010586 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +000010587 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +000010588 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +000010589 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +000010590 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +000010591 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +000010592 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +000010593 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +000010594 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +000010595 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +000010596 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +000010597 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +000010598 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
10599 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice1697dd72011-03-30 17:11:45 +000010600 { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
Caroline Ticefa172202011-02-11 22:49:54 +000010601
10602 //----------------------------------------------------------------------
10603 // Store instructions
10604 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +000010605 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +000010606 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +000010607 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +000010608 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +000010609 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +000010610 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
Caroline Tice5168b6c2011-03-30 05:15:46 +000010611 { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
Caroline Ticeef440002011-03-30 05:40:56 +000010612 { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Ticed42b3cc2011-03-30 06:03:24 +000010613 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
Caroline Tice1511f502011-02-15 00:19:42 +000010614
Caroline Tice6bf65162011-03-03 17:42:58 +000010615 //----------------------------------------------------------------------
10616 // Other instructions
10617 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +000010618 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +000010619 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +000010620 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +000010621 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
10622 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000010623
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010624 };
10625 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
10626
10627 for (size_t i=0; i<k_num_arm_opcodes; ++i)
10628 {
10629 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
10630 return &g_arm_opcodes[i];
10631 }
10632 return NULL;
10633}
Greg Clayton64c84432011-01-21 22:02:52 +000010634
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010635
10636EmulateInstructionARM::ARMOpcode*
10637EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +000010638{
Johnny Chenfdd179e2011-01-31 20:09:28 +000010639
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010640 static ARMOpcode
10641 g_thumb_opcodes[] =
10642 {
10643 //----------------------------------------------------------------------
10644 // Prologue instructions
10645 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +000010646
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010647 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +000010648 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
10649 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
10650 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +000010651
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010652 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +000010653 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +000010654 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +000010655 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +000010656 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +000010657 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +000010658
Johnny Chen864a8e82011-02-18 00:07:39 +000010659 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +000010660 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +000010661
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010662 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +000010663 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000010664 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +000010665 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
10666 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Caroline Ticed05b4902011-03-29 21:24:06 +000010667 { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
Johnny Chenfdd179e2011-01-31 20:09:28 +000010668
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010669 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +000010670 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
10671 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +000010672
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010673 //----------------------------------------------------------------------
10674 // Epilogue instructions
10675 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +000010676
Caroline Ticee2212882011-03-22 22:38:28 +000010677 { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +000010678 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +000010679 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
10680 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
10681 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +000010682 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
10683 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +000010684
10685 //----------------------------------------------------------------------
10686 // Supervisor Call (previously Software Interrupt)
10687 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +000010688 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
10689
10690 //----------------------------------------------------------------------
10691 // If Then makes up to four following instructions conditional.
10692 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +000010693 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
10694
10695 //----------------------------------------------------------------------
10696 // Branch instructions
10697 //----------------------------------------------------------------------
10698 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
10699 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Caroline Ticee2212882011-03-22 22:38:28 +000010700 { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +000010701 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +000010702 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +000010703 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +000010704 { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000010705 // J1 == J2 == 1
Caroline Ticee2212882011-03-22 22:38:28 +000010706 { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
Johnny Chen383d6292011-02-11 21:23:32 +000010707 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +000010708 // for example, "bx lr"
10709 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +000010710 // bxj
10711 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +000010712 // compare and branch
10713 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +000010714 // table branch byte
10715 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
10716 // table branch halfword
10717 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +000010718
10719 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +000010720 // Data-processing instructions
10721 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +000010722 // adc (immediate)
10723 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
10724 // adc (register)
10725 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
10726 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
10727 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +000010728 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +000010729 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +000010730 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +000010731 // adr
10732 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
10733 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
10734 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000010735 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +000010736 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +000010737 // and (register)
10738 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
10739 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +000010740 // bic (immediate)
10741 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
10742 // bic (register)
10743 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
10744 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000010745 // eor (immediate)
10746 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
10747 // eor (register)
10748 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
10749 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000010750 // orr (immediate)
10751 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
10752 // orr (register)
10753 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
10754 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +000010755 // rsb (immediate)
10756 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
10757 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
10758 // rsb (register)
10759 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +000010760 // sbc (immediate)
10761 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
10762 // sbc (register)
10763 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
10764 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +000010765 // add (immediate, Thumb)
10766 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
10767 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
10768 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
10769 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +000010770 // sub (immediate, Thumb)
10771 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
10772 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
10773 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
10774 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +000010775 // sub (sp minus immediate)
10776 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
10777 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Caroline Tice4cccd532011-03-29 23:44:20 +000010778 // sub (register)
10779 { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
10780 { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +000010781 // teq (immediate)
10782 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
10783 // teq (register)
10784 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +000010785 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +000010786 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +000010787 // tst (register)
10788 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
10789 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
10790
Johnny Chen7c5234d2011-02-18 23:41:11 +000010791
Johnny Chen338bf542011-02-10 19:29:03 +000010792 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +000010793 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +000010794 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +000010795 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +000010796 // mov{s}<c>.w <Rd>, <Rm>
10797 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +000010798 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +000010799 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
10800 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Caroline Tice89c6d582011-03-29 19:53:44 +000010801 { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
Johnny Chend642a6a2011-02-22 01:01:03 +000010802 // mvn (immediate)
10803 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
10804 // mvn (register)
10805 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
10806 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010807 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +000010808 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010809 // cmn (register)
10810 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +000010811 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010812 // cmp (immediate)
10813 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +000010814 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +000010815 // cmp (register) (Rn and Rm both from r0-r7)
10816 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
10817 // cmp (register) (Rn and Rm not both from r0-r7)
10818 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +000010819 // asr (immediate)
10820 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +000010821 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +000010822 // asr (register)
10823 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
10824 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010825 // lsl (immediate)
10826 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
10827 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
10828 // lsl (register)
10829 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
10830 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
10831 // lsr (immediate)
10832 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
10833 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
10834 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +000010835 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +000010836 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +000010837 // rrx is a special case encoding of ror (immediate)
10838 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
10839 // ror (immediate)
10840 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
10841 // ror (register)
10842 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
10843 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +000010844 // mul
10845 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
10846 // mul
10847 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +000010848
Johnny Chen26863dc2011-02-09 23:43:29 +000010849 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +000010850 // Load instructions
10851 //----------------------------------------------------------------------
10852 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +000010853 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +000010854 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticebaf1f642011-03-24 19:23:45 +000010855 { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
10856 { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
10857 { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
10858 { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
10859 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +000010860 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +000010861 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
10862 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +000010863 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
10864 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
10865 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +000010866 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +000010867 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
Caroline Ticeef440002011-03-30 05:40:56 +000010868 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +000010869 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
10870 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
10871 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +000010872 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +000010873 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
10874 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +000010875 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
10876 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +000010877 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +000010878 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
10879 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +000010880 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
10881 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +000010882 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +000010883 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
10884 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice1697dd72011-03-30 17:11:45 +000010885 { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt?, <Rt2>, [<Rn>,#+/-<imm>]!"},
Caroline Ticefa172202011-02-11 22:49:54 +000010886
10887 //----------------------------------------------------------------------
10888 // Store instructions
10889 //----------------------------------------------------------------------
10890 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +000010891 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +000010892 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +000010893 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
10894 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
10895 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
10896 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
10897 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
10898 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
10899 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
10900 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +000010901 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +000010902 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
10903 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice5168b6c2011-03-30 05:15:46 +000010904 { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
Caroline Tice6bf65162011-03-03 17:42:58 +000010905
10906 //----------------------------------------------------------------------
10907 // Other instructions
10908 //----------------------------------------------------------------------
10909 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +000010910 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
10911 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +000010912 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
10913 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +000010914 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
10915 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +000010916 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
10917 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
10918 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +000010919
Greg Clayton2b8e8b02011-02-01 00:49:32 +000010920 };
10921
10922 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
10923 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
10924 {
10925 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
10926 return &g_thumb_opcodes[i];
10927 }
10928 return NULL;
10929}
Greg Clayton64c84432011-01-21 22:02:52 +000010930
Greg Clayton31e2a382011-01-30 20:03:56 +000010931bool
Greg Clayton395fc332011-02-15 21:59:32 +000010932EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +000010933{
10934 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +000010935 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +000010936 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +000010937 {
Greg Clayton395fc332011-02-15 21:59:32 +000010938 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
10939 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
10940 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
10941 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
10942 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
10943 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
10944 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
10945 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
10946 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
10947 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +000010948 }
10949 return m_arm_isa != 0;
10950}
10951
10952
Greg Clayton64c84432011-01-21 22:02:52 +000010953bool
10954EmulateInstructionARM::ReadInstruction ()
10955{
10956 bool success = false;
Greg Claytonb3448432011-03-24 21:19:54 +000010957 m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000010958 if (success)
10959 {
10960 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
10961 if (success)
10962 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +000010963 Context read_inst_context;
10964 read_inst_context.type = eContextReadOpcode;
10965 read_inst_context.SetNoArgs ();
10966
Greg Claytonb3448432011-03-24 21:19:54 +000010967 if (m_opcode_cpsr & MASK_CPSR_T)
Greg Clayton64c84432011-01-21 22:02:52 +000010968 {
Greg Claytonb3448432011-03-24 21:19:54 +000010969 m_opcode_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +000010970 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +000010971
10972 if (success)
10973 {
Greg Clayton7bc39082011-03-24 23:53:38 +000010974 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
Greg Clayton64c84432011-01-21 22:02:52 +000010975 {
Greg Clayton7bc39082011-03-24 23:53:38 +000010976 m_opcode.SetOpcode16 (thumb_opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000010977 }
10978 else
10979 {
Greg Clayton7bc39082011-03-24 23:53:38 +000010980 m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000010981 }
10982 }
10983 }
10984 else
10985 {
Greg Claytonb3448432011-03-24 21:19:54 +000010986 m_opcode_mode = eModeARM;
Greg Clayton7bc39082011-03-24 23:53:38 +000010987 m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
Greg Clayton64c84432011-01-21 22:02:52 +000010988 }
10989 }
10990 }
10991 if (!success)
10992 {
Greg Claytonb3448432011-03-24 21:19:54 +000010993 m_opcode_mode = eModeInvalid;
10994 m_opcode_pc = LLDB_INVALID_ADDRESS;
Greg Clayton64c84432011-01-21 22:02:52 +000010995 }
10996 return success;
10997}
10998
Johnny Chenee9b1f72011-02-09 01:00:31 +000010999uint32_t
11000EmulateInstructionARM::ArchVersion ()
11001{
11002 return m_arm_isa;
11003}
11004
Greg Clayton64c84432011-01-21 22:02:52 +000011005bool
Greg Clayton7bc39082011-03-24 23:53:38 +000011006EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +000011007{
Greg Claytonb3448432011-03-24 21:19:54 +000011008 if (m_opcode_cpsr == 0)
Greg Clayton64c84432011-01-21 22:02:52 +000011009 return false;
11010
Greg Clayton7bc39082011-03-24 23:53:38 +000011011 const uint32_t cond = CurrentCond (opcode);
Greg Clayton64c84432011-01-21 22:02:52 +000011012
11013 if (cond == UINT32_MAX)
11014 return false;
11015
11016 bool result = false;
11017 switch (UnsignedBits(cond, 3, 1))
11018 {
Greg Claytonb3448432011-03-24 21:19:54 +000011019 case 0: result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break;
11020 case 1: result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break;
11021 case 2: result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break;
11022 case 3: result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break;
11023 case 4: result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); break;
Greg Clayton64c84432011-01-21 22:02:52 +000011024 case 5:
11025 {
Greg Claytonb3448432011-03-24 21:19:54 +000011026 bool n = (m_opcode_cpsr & MASK_CPSR_N);
11027 bool v = (m_opcode_cpsr & MASK_CPSR_V);
Greg Clayton64c84432011-01-21 22:02:52 +000011028 result = n == v;
11029 }
11030 break;
11031 case 6:
11032 {
Greg Claytonb3448432011-03-24 21:19:54 +000011033 bool n = (m_opcode_cpsr & MASK_CPSR_N);
11034 bool v = (m_opcode_cpsr & MASK_CPSR_V);
11035 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
Greg Clayton64c84432011-01-21 22:02:52 +000011036 }
11037 break;
11038 case 7:
11039 result = true;
11040 break;
11041 }
11042
11043 if (cond & 1)
11044 result = !result;
11045 return result;
11046}
11047
Johnny Chen9ee056b2011-02-08 00:06:35 +000011048uint32_t
Greg Clayton7bc39082011-03-24 23:53:38 +000011049EmulateInstructionARM::CurrentCond (const uint32_t opcode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000011050{
Greg Claytonb3448432011-03-24 21:19:54 +000011051 switch (m_opcode_mode)
Johnny Chen9ee056b2011-02-08 00:06:35 +000011052 {
11053 default:
11054 case eModeInvalid:
11055 break;
11056
11057 case eModeARM:
Greg Clayton7bc39082011-03-24 23:53:38 +000011058 return UnsignedBits(opcode, 31, 28);
Johnny Chen9ee056b2011-02-08 00:06:35 +000011059
11060 case eModeThumb:
11061 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
11062 // 'cond' field of the encoding.
Johnny Chen9ee056b2011-02-08 00:06:35 +000011063 {
Greg Clayton7bc39082011-03-24 23:53:38 +000011064 const uint32_t byte_size = m_opcode.GetByteSize();
11065 if (byte_size == 2)
11066 {
11067 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
11068 return Bits32(opcode, 11, 7);
11069 }
11070 else
11071 {
11072 assert (byte_size == 4);
11073 if (Bits32(opcode, 31, 27) == 0x1e &&
11074 Bits32(opcode, 15, 14) == 0x02 &&
11075 Bits32(opcode, 12, 12) == 0x00 &&
11076 Bits32(opcode, 25, 22) <= 0x0d)
11077 {
11078 return Bits32(opcode, 25, 22);
11079 }
11080 }
11081
11082 return m_it_session.GetCond();
Johnny Chen9ee056b2011-02-08 00:06:35 +000011083 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000011084 }
11085 return UINT32_MAX; // Return invalid value
11086}
11087
Johnny Chen9ee056b2011-02-08 00:06:35 +000011088bool
Johnny Chen098ae2d2011-02-12 00:50:05 +000011089EmulateInstructionARM::InITBlock()
11090{
11091 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
11092}
11093
11094bool
11095EmulateInstructionARM::LastInITBlock()
11096{
11097 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
11098}
11099
Caroline Ticeb27771d2011-03-03 22:37:46 +000011100bool
11101EmulateInstructionARM::BadMode (uint32_t mode)
11102{
11103
11104 switch (mode)
11105 {
11106 case 16: return false; // '10000'
11107 case 17: return false; // '10001'
11108 case 18: return false; // '10010'
11109 case 19: return false; // '10011'
11110 case 22: return false; // '10110'
11111 case 23: return false; // '10111'
11112 case 27: return false; // '11011'
11113 case 31: return false; // '11111'
11114 default: return true;
11115 }
11116 return true;
11117}
11118
11119bool
11120EmulateInstructionARM::CurrentModeIsPrivileged ()
11121{
Greg Claytonb3448432011-03-24 21:19:54 +000011122 uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
Caroline Ticeb27771d2011-03-03 22:37:46 +000011123
11124 if (BadMode (mode))
11125 return false;
11126
11127 if (mode == 16)
11128 return false;
11129
11130 return true;
11131}
11132
11133void
11134EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
11135{
11136 bool privileged = CurrentModeIsPrivileged();
11137
11138 uint32_t tmp_cpsr = 0;
11139
Greg Claytonb3448432011-03-24 21:19:54 +000011140 tmp_cpsr = tmp_cpsr | (Bits32 (m_opcode_cpsr, 23, 20) << 20);
Caroline Ticeb27771d2011-03-03 22:37:46 +000011141
11142 if (BitIsSet (bytemask, 3))
11143 {
11144 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
11145 if (affect_execstate)
11146 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
11147 }
11148
11149 if (BitIsSet (bytemask, 2))
11150 {
11151 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
11152 }
11153
11154 if (BitIsSet (bytemask, 1))
11155 {
11156 if (affect_execstate)
11157 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
11158 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
11159 if (privileged)
11160 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
11161 }
11162
11163 if (BitIsSet (bytemask, 0))
11164 {
11165 if (privileged)
11166 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
11167 if (affect_execstate)
11168 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
11169 if (privileged)
11170 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
11171 }
11172
Greg Claytonb3448432011-03-24 21:19:54 +000011173 m_opcode_cpsr = tmp_cpsr;
Caroline Ticeb27771d2011-03-03 22:37:46 +000011174}
11175
11176
Johnny Chen098ae2d2011-02-12 00:50:05 +000011177bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000011178EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
11179{
11180 addr_t target;
11181
Johnny Chenee9b1f72011-02-09 01:00:31 +000011182 // Check the current instruction set.
11183 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000011184 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011185 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000011186 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011187
Johnny Chen9ee056b2011-02-08 00:06:35 +000011188 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000011189 return false;
11190
11191 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000011192}
11193
11194// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
11195bool
Johnny Chen668b4512011-02-15 21:08:58 +000011196EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000011197{
11198 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000011199 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
11200 // we want to record it and issue a WriteRegister callback so the clients
11201 // can track the mode changes accordingly.
11202 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000011203
11204 if (BitIsSet(addr, 0))
11205 {
Johnny Chen0f309db2011-02-09 19:11:32 +000011206 if (CurrentInstrSet() != eModeThumb)
11207 {
11208 SelectInstrSet(eModeThumb);
11209 cpsr_changed = true;
11210 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000011211 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000011212 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000011213 }
11214 else if (BitIsClear(addr, 1))
11215 {
Johnny Chen0f309db2011-02-09 19:11:32 +000011216 if (CurrentInstrSet() != eModeARM)
11217 {
11218 SelectInstrSet(eModeARM);
11219 cpsr_changed = true;
11220 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000011221 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000011222 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000011223 }
11224 else
11225 return false; // address<1:0> == '10' => UNPREDICTABLE
11226
Johnny Chen0f309db2011-02-09 19:11:32 +000011227 if (cpsr_changed)
11228 {
Johnny Chen558133b2011-02-09 23:59:17 +000011229 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000011230 return false;
11231 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000011232 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000011233 return false;
11234
11235 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000011236}
Greg Clayton64c84432011-01-21 22:02:52 +000011237
Johnny Chenee9b1f72011-02-09 01:00:31 +000011238// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
11239bool
Johnny Chen668b4512011-02-15 21:08:58 +000011240EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000011241{
11242 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000011243 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000011244 else
11245 return BranchWritePC((const Context)context, addr);
11246}
11247
Johnny Chen26863dc2011-02-09 23:43:29 +000011248// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
11249bool
Johnny Chen668b4512011-02-15 21:08:58 +000011250EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000011251{
11252 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000011253 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000011254 else
11255 return BranchWritePC((const Context)context, addr);
11256}
11257
Johnny Chenee9b1f72011-02-09 01:00:31 +000011258EmulateInstructionARM::Mode
11259EmulateInstructionARM::CurrentInstrSet ()
11260{
Greg Claytonb3448432011-03-24 21:19:54 +000011261 return m_opcode_mode;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011262}
11263
Greg Claytonb3448432011-03-24 21:19:54 +000011264// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000011265// ReadInstruction() is performed. This function has a side effect of updating
11266// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000011267bool
11268EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
11269{
Greg Claytonb3448432011-03-24 21:19:54 +000011270 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011271 switch (arm_or_thumb)
11272 {
11273 default:
11274 return false;
11275 eModeARM:
11276 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000011277 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011278 break;
11279 eModeThumb:
11280 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000011281 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000011282 break;
11283 }
11284 return true;
11285}
11286
Johnny Chenef21b592011-02-10 01:52:38 +000011287// This function returns TRUE if the processor currently provides support for
11288// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
11289// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
11290bool
11291EmulateInstructionARM::UnalignedSupport()
11292{
11293 return (ArchVersion() >= ARMv7);
11294}
11295
Johnny Chenbf6ad172011-02-11 01:29:53 +000011296// The main addition and subtraction instructions can produce status information
11297// about both unsigned carry and signed overflow conditions. This status
11298// information can be used to synthesize multi-word additions and subtractions.
11299EmulateInstructionARM::AddWithCarryResult
11300EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
11301{
11302 uint32_t result;
11303 uint8_t carry_out;
11304 uint8_t overflow;
11305
11306 uint64_t unsigned_sum = x + y + carry_in;
11307 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
11308
11309 result = UnsignedBits(unsigned_sum, 31, 0);
11310 carry_out = (result == unsigned_sum ? 0 : 1);
11311 overflow = ((int32_t)result == signed_sum ? 0 : 1);
11312
11313 AddWithCarryResult res = { result, carry_out, overflow };
11314 return res;
11315}
11316
Johnny Chen157b9592011-02-18 21:13:05 +000011317uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000011318EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000011319{
Johnny Chene39f22d2011-02-19 01:36:13 +000011320 uint32_t reg_kind, reg_num;
11321 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000011322 {
Johnny Chene39f22d2011-02-19 01:36:13 +000011323 case SP_REG:
11324 reg_kind = eRegisterKindGeneric;
11325 reg_num = LLDB_REGNUM_GENERIC_SP;
11326 break;
11327 case LR_REG:
11328 reg_kind = eRegisterKindGeneric;
11329 reg_num = LLDB_REGNUM_GENERIC_RA;
11330 break;
11331 case PC_REG:
11332 reg_kind = eRegisterKindGeneric;
11333 reg_num = LLDB_REGNUM_GENERIC_PC;
11334 break;
11335 default:
Greg Clayton4fdf7602011-03-20 04:57:14 +000011336 if (num < SP_REG)
Johnny Chene39f22d2011-02-19 01:36:13 +000011337 {
11338 reg_kind = eRegisterKindDWARF;
11339 reg_num = dwarf_r0 + num;
11340 }
Johnny Chen157b9592011-02-18 21:13:05 +000011341 else
Johnny Chene39f22d2011-02-19 01:36:13 +000011342 {
11343 assert(0 && "Invalid register number");
11344 *success = false;
Greg Clayton4fdf7602011-03-20 04:57:14 +000011345 return UINT32_MAX;
Johnny Chene39f22d2011-02-19 01:36:13 +000011346 }
11347 break;
Johnny Chen157b9592011-02-18 21:13:05 +000011348 }
Johnny Chene39f22d2011-02-19 01:36:13 +000011349
11350 // Read our register.
11351 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
11352
11353 // When executing an ARM instruction , PC reads as the address of the current
11354 // instruction plus 8.
11355 // When executing a Thumb instruction , PC reads as the address of the current
11356 // instruction plus 4.
11357 if (num == 15)
11358 {
11359 if (CurrentInstrSet() == eModeARM)
11360 val += 8;
11361 else
11362 val += 4;
11363 }
Johnny Chen157b9592011-02-18 21:13:05 +000011364
11365 return val;
11366}
11367
Johnny Chenca67d1c2011-02-17 01:35:27 +000011368// Write the result to the ARM core register Rd, and optionally update the
11369// condition flags based on the result.
11370//
11371// This helper method tries to encapsulate the following pseudocode from the
11372// ARM Architecture Reference Manual:
11373//
11374// if d == 15 then // Can only occur for encoding A1
11375// ALUWritePC(result); // setflags is always FALSE here
11376// else
11377// R[d] = result;
11378// if setflags then
11379// APSR.N = result<31>;
11380// APSR.Z = IsZeroBit(result);
11381// APSR.C = carry;
11382// // APSR.V unchanged
11383//
11384// In the above case, the API client does not pass in the overflow arg, which
11385// defaults to ~0u.
11386bool
Johnny Chen10530c22011-02-17 22:37:12 +000011387EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
11388 const uint32_t result,
11389 const uint32_t Rd,
11390 bool setflags,
11391 const uint32_t carry,
11392 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000011393{
11394 if (Rd == 15)
11395 {
11396 if (!ALUWritePC (context, result))
11397 return false;
11398 }
11399 else
11400 {
Johnny Chena695f952011-02-23 21:24:25 +000011401 uint32_t reg_kind, reg_num;
11402 switch (Rd)
11403 {
11404 case SP_REG:
11405 reg_kind = eRegisterKindGeneric;
11406 reg_num = LLDB_REGNUM_GENERIC_SP;
11407 break;
11408 case LR_REG:
11409 reg_kind = eRegisterKindGeneric;
11410 reg_num = LLDB_REGNUM_GENERIC_RA;
11411 break;
11412 default:
11413 reg_kind = eRegisterKindDWARF;
11414 reg_num = dwarf_r0 + Rd;
11415 }
11416 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000011417 return false;
11418 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000011419 return WriteFlags (context, result, carry, overflow);
11420 }
11421 return true;
11422}
11423
11424// This helper method tries to encapsulate the following pseudocode from the
11425// ARM Architecture Reference Manual:
11426//
11427// APSR.N = result<31>;
11428// APSR.Z = IsZeroBit(result);
11429// APSR.C = carry;
11430// APSR.V = overflow
11431//
11432// Default arguments can be specified for carry and overflow parameters, which means
11433// not to update the respective flags.
11434bool
11435EmulateInstructionARM::WriteFlags (Context &context,
11436 const uint32_t result,
11437 const uint32_t carry,
11438 const uint32_t overflow)
11439{
Greg Claytonb3448432011-03-24 21:19:54 +000011440 m_new_inst_cpsr = m_opcode_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000011441 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
11442 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000011443 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000011444 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000011445 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000011446 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Greg Claytonb3448432011-03-24 21:19:54 +000011447 if (m_new_inst_cpsr != m_opcode_cpsr)
Johnny Chen10530c22011-02-17 22:37:12 +000011448 {
11449 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
11450 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000011451 }
11452 return true;
11453}
11454
Greg Clayton64c84432011-01-21 22:02:52 +000011455bool
11456EmulateInstructionARM::EvaluateInstruction ()
11457{
Johnny Chenc315f862011-02-05 00:46:10 +000011458 // Advance the ITSTATE bits to their values for the next instruction.
Greg Claytonb3448432011-03-24 21:19:54 +000011459 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
Johnny Chenc315f862011-02-05 00:46:10 +000011460 m_it_session.ITAdvance();
11461
Greg Clayton64c84432011-01-21 22:02:52 +000011462 return false;
11463}