blob: 0c947847dd831f1b2cc39c1c198099021857a2c8 [file] [log] [blame]
Greg Clayton64c84432011-01-21 22:02:52 +00001//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Caroline Ticefa172202011-02-11 22:49:54 +000010#include <stdlib.h>
11
Greg Clayton64c84432011-01-21 22:02:52 +000012#include "EmulateInstructionARM.h"
Greg Clayton395fc332011-02-15 21:59:32 +000013#include "lldb/Core/ArchSpec.h"
Greg Clayton8482ded2011-02-01 00:04:43 +000014#include "lldb/Core/ConstString.h"
15
Greg Claytonf29a08f2011-02-09 17:41:27 +000016#include "Plugins/Process/Utility/ARMDefines.h"
17#include "Plugins/Process/Utility/ARMUtils.h"
18#include "Utility/ARM_DWARF_Registers.h"
19
Johnny Chen9b8d7832011-02-02 01:13:56 +000020#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
Johnny Chen93070472011-02-04 23:02:47 +000021 // and CountTrailingZeros_32 function
Greg Clayton64c84432011-01-21 22:02:52 +000022
23using namespace lldb;
24using namespace lldb_private;
25
Johnny Chene97c0d52011-02-18 19:32:20 +000026// Convenient macro definitions.
Johnny Chen24348842011-02-23 00:15:56 +000027#define APSR_C Bit32(m_inst_cpsr, CPSR_C_POS)
28#define APSR_V Bit32(m_inst_cpsr, CPSR_V_POS)
Johnny Chene97c0d52011-02-18 19:32:20 +000029
Caroline Ticef55261f2011-02-18 22:24:22 +000030#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
31
Johnny Chen0e00af22011-02-10 19:40:42 +000032//----------------------------------------------------------------------
33//
34// ITSession implementation
35//
36//----------------------------------------------------------------------
37
Johnny Chen93070472011-02-04 23:02:47 +000038// A8.6.50
39// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
40static unsigned short CountITSize(unsigned ITMask) {
41 // First count the trailing zeros of the IT mask.
42 unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
43 if (TZ > 3)
44 {
45 printf("Encoding error: IT Mask '0000'\n");
46 return 0;
47 }
48 return (4 - TZ);
49}
50
51// Init ITState. Note that at least one bit is always 1 in mask.
52bool ITSession::InitIT(unsigned short bits7_0)
53{
54 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
55 if (ITCounter == 0)
56 return false;
57
58 // A8.6.50 IT
59 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
60 if (FirstCond == 0xF)
61 {
62 printf("Encoding error: IT FirstCond '1111'\n");
63 return false;
64 }
65 if (FirstCond == 0xE && ITCounter != 1)
66 {
67 printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
68 return false;
69 }
70
71 ITState = bits7_0;
72 return true;
73}
74
75// Update ITState if necessary.
76void ITSession::ITAdvance()
77{
78 assert(ITCounter);
79 --ITCounter;
80 if (ITCounter == 0)
81 ITState = 0;
82 else
83 {
84 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
85 SetBits32(ITState, 4, 0, NewITState4_0);
86 }
87}
88
89// Return true if we're inside an IT Block.
90bool ITSession::InITBlock()
91{
92 return ITCounter != 0;
93}
94
Johnny Chenc315f862011-02-05 00:46:10 +000095// Return true if we're the last instruction inside an IT Block.
96bool ITSession::LastInITBlock()
97{
98 return ITCounter == 1;
99}
100
Johnny Chen93070472011-02-04 23:02:47 +0000101// Get condition bits for the current thumb instruction.
102uint32_t ITSession::GetCond()
103{
Johnny Chenc315f862011-02-05 00:46:10 +0000104 if (InITBlock())
105 return Bits32(ITState, 7, 4);
106 else
107 return COND_AL;
Johnny Chen93070472011-02-04 23:02:47 +0000108}
109
Greg Clayton64c84432011-01-21 22:02:52 +0000110// ARM constants used during decoding
111#define REG_RD 0
112#define LDM_REGLIST 1
Johnny Chene39f22d2011-02-19 01:36:13 +0000113#define SP_REG 13
114#define LR_REG 14
Greg Clayton64c84432011-01-21 22:02:52 +0000115#define PC_REG 15
116#define PC_REGLIST_BIT 0x8000
117
Johnny Chen251af6a2011-01-21 22:47:25 +0000118#define ARMv4 (1u << 0)
Greg Clayton64c84432011-01-21 22:02:52 +0000119#define ARMv4T (1u << 1)
120#define ARMv5T (1u << 2)
121#define ARMv5TE (1u << 3)
122#define ARMv5TEJ (1u << 4)
Johnny Chen251af6a2011-01-21 22:47:25 +0000123#define ARMv6 (1u << 5)
Greg Clayton64c84432011-01-21 22:02:52 +0000124#define ARMv6K (1u << 6)
125#define ARMv6T2 (1u << 7)
Johnny Chen251af6a2011-01-21 22:47:25 +0000126#define ARMv7 (1u << 8)
Johnny Chen60c0d622011-01-25 23:49:39 +0000127#define ARMv8 (1u << 9)
Greg Clayton64c84432011-01-21 22:02:52 +0000128#define ARMvAll (0xffffffffu)
129
Johnny Chen9b8d7832011-02-02 01:13:56 +0000130#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
131#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen59e6ab72011-02-24 21:01:20 +0000132#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Caroline Tice6bf65162011-03-03 17:42:58 +0000133#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv8)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000134#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000135
Johnny Chen0e00af22011-02-10 19:40:42 +0000136//----------------------------------------------------------------------
137//
138// EmulateInstructionARM implementation
139//
140//----------------------------------------------------------------------
141
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000142void
143EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000144{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000145}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000146
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000147void
148EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000149{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000150}
151
Caroline Ticefa172202011-02-11 22:49:54 +0000152// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
153bool
154EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
155{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000156 EmulateInstruction::Context context;
157 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
158 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000159
160 uint32_t random_data = rand ();
161 const uint32_t addr_byte_size = GetAddressByteSize();
162
Caroline Ticecc96eb52011-02-17 19:20:40 +0000163 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000164 return false;
165
166 return true;
167}
168
Caroline Tice713c2662011-02-11 17:59:55 +0000169// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
170bool
171EmulateInstructionARM::WriteBits32Unknown (int n)
172{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000173 EmulateInstruction::Context context;
174 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
175 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000176
Johnny Chen62ff6f52011-02-11 18:11:22 +0000177 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000178 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
179
180 if (!success)
181 return false;
182
183 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
184 return false;
185
186 return true;
187}
188
Johnny Chen08c25e82011-01-31 18:02:28 +0000189// Push Multiple Registers stores multiple registers to the stack, storing to
190// consecutive memory locations ending just below the address in SP, and updates
191// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000192bool
Johnny Chen9f687722011-02-18 00:02:28 +0000193EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000194{
195#if 0
196 // ARM pseudo code...
197 if (ConditionPassed())
198 {
199 EncodingSpecificOperations();
200 NullCheckIfThumbEE(13);
201 address = SP - 4*BitCount(registers);
202
203 for (i = 0 to 14)
204 {
205 if (registers<i> == ’1’)
206 {
207 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
208 MemA[address,4] = bits(32) UNKNOWN;
209 else
210 MemA[address,4] = R[i];
211 address = address + 4;
212 }
213 }
214
215 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
216 MemA[address,4] = PCStoreValue();
217
218 SP = SP - 4*BitCount(registers);
219 }
220#endif
221
222 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000223 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000224 if (!success)
225 return false;
226
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000227 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000228 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000229 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000230 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000231 if (!success)
232 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000233 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000234 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000235 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000236 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000237 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000238 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000239 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000240 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000241 // if BitCount(registers) < 1 then UNPREDICTABLE;
242 if (BitCount(registers) < 1)
243 return false;
244 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000245 case eEncodingT2:
246 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000247 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000248 // if BitCount(registers) < 2 then UNPREDICTABLE;
249 if (BitCount(registers) < 2)
250 return false;
251 break;
252 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000253 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000254 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000255 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000256 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000257 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000258 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000259 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000260 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000261 // Instead of return false, let's handle the following case as well,
262 // which amounts to pushing one reg onto the full descending stacks.
263 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000264 break;
265 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000266 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000267 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000268 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000269 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000270 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000271 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000272 default:
273 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000274 }
Johnny Chence1ca772011-01-25 01:13:00 +0000275 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000276 addr_t addr = sp - sp_offset;
277 uint32_t i;
278
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000279 EmulateInstruction::Context context;
280 context.type = EmulateInstruction::eContextPushRegisterOnStack;
281 Register dwarf_reg;
282 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000283 Register sp_reg;
284 sp_reg.SetRegister (eRegisterKindDWARF, dwarf_sp);
Greg Clayton64c84432011-01-21 22:02:52 +0000285 for (i=0; i<15; ++i)
286 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000287 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000288 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000289 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000290 context.SetRegisterToRegisterPlusOffset (dwarf_reg, sp_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000291 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000292 if (!success)
293 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000294 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000295 return false;
296 addr += addr_byte_size;
297 }
298 }
299
Johnny Chen7c1bf922011-02-08 23:49:37 +0000300 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000301 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000302 dwarf_reg.num = dwarf_pc;
303 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000304 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000305 if (!success)
306 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000307 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000308 return false;
309 }
310
311 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000312 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000313
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000314 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000315 return false;
316 }
317 return true;
318}
319
Johnny Chenef85e912011-01-31 23:07:40 +0000320// Pop Multiple Registers loads multiple registers from the stack, loading from
321// consecutive memory locations staring at the address in SP, and updates
322// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000323bool
Johnny Chen9f687722011-02-18 00:02:28 +0000324EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000325{
326#if 0
327 // ARM pseudo code...
328 if (ConditionPassed())
329 {
330 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
331 address = SP;
332 for i = 0 to 14
333 if registers<i> == ‘1’ then
334 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
335 if registers<15> == ‘1’ then
336 if UnalignedAllowed then
337 LoadWritePC(MemU[address,4]);
338 else
339 LoadWritePC(MemA[address,4]);
340 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
341 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
342 }
343#endif
344
345 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000346 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000347 if (!success)
348 return false;
349
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000350 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000351 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000352 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000353 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000354 if (!success)
355 return false;
356 uint32_t registers = 0;
357 uint32_t Rt; // the destination register
358 switch (encoding) {
359 case eEncodingT1:
360 registers = Bits32(opcode, 7, 0);
361 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000362 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000363 registers |= (1u << 15);
364 // if BitCount(registers) < 1 then UNPREDICTABLE;
365 if (BitCount(registers) < 1)
366 return false;
367 break;
368 case eEncodingT2:
369 // Ignore bit 13.
370 registers = Bits32(opcode, 15, 0) & ~0x2000;
371 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000372 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000373 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000374 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
375 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
376 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000377 break;
378 case eEncodingT3:
379 Rt = Bits32(opcode, 15, 12);
380 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000381 if (Rt == 13)
382 return false;
383 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000384 return false;
385 registers = (1u << Rt);
386 break;
387 case eEncodingA1:
388 registers = Bits32(opcode, 15, 0);
389 // Instead of return false, let's handle the following case as well,
390 // which amounts to popping one reg from the full descending stacks.
391 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
392
393 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000394 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000395 return false;
396 break;
397 case eEncodingA2:
398 Rt = Bits32(opcode, 15, 12);
399 // if t == 13 then UNPREDICTABLE;
400 if (Rt == dwarf_sp)
401 return false;
402 registers = (1u << Rt);
403 break;
404 default:
405 return false;
406 }
407 addr_t sp_offset = addr_byte_size * BitCount (registers);
408 addr_t addr = sp;
409 uint32_t i, data;
410
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000411 EmulateInstruction::Context context;
412 context.type = EmulateInstruction::eContextPopRegisterOffStack;
413 Register dwarf_reg;
414 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Caroline Tice8ce836d2011-03-16 22:46:55 +0000415 Register sp_reg;
416 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
Johnny Chenef85e912011-01-31 23:07:40 +0000417 for (i=0; i<15; ++i)
418 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000419 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000420 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000421 dwarf_reg.num = dwarf_r0 + i;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000422 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000423 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000424 if (!success)
425 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000426 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000427 return false;
428 addr += addr_byte_size;
429 }
430 }
431
Johnny Chen7c1bf922011-02-08 23:49:37 +0000432 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000433 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000434 dwarf_reg.num = dwarf_pc;
Caroline Tice8ce836d2011-03-16 22:46:55 +0000435 context.SetRegisterPlusOffset (sp_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000436 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000437 if (!success)
438 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000439 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000440 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000441 return false;
442 addr += addr_byte_size;
443 }
444
445 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000446 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000447
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000448 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000449 return false;
450 }
451 return true;
452}
453
Johnny Chen5b442b72011-01-27 19:34:30 +0000454// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000455// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000456bool
Johnny Chen9f687722011-02-18 00:02:28 +0000457EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000458{
459#if 0
460 // ARM pseudo code...
461 if (ConditionPassed())
462 {
463 EncodingSpecificOperations();
464 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
465 if d == 15 then
466 ALUWritePC(result); // setflags is always FALSE here
467 else
468 R[d] = result;
469 if setflags then
470 APSR.N = result<31>;
471 APSR.Z = IsZeroBit(result);
472 APSR.C = carry;
473 APSR.V = overflow;
474 }
475#endif
476
477 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000478 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000479 if (!success)
480 return false;
481
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000482 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000483 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000484 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000485 if (!success)
486 return false;
487 uint32_t Rd; // the destination register
488 uint32_t imm32;
489 switch (encoding) {
490 case eEncodingT1:
491 Rd = 7;
492 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
493 break;
494 case eEncodingA1:
495 Rd = Bits32(opcode, 15, 12);
496 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
497 break;
498 default:
499 return false;
500 }
501 addr_t sp_offset = imm32;
502 addr_t addr = sp + sp_offset; // a pointer to the stack area
503
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000504 EmulateInstruction::Context context;
505 context.type = EmulateInstruction::eContextRegisterPlusOffset;
506 Register sp_reg;
507 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
508 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000509
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000510 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000511 return false;
512 }
513 return true;
514}
515
Johnny Chen2ccad832011-01-28 19:57:25 +0000516// Set r7 or ip to the current stack pointer.
517// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000518bool
Johnny Chen9f687722011-02-18 00:02:28 +0000519EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000520{
521#if 0
522 // ARM pseudo code...
523 if (ConditionPassed())
524 {
525 EncodingSpecificOperations();
526 result = R[m];
527 if d == 15 then
528 ALUWritePC(result); // setflags is always FALSE here
529 else
530 R[d] = result;
531 if setflags then
532 APSR.N = result<31>;
533 APSR.Z = IsZeroBit(result);
534 // APSR.C unchanged
535 // APSR.V unchanged
536 }
537#endif
538
539 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000540 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000541 //if (!success)
542 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000543
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000544 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000545 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000546 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000547 if (!success)
548 return false;
549 uint32_t Rd; // the destination register
550 switch (encoding) {
551 case eEncodingT1:
552 Rd = 7;
553 break;
554 case eEncodingA1:
555 Rd = 12;
556 break;
557 default:
558 return false;
559 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000560
561 EmulateInstruction::Context context;
562 context.type = EmulateInstruction::eContextRegisterPlusOffset;
563 Register sp_reg;
564 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
565 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000566
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000567 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000568 return false;
569 }
570 return true;
571}
572
Johnny Chen1c13b622011-01-29 00:11:15 +0000573// Move from high register (r8-r15) to low register (r0-r7).
574// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000575bool
Johnny Chen9f687722011-02-18 00:02:28 +0000576EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000577{
Johnny Chen9f687722011-02-18 00:02:28 +0000578 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000579}
580
581// Move from register to register.
582// MOV (register)
583bool
Johnny Chen9f687722011-02-18 00:02:28 +0000584EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000585{
Johnny Chen1c13b622011-01-29 00:11:15 +0000586#if 0
587 // ARM pseudo code...
588 if (ConditionPassed())
589 {
590 EncodingSpecificOperations();
591 result = R[m];
592 if d == 15 then
593 ALUWritePC(result); // setflags is always FALSE here
594 else
595 R[d] = result;
596 if setflags then
597 APSR.N = result<31>;
598 APSR.Z = IsZeroBit(result);
599 // APSR.C unchanged
600 // APSR.V unchanged
601 }
602#endif
603
604 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000605 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000606 if (!success)
607 return false;
608
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000609 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000610 {
611 uint32_t Rm; // the source register
612 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000613 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000614 switch (encoding) {
615 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000616 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000617 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000618 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000619 if (Rd == 15 && InITBlock() && !LastInITBlock())
620 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000621 break;
622 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000623 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000624 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000625 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000626 if (InITBlock())
627 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000628 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000629 case eEncodingT3:
630 Rd = Bits32(opcode, 11, 8);
631 Rm = Bits32(opcode, 3, 0);
632 setflags = BitIsSet(opcode, 20);
633 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
634 if (setflags && (BadReg(Rd) || BadReg(Rm)))
635 return false;
636 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
637 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
638 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000639 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000640 case eEncodingA1:
641 Rd = Bits32(opcode, 15, 12);
642 Rm = Bits32(opcode, 3, 0);
643 setflags = BitIsSet(opcode, 20);
644 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
645 // TODO: Emulate SUBS PC, LR and related instructions.
646 if (Rd == 15 && setflags)
647 return false;
648 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000649 default:
650 return false;
651 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000652 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000653 if (!success)
654 return false;
655
656 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000657 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000658 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000659 Register dwarf_reg;
660 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000661 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000662
Johnny Chen10530c22011-02-17 22:37:12 +0000663 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000664 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000665 }
666 return true;
667}
668
Johnny Chen357c30f2011-02-14 22:04:25 +0000669// Move (immediate) writes an immediate value to the destination register. It
670// can optionally update the condition flags based on the value.
671// MOV (immediate)
672bool
Johnny Chen9f687722011-02-18 00:02:28 +0000673EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000674{
675#if 0
676 // ARM pseudo code...
677 if (ConditionPassed())
678 {
679 EncodingSpecificOperations();
680 result = imm32;
681 if d == 15 then // Can only occur for ARM encoding
682 ALUWritePC(result); // setflags is always FALSE here
683 else
684 R[d] = result;
685 if setflags then
686 APSR.N = result<31>;
687 APSR.Z = IsZeroBit(result);
688 APSR.C = carry;
689 // APSR.V unchanged
690 }
691#endif
692 bool success = false;
693 const uint32_t opcode = OpcodeAsUnsigned (&success);
694 if (!success)
695 return false;
696
697 if (ConditionPassed())
698 {
699 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000700 uint32_t imm32; // the immediate value to be written to Rd
701 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
702 bool setflags;
703 switch (encoding) {
704 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000705 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000706 setflags = !InITBlock();
707 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000708 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000709 break;
710 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000711 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000712 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000713 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000714 if (BadReg(Rd))
715 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000716 break;
717 default:
718 return false;
719 }
720 uint32_t result = imm32;
721
722 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000723 EmulateInstruction::Context context;
724 context.type = EmulateInstruction::eContextImmediate;
725 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000726
Johnny Chen10530c22011-02-17 22:37:12 +0000727 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000728 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000729 }
730 return true;
731}
732
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000733// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
734// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
735// unsigned values.
736//
737// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
738// limited to only a few forms of the instruction.
739bool
740EmulateInstructionARM::EmulateMUL (ARMEncoding encoding)
741{
742#if 0
743 if ConditionPassed() then
744 EncodingSpecificOperations();
745 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
746 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
747 result = operand1 * operand2;
748 R[d] = result<31:0>;
749 if setflags then
750 APSR.N = result<31>;
751 APSR.Z = IsZeroBit(result);
752 if ArchVersion() == 4 then
753 APSR.C = bit UNKNOWN;
754 // else APSR.C unchanged
755 // APSR.V always unchanged
756#endif
757
758 bool success = false;
759 const uint32_t opcode = OpcodeAsUnsigned (&success);
760 if (!success)
761 return false;
762
763 if (ConditionPassed())
764 {
765 uint32_t d;
766 uint32_t n;
767 uint32_t m;
768 bool setflags;
769
770 // EncodingSpecificOperations();
771 switch (encoding)
772 {
773 case eEncodingT1:
774 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
775 d = Bits32 (opcode, 2, 0);
776 n = Bits32 (opcode, 5, 3);
777 m = Bits32 (opcode, 2, 0);
778 setflags = !InITBlock();
779
780 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
781 if ((ArchVersion() < ARMv6) && (d == n))
782 return false;
783
784 break;
785
786 case eEncodingT2:
787 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
788 d = Bits32 (opcode, 11, 8);
789 n = Bits32 (opcode, 19, 16);
790 m = Bits32 (opcode, 3, 0);
791 setflags = false;
792
793 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
794 if (BadReg (d) || BadReg (n) || BadReg (m))
795 return false;
796
797 break;
798
799 case eEncodingA1:
800 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ’1’);
801 d = Bits32 (opcode, 19, 16);
802 n = Bits32 (opcode, 3, 0);
803 m = Bits32 (opcode, 11, 8);
804 setflags = BitIsSet (opcode, 20);
805
806 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
807 if ((d == 15) || (n == 15) || (m == 15))
808 return false;
809
810 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
811 if ((ArchVersion() < ARMv6) && (d == n))
812 return false;
813
814 break;
815
816 default:
817 return false;
818 }
819
820 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
821 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
822 if (!success)
823 return false;
824
825 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
826 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
827 if (!success)
828 return false;
829
830 // result = operand1 * operand2;
831 uint64_t result = operand1 * operand2;
832
833 // R[d] = result<31:0>;
834 Register op1_reg;
835 Register op2_reg;
836 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
837 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
838
839 EmulateInstruction::Context context;
840 context.type = eContextMultiplication;
841 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
842
843 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
844 return false;
845
846 // if setflags then
847 if (setflags)
848 {
849 // APSR.N = result<31>;
850 // APSR.Z = IsZeroBit(result);
851 m_new_inst_cpsr = m_inst_cpsr;
852 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
853 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
854 if (m_new_inst_cpsr != m_inst_cpsr)
855 {
856 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
857 return false;
858 }
859
860 // if ArchVersion() == 4 then
861 // APSR.C = bit UNKNOWN;
862 }
863 }
864 return true;
865}
866
Johnny Chend642a6a2011-02-22 01:01:03 +0000867// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
868// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000869bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000870EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000871{
872#if 0
873 // ARM pseudo code...
874 if (ConditionPassed())
875 {
876 EncodingSpecificOperations();
877 result = NOT(imm32);
878 if d == 15 then // Can only occur for ARM encoding
879 ALUWritePC(result); // setflags is always FALSE here
880 else
881 R[d] = result;
882 if setflags then
883 APSR.N = result<31>;
884 APSR.Z = IsZeroBit(result);
885 APSR.C = carry;
886 // APSR.V unchanged
887 }
888#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000889 bool success = false;
890 const uint32_t opcode = OpcodeAsUnsigned (&success);
891 if (!success)
892 return false;
893
894 if (ConditionPassed())
895 {
896 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000897 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
898 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000899 bool setflags;
900 switch (encoding) {
901 case eEncodingT1:
902 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000903 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000904 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000905 break;
906 case eEncodingA1:
907 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000908 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000909 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
910 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
911 // TODO: Emulate SUBS PC, LR and related instructions.
912 if (Rd == 15 && setflags)
913 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000914 break;
915 default:
916 return false;
917 }
918 uint32_t result = ~imm32;
919
920 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000921 EmulateInstruction::Context context;
922 context.type = EmulateInstruction::eContextImmediate;
923 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000924
Johnny Chen10530c22011-02-17 22:37:12 +0000925 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000926 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000927 }
928 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000929}
930
Johnny Chend642a6a2011-02-22 01:01:03 +0000931// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
932// It can optionally update the condition flags based on the result.
933bool
934EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
935{
936#if 0
937 // ARM pseudo code...
938 if (ConditionPassed())
939 {
940 EncodingSpecificOperations();
941 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
942 result = NOT(shifted);
943 if d == 15 then // Can only occur for ARM encoding
944 ALUWritePC(result); // setflags is always FALSE here
945 else
946 R[d] = result;
947 if setflags then
948 APSR.N = result<31>;
949 APSR.Z = IsZeroBit(result);
950 APSR.C = carry;
951 // APSR.V unchanged
952 }
953#endif
954
955 bool success = false;
956 const uint32_t opcode = OpcodeAsUnsigned (&success);
957 if (!success)
958 return false;
959
960 if (ConditionPassed())
961 {
962 uint32_t Rm; // the source register
963 uint32_t Rd; // the destination register
964 ARM_ShifterType shift_t;
965 uint32_t shift_n; // the shift applied to the value read from Rm
966 bool setflags;
967 uint32_t carry; // the carry bit after the shift operation
968 switch (encoding) {
969 case eEncodingT1:
970 Rd = Bits32(opcode, 2, 0);
971 Rm = Bits32(opcode, 5, 3);
972 setflags = !InITBlock();
973 shift_t = SRType_LSL;
974 shift_n = 0;
975 if (InITBlock())
976 return false;
977 break;
978 case eEncodingT2:
979 Rd = Bits32(opcode, 11, 8);
980 Rm = Bits32(opcode, 3, 0);
981 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000982 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000983 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000984 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000985 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000986 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000987 case eEncodingA1:
988 Rd = Bits32(opcode, 15, 12);
989 Rm = Bits32(opcode, 3, 0);
990 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000991 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000992 break;
993 default:
994 return false;
995 }
996 uint32_t value = ReadCoreReg(Rm, &success);
997 if (!success)
998 return false;
999
1000 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
1001 uint32_t result = ~shifted;
1002
1003 // The context specifies that an immediate is to be moved into Rd.
1004 EmulateInstruction::Context context;
1005 context.type = EmulateInstruction::eContextImmediate;
1006 context.SetNoArgs ();
1007
1008 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1009 return false;
1010 }
1011 return true;
1012}
1013
Johnny Chen788e0552011-01-27 22:52:23 +00001014// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1015// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001016bool
Johnny Chenc9de9102011-02-11 19:12:30 +00001017EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001018{
1019#if 0
1020 // ARM pseudo code...
1021 if (ConditionPassed())
1022 {
1023 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1024 base = Align(PC,4);
1025 address = if add then (base + imm32) else (base - imm32);
1026 data = MemU[address,4];
1027 if t == 15 then
1028 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
1029 elsif UnalignedSupport() || address<1:0> = ‘00’ then
1030 R[t] = data;
1031 else // Can only apply before ARMv7
1032 if CurrentInstrSet() == InstrSet_ARM then
1033 R[t] = ROR(data, 8*UInt(address<1:0>));
1034 else
1035 R[t] = bits(32) UNKNOWN;
1036 }
1037#endif
1038
1039 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001040 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +00001041 if (!success)
1042 return false;
1043
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001044 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +00001045 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001046 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001047 if (!success)
1048 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001049
1050 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001051 EmulateInstruction::Context context;
1052 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1053 Register pc_reg;
1054 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1055 context.SetRegisterPlusOffset (pc_reg, 0);
1056
Johnny Chenc9de9102011-02-11 19:12:30 +00001057 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001058 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001059 bool add; // +imm32 or -imm32?
1060 addr_t base; // the base address
1061 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001062 uint32_t data; // the literal data value from the PC relative load
1063 switch (encoding) {
1064 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001065 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001066 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001067 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001068 break;
1069 case eEncodingT2:
1070 Rt = Bits32(opcode, 15, 12);
1071 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1072 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001073 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001074 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001075 break;
1076 default:
1077 return false;
1078 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001079
Johnny Chene39f22d2011-02-19 01:36:13 +00001080 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001081 if (add)
1082 address = base + imm32;
1083 else
1084 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001085
1086 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001087 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001088 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001089 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001090
1091 if (Rt == 15)
1092 {
1093 if (Bits32(address, 1, 0) == 0)
1094 {
1095 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001096 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001097 return false;
1098 }
1099 else
1100 return false;
1101 }
1102 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1103 {
1104 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1105 return false;
1106 }
1107 else // We don't handle ARM for now.
1108 return false;
1109
1110 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +00001111 return false;
1112 }
1113 return true;
1114}
1115
Johnny Chen5b442b72011-01-27 19:34:30 +00001116// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001117// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001118bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001119EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001120{
1121#if 0
1122 // ARM pseudo code...
1123 if (ConditionPassed())
1124 {
1125 EncodingSpecificOperations();
1126 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
1127 if d == 15 then // Can only occur for ARM encoding
1128 ALUWritePC(result); // setflags is always FALSE here
1129 else
1130 R[d] = result;
1131 if setflags then
1132 APSR.N = result<31>;
1133 APSR.Z = IsZeroBit(result);
1134 APSR.C = carry;
1135 APSR.V = overflow;
1136 }
1137#endif
1138
1139 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001140 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001141 if (!success)
1142 return false;
1143
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001144 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +00001145 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001146 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001147 if (!success)
1148 return false;
1149 uint32_t imm32; // the immediate operand
1150 switch (encoding) {
1151 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001152 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001153 break;
1154 default:
1155 return false;
1156 }
1157 addr_t sp_offset = imm32;
1158 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1159
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001160 EmulateInstruction::Context context;
1161 context.type = EmulateInstruction::eContextAdjustStackPointer;
1162 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001163
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001164 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001165 return false;
1166 }
1167 return true;
1168}
1169
1170// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001171// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001172bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001173EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001174{
1175#if 0
1176 // ARM pseudo code...
1177 if (ConditionPassed())
1178 {
1179 EncodingSpecificOperations();
1180 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1181 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1182 if d == 15 then
1183 ALUWritePC(result); // setflags is always FALSE here
1184 else
1185 R[d] = result;
1186 if setflags then
1187 APSR.N = result<31>;
1188 APSR.Z = IsZeroBit(result);
1189 APSR.C = carry;
1190 APSR.V = overflow;
1191 }
1192#endif
1193
1194 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001195 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001196 if (!success)
1197 return false;
1198
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001199 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001200 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001201 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001202 if (!success)
1203 return false;
1204 uint32_t Rm; // the second operand
1205 switch (encoding) {
1206 case eEncodingT2:
1207 Rm = Bits32(opcode, 6, 3);
1208 break;
1209 default:
1210 return false;
1211 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001212 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001213 if (!success)
1214 return false;
1215
1216 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1217
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001218 EmulateInstruction::Context context;
1219 context.type = EmulateInstruction::eContextAdjustStackPointer;
1220 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001221
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001222 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001223 return false;
1224 }
1225 return true;
1226}
1227
Johnny Chen9b8d7832011-02-02 01:13:56 +00001228// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1229// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1230// from Thumb to ARM.
1231// BLX (immediate)
1232bool
1233EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1234{
1235#if 0
1236 // ARM pseudo code...
1237 if (ConditionPassed())
1238 {
1239 EncodingSpecificOperations();
1240 if CurrentInstrSet() == InstrSet_ARM then
1241 LR = PC - 4;
1242 else
1243 LR = PC<31:1> : '1';
1244 if targetInstrSet == InstrSet_ARM then
1245 targetAddress = Align(PC,4) + imm32;
1246 else
1247 targetAddress = PC + imm32;
1248 SelectInstrSet(targetInstrSet);
1249 BranchWritePC(targetAddress);
1250 }
1251#endif
1252
1253 bool success = false;
1254 const uint32_t opcode = OpcodeAsUnsigned (&success);
1255 if (!success)
1256 return false;
1257
1258 if (ConditionPassed())
1259 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001260 EmulateInstruction::Context context;
1261 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001262 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001263 if (!success)
1264 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001265 addr_t lr; // next instruction address
1266 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001267 int32_t imm32; // PC-relative offset
1268 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001269 case eEncodingT1:
1270 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001271 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001272 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001273 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001274 uint32_t J1 = Bit32(opcode, 13);
1275 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001276 uint32_t imm11 = Bits32(opcode, 10, 0);
1277 uint32_t I1 = !(J1 ^ S);
1278 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001279 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001280 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001281 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001282 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001283 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001284 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001285 break;
1286 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001287 case eEncodingT2:
1288 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001289 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001290 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001291 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001292 uint32_t J1 = Bit32(opcode, 13);
1293 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001294 uint32_t imm10L = Bits32(opcode, 10, 1);
1295 uint32_t I1 = !(J1 ^ S);
1296 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001297 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001298 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001299 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001300 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001301 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001302 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001303 break;
1304 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001305 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001306 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001307 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001308 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001309 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001310 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001311 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001312 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001313 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001314 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001315 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001316 break;
1317 default:
1318 return false;
1319 }
1320 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1321 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001322 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001323 return false;
1324 }
1325 return true;
1326}
1327
1328// Branch with Link and Exchange (register) calls a subroutine at an address and
1329// instruction set specified by a register.
1330// BLX (register)
1331bool
1332EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1333{
1334#if 0
1335 // ARM pseudo code...
1336 if (ConditionPassed())
1337 {
1338 EncodingSpecificOperations();
1339 target = R[m];
1340 if CurrentInstrSet() == InstrSet_ARM then
1341 next_instr_addr = PC - 4;
1342 LR = next_instr_addr;
1343 else
1344 next_instr_addr = PC - 2;
1345 LR = next_instr_addr<31:1> : ‘1’;
1346 BXWritePC(target);
1347 }
1348#endif
1349
1350 bool success = false;
1351 const uint32_t opcode = OpcodeAsUnsigned (&success);
1352 if (!success)
1353 return false;
1354
1355 if (ConditionPassed())
1356 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001357 EmulateInstruction::Context context;
1358 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001359 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001360 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001361 if (!success)
1362 return false;
1363 uint32_t Rm; // the register with the target address
1364 switch (encoding) {
1365 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001366 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001367 Rm = Bits32(opcode, 6, 3);
1368 // if m == 15 then UNPREDICTABLE;
1369 if (Rm == 15)
1370 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001371 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001372 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001373 break;
1374 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001375 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001376 Rm = Bits32(opcode, 3, 0);
1377 // if m == 15 then UNPREDICTABLE;
1378 if (Rm == 15)
1379 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001380 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001381 default:
1382 return false;
1383 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001384 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001385 if (!success)
1386 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001387 Register dwarf_reg;
1388 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1389 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001390 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1391 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001392 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001393 return false;
1394 }
1395 return true;
1396}
1397
Johnny Chenab3b3512011-02-12 00:10:51 +00001398// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001399bool
1400EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1401{
1402#if 0
1403 // ARM pseudo code...
1404 if (ConditionPassed())
1405 {
1406 EncodingSpecificOperations();
1407 BXWritePC(R[m]);
1408 }
1409#endif
1410
1411 bool success = false;
1412 const uint32_t opcode = OpcodeAsUnsigned (&success);
1413 if (!success)
1414 return false;
1415
1416 if (ConditionPassed())
1417 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001418 EmulateInstruction::Context context;
1419 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001420 uint32_t Rm; // the register with the target address
1421 switch (encoding) {
1422 case eEncodingT1:
1423 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001424 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001425 return false;
1426 break;
1427 case eEncodingA1:
1428 Rm = Bits32(opcode, 3, 0);
1429 break;
1430 default:
1431 return false;
1432 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001433 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001434 if (!success)
1435 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001436
1437 Register dwarf_reg;
1438 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001439 context.SetRegister (dwarf_reg);
1440 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001441 return false;
1442 }
1443 return true;
1444}
1445
Johnny Chen59e6ab72011-02-24 21:01:20 +00001446// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1447// address and instruction set specified by a register as though it were a BX instruction.
1448//
1449// TODO: Emulate Jazelle architecture?
1450// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1451bool
1452EmulateInstructionARM::EmulateBXJRm (ARMEncoding encoding)
1453{
1454#if 0
1455 // ARM pseudo code...
1456 if (ConditionPassed())
1457 {
1458 EncodingSpecificOperations();
1459 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1460 BXWritePC(R[m]);
1461 else
1462 if JazelleAcceptsExecution() then
1463 SwitchToJazelleExecution();
1464 else
1465 SUBARCHITECTURE_DEFINED handler call;
1466 }
1467#endif
1468
1469 bool success = false;
1470 const uint32_t opcode = OpcodeAsUnsigned (&success);
1471 if (!success)
1472 return false;
1473
1474 if (ConditionPassed())
1475 {
1476 EmulateInstruction::Context context;
1477 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1478 uint32_t Rm; // the register with the target address
1479 switch (encoding) {
1480 case eEncodingT1:
1481 Rm = Bits32(opcode, 19, 16);
1482 if (BadReg(Rm))
1483 return false;
1484 if (InITBlock() && !LastInITBlock())
1485 return false;
1486 break;
1487 case eEncodingA1:
1488 Rm = Bits32(opcode, 3, 0);
1489 if (Rm == 15)
1490 return false;
1491 break;
1492 default:
1493 return false;
1494 }
1495 addr_t target = ReadCoreReg (Rm, &success);
1496 if (!success)
1497 return false;
1498
1499 Register dwarf_reg;
1500 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1501 context.SetRegister (dwarf_reg);
1502 if (!BXWritePC(context, target))
1503 return false;
1504 }
1505 return true;
1506}
1507
Johnny Chen0d0148e2011-01-28 02:26:08 +00001508// Set r7 to point to some ip offset.
1509// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001510bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001511EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001512{
1513#if 0
1514 // ARM pseudo code...
1515 if (ConditionPassed())
1516 {
1517 EncodingSpecificOperations();
1518 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1519 if d == 15 then // Can only occur for ARM encoding
1520 ALUWritePC(result); // setflags is always FALSE here
1521 else
1522 R[d] = result;
1523 if setflags then
1524 APSR.N = result<31>;
1525 APSR.Z = IsZeroBit(result);
1526 APSR.C = carry;
1527 APSR.V = overflow;
1528 }
1529#endif
1530
1531 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001532 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001533 if (!success)
1534 return false;
1535
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001536 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001537 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001538 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001539 if (!success)
1540 return false;
1541 uint32_t imm32;
1542 switch (encoding) {
1543 case eEncodingA1:
1544 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1545 break;
1546 default:
1547 return false;
1548 }
1549 addr_t ip_offset = imm32;
1550 addr_t addr = ip - ip_offset; // the adjusted ip value
1551
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001552 EmulateInstruction::Context context;
1553 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1554 Register dwarf_reg;
1555 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1556 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001557
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001558 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001559 return false;
1560 }
1561 return true;
1562}
1563
1564// Set ip to point to some stack offset.
1565// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001566bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001567EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001568{
1569#if 0
1570 // ARM pseudo code...
1571 if (ConditionPassed())
1572 {
1573 EncodingSpecificOperations();
1574 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1575 if d == 15 then // Can only occur for ARM encoding
1576 ALUWritePC(result); // setflags is always FALSE here
1577 else
1578 R[d] = result;
1579 if setflags then
1580 APSR.N = result<31>;
1581 APSR.Z = IsZeroBit(result);
1582 APSR.C = carry;
1583 APSR.V = overflow;
1584 }
1585#endif
1586
1587 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001588 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001589 if (!success)
1590 return false;
1591
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001592 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001593 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001594 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001595 if (!success)
1596 return false;
1597 uint32_t imm32;
1598 switch (encoding) {
1599 case eEncodingA1:
1600 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1601 break;
1602 default:
1603 return false;
1604 }
1605 addr_t sp_offset = imm32;
1606 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1607
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001608 EmulateInstruction::Context context;
1609 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1610 Register dwarf_reg;
1611 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1612 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001613
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001614 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001615 return false;
1616 }
1617 return true;
1618}
1619
Johnny Chenc9e747f2011-02-23 01:55:07 +00001620// This instruction subtracts an immediate value from the SP value, and writes
1621// the result to the destination register.
1622//
1623// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001624bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001625EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001626{
1627#if 0
1628 // ARM pseudo code...
1629 if (ConditionPassed())
1630 {
1631 EncodingSpecificOperations();
1632 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001633 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001634 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001635 else
1636 R[d] = result;
1637 if setflags then
1638 APSR.N = result<31>;
1639 APSR.Z = IsZeroBit(result);
1640 APSR.C = carry;
1641 APSR.V = overflow;
1642 }
1643#endif
1644
1645 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001646 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001647 if (!success)
1648 return false;
1649
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001650 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001651 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001652 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001653 if (!success)
1654 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001655
1656 uint32_t Rd;
1657 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001658 uint32_t imm32;
1659 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001660 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001661 Rd = 13;
1662 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001663 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001664 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001665 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001666 Rd = Bits32(opcode, 11, 8);
1667 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001668 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001669 if (Rd == 15 && setflags)
1670 return EmulateCMPImm(eEncodingT2);
1671 if (Rd == 15 && !setflags)
1672 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001673 break;
1674 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001675 Rd = Bits32(opcode, 11, 8);
1676 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001677 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001678 if (Rd == 15)
1679 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001680 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001681 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001682 Rd = Bits32(opcode, 15, 12);
1683 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001684 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001685 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1686 // TODO: Emulate SUBS PC, LR and related instructions.
1687 if (Rd == 15 && setflags)
1688 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001689 break;
1690 default:
1691 return false;
1692 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001693 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1694
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001695 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001696 if (Rd == 13)
1697 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001698 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1699 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001700 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001701 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001702 }
1703 else
1704 {
1705 context.type = EmulateInstruction::eContextImmediate;
1706 context.SetNoArgs ();
1707 }
1708
1709 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001710 return false;
1711 }
1712 return true;
1713}
1714
Johnny Chen08c25e82011-01-31 18:02:28 +00001715// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001716bool
1717EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001718{
1719#if 0
1720 // ARM pseudo code...
1721 if (ConditionPassed())
1722 {
1723 EncodingSpecificOperations();
1724 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1725 address = if index then offset_addr else R[n];
1726 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1727 if wback then R[n] = offset_addr;
1728 }
1729#endif
1730
1731 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001732 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001733 if (!success)
1734 return false;
1735
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001736 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001737 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001738 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001739 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001740 if (!success)
1741 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001742 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001743 uint32_t imm12;
1744 switch (encoding) {
1745 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001746 Rt = Bits32(opcode, 15, 12);
1747 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001748 break;
1749 default:
1750 return false;
1751 }
1752 addr_t sp_offset = imm12;
1753 addr_t addr = sp - sp_offset;
1754
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001755 EmulateInstruction::Context context;
1756 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1757 Register dwarf_reg;
1758 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001759 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001760 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001761 dwarf_reg.num = dwarf_r0 + Rt;
1762 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001763 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001764 if (!success)
1765 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001766 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001767 return false;
1768 }
1769 else
1770 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001771 dwarf_reg.num = dwarf_pc;
1772 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001773 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001774 if (!success)
1775 return false;
Caroline Tice8d681f52011-03-17 23:50:16 +00001776 if (!MemUWrite (context, addr, pc, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001777 return false;
1778 }
1779
1780 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001781 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001782
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001783 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001784 return false;
1785 }
1786 return true;
1787}
1788
Johnny Chen08c25e82011-01-31 18:02:28 +00001789// Vector Push stores multiple extension registers to the stack.
1790// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001791bool
1792EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001793{
1794#if 0
1795 // ARM pseudo code...
1796 if (ConditionPassed())
1797 {
1798 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1799 address = SP - imm32;
1800 SP = SP - imm32;
1801 if single_regs then
1802 for r = 0 to regs-1
1803 MemA[address,4] = S[d+r]; address = address+4;
1804 else
1805 for r = 0 to regs-1
1806 // Store as two word-aligned words in the correct order for current endianness.
1807 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1808 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1809 address = address+8;
1810 }
1811#endif
1812
1813 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001814 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001815 if (!success)
1816 return false;
1817
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001818 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001819 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001820 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001821 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001822 if (!success)
1823 return false;
1824 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001825 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001826 uint32_t imm32; // stack offset
1827 uint32_t regs; // number of registers
1828 switch (encoding) {
1829 case eEncodingT1:
1830 case eEncodingA1:
1831 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001832 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001833 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1834 // If UInt(imm8) is odd, see "FSTMX".
1835 regs = Bits32(opcode, 7, 0) / 2;
1836 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1837 if (regs == 0 || regs > 16 || (d + regs) > 32)
1838 return false;
1839 break;
1840 case eEncodingT2:
1841 case eEncodingA2:
1842 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001843 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001844 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1845 regs = Bits32(opcode, 7, 0);
1846 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1847 if (regs == 0 || regs > 16 || (d + regs) > 32)
1848 return false;
1849 break;
1850 default:
1851 return false;
1852 }
1853 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1854 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1855 addr_t sp_offset = imm32;
1856 addr_t addr = sp - sp_offset;
1857 uint32_t i;
1858
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001859 EmulateInstruction::Context context;
1860 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1861 Register dwarf_reg;
1862 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001863 for (i=d; i<regs; ++i)
1864 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001865 dwarf_reg.num = start_reg + i;
1866 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001867 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001868 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001869 if (!success)
1870 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001871 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001872 return false;
1873 addr += reg_byte_size;
1874 }
1875
1876 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001877 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001878
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001879 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001880 return false;
1881 }
1882 return true;
1883}
1884
Johnny Chen587a0a42011-02-01 18:35:28 +00001885// Vector Pop loads multiple extension registers from the stack.
1886// It also updates SP to point just above the loaded data.
1887bool
1888EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1889{
1890#if 0
1891 // ARM pseudo code...
1892 if (ConditionPassed())
1893 {
1894 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1895 address = SP;
1896 SP = SP + imm32;
1897 if single_regs then
1898 for r = 0 to regs-1
1899 S[d+r] = MemA[address,4]; address = address+4;
1900 else
1901 for r = 0 to regs-1
1902 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1903 // Combine the word-aligned words in the correct order for current endianness.
1904 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1905 }
1906#endif
1907
1908 bool success = false;
1909 const uint32_t opcode = OpcodeAsUnsigned (&success);
1910 if (!success)
1911 return false;
1912
1913 if (ConditionPassed())
1914 {
1915 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001916 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001917 if (!success)
1918 return false;
1919 bool single_regs;
1920 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1921 uint32_t imm32; // stack offset
1922 uint32_t regs; // number of registers
1923 switch (encoding) {
1924 case eEncodingT1:
1925 case eEncodingA1:
1926 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001927 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001928 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1929 // If UInt(imm8) is odd, see "FLDMX".
1930 regs = Bits32(opcode, 7, 0) / 2;
1931 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1932 if (regs == 0 || regs > 16 || (d + regs) > 32)
1933 return false;
1934 break;
1935 case eEncodingT2:
1936 case eEncodingA2:
1937 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001938 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001939 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1940 regs = Bits32(opcode, 7, 0);
1941 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1942 if (regs == 0 || regs > 16 || (d + regs) > 32)
1943 return false;
1944 break;
1945 default:
1946 return false;
1947 }
1948 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1949 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1950 addr_t sp_offset = imm32;
1951 addr_t addr = sp;
1952 uint32_t i;
1953 uint64_t data; // uint64_t to accomodate 64-bit registers.
1954
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001955 EmulateInstruction::Context context;
1956 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1957 Register dwarf_reg;
1958 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001959 for (i=d; i<regs; ++i)
1960 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001961 dwarf_reg.num = start_reg + i;
1962 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001963 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001964 if (!success)
1965 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001966 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001967 return false;
1968 addr += reg_byte_size;
1969 }
1970
1971 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001972 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001973
1974 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1975 return false;
1976 }
1977 return true;
1978}
1979
Johnny Chenb77be412011-02-04 00:40:18 +00001980// SVC (previously SWI)
1981bool
1982EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1983{
1984#if 0
1985 // ARM pseudo code...
1986 if (ConditionPassed())
1987 {
1988 EncodingSpecificOperations();
1989 CallSupervisor();
1990 }
1991#endif
1992
1993 bool success = false;
1994 const uint32_t opcode = OpcodeAsUnsigned (&success);
1995 if (!success)
1996 return false;
1997
1998 if (ConditionPassed())
1999 {
Johnny Chene39f22d2011-02-19 01:36:13 +00002000 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00002001 addr_t lr; // next instruction address
2002 if (!success)
2003 return false;
2004 uint32_t imm32; // the immediate constant
2005 uint32_t mode; // ARM or Thumb mode
2006 switch (encoding) {
2007 case eEncodingT1:
2008 lr = (pc + 2) | 1u; // return address
2009 imm32 = Bits32(opcode, 7, 0);
2010 mode = eModeThumb;
2011 break;
2012 case eEncodingA1:
2013 lr = pc + 4; // return address
2014 imm32 = Bits32(opcode, 23, 0);
2015 mode = eModeARM;
2016 break;
2017 default:
2018 return false;
2019 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002020
2021 EmulateInstruction::Context context;
2022 context.type = EmulateInstruction::eContextSupervisorCall;
2023 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002024 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2025 return false;
2026 }
2027 return true;
2028}
2029
Johnny Chenc315f862011-02-05 00:46:10 +00002030// If Then makes up to four following instructions (the IT block) conditional.
2031bool
2032EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
2033{
2034#if 0
2035 // ARM pseudo code...
2036 EncodingSpecificOperations();
2037 ITSTATE.IT<7:0> = firstcond:mask;
2038#endif
2039
2040 bool success = false;
2041 const uint32_t opcode = OpcodeAsUnsigned (&success);
2042 if (!success)
2043 return false;
2044
2045 m_it_session.InitIT(Bits32(opcode, 7, 0));
2046 return true;
2047}
2048
Johnny Chen3b620b32011-02-07 20:11:47 +00002049// Branch causes a branch to a target address.
2050bool
2051EmulateInstructionARM::EmulateB (ARMEncoding encoding)
2052{
2053#if 0
2054 // ARM pseudo code...
2055 if (ConditionPassed())
2056 {
2057 EncodingSpecificOperations();
2058 BranchWritePC(PC + imm32);
2059 }
2060#endif
2061
2062 bool success = false;
2063 const uint32_t opcode = OpcodeAsUnsigned (&success);
2064 if (!success)
2065 return false;
2066
Johnny Chen9ee056b2011-02-08 00:06:35 +00002067 if (ConditionPassed())
2068 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002069 EmulateInstruction::Context context;
2070 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002071 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002072 if (!success)
2073 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002074 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002075 int32_t imm32; // PC-relative offset
2076 switch (encoding) {
2077 case eEncodingT1:
2078 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2079 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002080 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002081 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002082 break;
2083 case eEncodingT2:
2084 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002085 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002086 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002087 break;
2088 case eEncodingT3:
2089 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2090 {
Johnny Chenbd599902011-02-10 21:39:01 +00002091 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002092 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002093 uint32_t J1 = Bit32(opcode, 13);
2094 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002095 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002096 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002097 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002098 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002099 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002100 break;
2101 }
2102 case eEncodingT4:
2103 {
Johnny Chenbd599902011-02-10 21:39:01 +00002104 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002105 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002106 uint32_t J1 = Bit32(opcode, 13);
2107 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002108 uint32_t imm11 = Bits32(opcode, 10, 0);
2109 uint32_t I1 = !(J1 ^ S);
2110 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002111 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002112 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002113 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002114 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002115 break;
2116 }
2117 case eEncodingA1:
2118 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002119 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002120 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002121 break;
2122 default:
2123 return false;
2124 }
2125 if (!BranchWritePC(context, target))
2126 return false;
2127 }
2128 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002129}
2130
Johnny Chen53ebab72011-02-08 23:21:57 +00002131// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2132// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2133// CBNZ, CBZ
2134bool
2135EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
2136{
2137#if 0
2138 // ARM pseudo code...
2139 EncodingSpecificOperations();
2140 if nonzero ^ IsZero(R[n]) then
2141 BranchWritePC(PC + imm32);
2142#endif
2143
2144 bool success = false;
2145 const uint32_t opcode = OpcodeAsUnsigned (&success);
2146 if (!success)
2147 return false;
2148
2149 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002150 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002151 if (!success)
2152 return false;
2153
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002154 EmulateInstruction::Context context;
2155 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002156 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002157 if (!success)
2158 return false;
2159
2160 addr_t target; // target address
2161 uint32_t imm32; // PC-relative offset to branch forward
2162 bool nonzero;
2163 switch (encoding) {
2164 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002165 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002166 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002167 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002168 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002169 break;
2170 default:
2171 return false;
2172 }
2173 if (nonzero ^ (reg_val == 0))
2174 if (!BranchWritePC(context, target))
2175 return false;
2176
2177 return true;
2178}
2179
Johnny Chen60299ec2011-02-17 19:34:27 +00002180// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2181// A base register provides a pointer to the table, and a second register supplies an index into the table.
2182// The branch length is twice the value of the byte returned from the table.
2183//
2184// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2185// A base register provides a pointer to the table, and a second register supplies an index into the table.
2186// The branch length is twice the value of the halfword returned from the table.
2187// TBB, TBH
2188bool
2189EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
2190{
2191#if 0
2192 // ARM pseudo code...
2193 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2194 if is_tbh then
2195 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2196 else
2197 halfwords = UInt(MemU[R[n]+R[m], 1]);
2198 BranchWritePC(PC + 2*halfwords);
2199#endif
2200
2201 bool success = false;
2202 const uint32_t opcode = OpcodeAsUnsigned (&success);
2203 if (!success)
2204 return false;
2205
2206 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2207 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2208 bool is_tbh; // true if table branch halfword
2209 switch (encoding) {
2210 case eEncodingT1:
2211 Rn = Bits32(opcode, 19, 16);
2212 Rm = Bits32(opcode, 3, 0);
2213 is_tbh = BitIsSet(opcode, 4);
2214 if (Rn == 13 || BadReg(Rm))
2215 return false;
2216 if (InITBlock() && !LastInITBlock())
2217 return false;
2218 break;
2219 default:
2220 return false;
2221 }
2222
2223 // Read the address of the table from the operand register Rn.
2224 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002225 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002226 if (!success)
2227 return false;
2228
2229 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002230 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002231 if (!success)
2232 return false;
2233
2234 // the offsetted table address
2235 addr_t addr = base + (is_tbh ? index*2 : index);
2236
2237 // PC-relative offset to branch forward
2238 EmulateInstruction::Context context;
2239 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002240 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002241 if (!success)
2242 return false;
2243
Johnny Chene39f22d2011-02-19 01:36:13 +00002244 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002245 if (!success)
2246 return false;
2247
2248 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002249 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002250 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2251 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2252
2253 if (!BranchWritePC(context, target))
2254 return false;
2255
2256 return true;
2257}
2258
Caroline Ticedcc11b32011-03-02 23:57:02 +00002259// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2260// It can optionally update the condition flags based on the result.
2261bool
2262EmulateInstructionARM::EmulateADDImmThumb (ARMEncoding encoding)
2263{
2264#if 0
2265 if ConditionPassed() then
2266 EncodingSpecificOperations();
2267 (result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2268 R[d] = result;
2269 if setflags then
2270 APSR.N = result<31>;
2271 APSR.Z = IsZeroBit(result);
2272 APSR.C = carry;
2273 APSR.V = overflow;
2274#endif
2275
2276 bool success = false;
2277 const uint32_t opcode = OpcodeAsUnsigned (&success);
2278 if (!success)
2279 return false;
2280
2281 if (ConditionPassed())
2282 {
2283 uint32_t d;
2284 uint32_t n;
2285 bool setflags;
2286 uint32_t imm32;
2287 uint32_t carry_out;
2288
2289 //EncodingSpecificOperations();
2290 switch (encoding)
2291 {
2292 case eEncodingT1:
2293 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2294 d = Bits32 (opcode, 2, 0);
2295 n = Bits32 (opcode, 5, 3);
2296 setflags = !InITBlock();
2297 imm32 = Bits32 (opcode, 8,6);
2298
2299 break;
2300
2301 case eEncodingT2:
2302 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2303 d = Bits32 (opcode, 10, 8);
2304 n = Bits32 (opcode, 10, 8);
2305 setflags = !InITBlock();
2306 imm32 = Bits32 (opcode, 7, 0);
2307
2308 break;
2309
2310 case eEncodingT3:
2311 // if Rd == ’1111’ && S == ’1’ then SEE CMN (immediate);
2312 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2313 // d = UInt(Rd); n = UInt(Rn); setflags = (S == ’1’); imm32 = ThumbExpandImm(i:imm3:imm8);
2314 d = Bits32 (opcode, 11, 8);
2315 n = Bits32 (opcode, 19, 16);
2316 setflags = BitIsSet (opcode, 20);
2317 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2318
2319 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2320 if (BadReg (d) || (n == 15))
2321 return false;
2322
2323 break;
2324
2325 case eEncodingT4:
2326 {
2327 // if Rn == ’1111’ then SEE ADR;
2328 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2329 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2330 d = Bits32 (opcode, 11, 8);
2331 n = Bits32 (opcode, 19, 16);
2332 setflags = false;
2333 uint32_t i = Bit32 (opcode, 26);
2334 uint32_t imm3 = Bits32 (opcode, 14, 12);
2335 uint32_t imm8 = Bits32 (opcode, 7, 0);
2336 imm32 = (i << 11) | (imm3 << 8) | imm8;
2337
2338 // if BadReg(d) then UNPREDICTABLE;
2339 if (BadReg (d))
2340 return false;
2341
2342 break;
2343 }
2344 default:
2345 return false;
2346 }
2347
2348 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2349 if (!success)
2350 return false;
2351
2352 //(result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2353 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2354
2355 Register reg_n;
2356 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2357
2358 EmulateInstruction::Context context;
2359 context.type = eContextAddition;
2360 context.SetRegisterPlusOffset (reg_n, imm32);
2361
2362 //R[d] = result;
2363 //if setflags then
2364 //APSR.N = result<31>;
2365 //APSR.Z = IsZeroBit(result);
2366 //APSR.C = carry;
2367 //APSR.V = overflow;
2368 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2369 return false;
2370
2371 }
2372 return true;
2373}
2374
Johnny Chen8fa20592011-02-18 01:22:22 +00002375// This instruction adds an immediate value to a register value, and writes the result to the destination
2376// register. It can optionally update the condition flags based on the result.
2377bool
2378EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2379{
2380#if 0
2381 // ARM pseudo code...
2382 if ConditionPassed() then
2383 EncodingSpecificOperations();
2384 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2385 if d == 15 then
2386 ALUWritePC(result); // setflags is always FALSE here
2387 else
2388 R[d] = result;
2389 if setflags then
2390 APSR.N = result<31>;
2391 APSR.Z = IsZeroBit(result);
2392 APSR.C = carry;
2393 APSR.V = overflow;
2394#endif
2395
2396 bool success = false;
2397 const uint32_t opcode = OpcodeAsUnsigned (&success);
2398 if (!success)
2399 return false;
2400
2401 if (ConditionPassed())
2402 {
2403 uint32_t Rd, Rn;
2404 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2405 bool setflags;
2406 switch (encoding)
2407 {
2408 case eEncodingA1:
2409 Rd = Bits32(opcode, 15, 12);
2410 Rn = Bits32(opcode, 19, 16);
2411 setflags = BitIsSet(opcode, 20);
2412 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2413 break;
2414 default:
2415 return false;
2416 }
2417
Johnny Chen8fa20592011-02-18 01:22:22 +00002418 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002419 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002420 if (!success)
2421 return false;
2422
2423 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2424
2425 EmulateInstruction::Context context;
2426 context.type = EmulateInstruction::eContextImmediate;
2427 context.SetNoArgs ();
2428
2429 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2430 return false;
2431 }
2432 return true;
2433}
2434
Johnny Chend761dcf2011-02-17 22:03:29 +00002435// This instruction adds a register value and an optionally-shifted register value, and writes the result
2436// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002437bool
Johnny Chen9f687722011-02-18 00:02:28 +00002438EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002439{
2440#if 0
2441 // ARM pseudo code...
2442 if ConditionPassed() then
2443 EncodingSpecificOperations();
2444 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2445 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2446 if d == 15 then
2447 ALUWritePC(result); // setflags is always FALSE here
2448 else
2449 R[d] = result;
2450 if setflags then
2451 APSR.N = result<31>;
2452 APSR.Z = IsZeroBit(result);
2453 APSR.C = carry;
2454 APSR.V = overflow;
2455#endif
2456
2457 bool success = false;
2458 const uint32_t opcode = OpcodeAsUnsigned (&success);
2459 if (!success)
2460 return false;
2461
2462 if (ConditionPassed())
2463 {
2464 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002465 ARM_ShifterType shift_t;
2466 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002467 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002468 switch (encoding)
2469 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002470 case eEncodingT1:
2471 Rd = Bits32(opcode, 2, 0);
2472 Rn = Bits32(opcode, 5, 3);
2473 Rm = Bits32(opcode, 8, 6);
2474 setflags = !InITBlock();
2475 shift_t = SRType_LSL;
2476 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002477 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002478 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002479 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002480 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002481 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002482 shift_t = SRType_LSL;
2483 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002484 if (Rn == 15 && Rm == 15)
2485 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002486 if (Rd == 15 && InITBlock() && !LastInITBlock())
2487 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002488 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002489 case eEncodingA1:
2490 Rd = Bits32(opcode, 15, 12);
2491 Rn = Bits32(opcode, 19, 16);
2492 Rm = Bits32(opcode, 3, 0);
2493 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002494 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002495 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002496 default:
2497 return false;
2498 }
2499
Johnny Chen26863dc2011-02-09 23:43:29 +00002500 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002501 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002502 if (!success)
2503 return false;
2504
2505 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002506 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002507 if (!success)
2508 return false;
2509
Johnny Chene97c0d52011-02-18 19:32:20 +00002510 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002511 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002512
2513 EmulateInstruction::Context context;
Caroline Tice8ce836d2011-03-16 22:46:55 +00002514 context.type = EmulateInstruction::eContextAddition;
2515 Register op1_reg;
2516 Register op2_reg;
2517 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
2518 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
2519 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002520
Johnny Chen10530c22011-02-17 22:37:12 +00002521 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002522 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002523 }
2524 return true;
2525}
2526
Johnny Chen34075cb2011-02-22 01:56:31 +00002527// Compare Negative (immediate) adds a register value and an immediate value.
2528// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002529bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002530EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2531{
2532#if 0
2533 // ARM pseudo code...
2534 if ConditionPassed() then
2535 EncodingSpecificOperations();
2536 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2537 APSR.N = result<31>;
2538 APSR.Z = IsZeroBit(result);
2539 APSR.C = carry;
2540 APSR.V = overflow;
2541#endif
2542
2543 bool success = false;
2544 const uint32_t opcode = OpcodeAsUnsigned (&success);
2545 if (!success)
2546 return false;
2547
2548 uint32_t Rn; // the first operand
2549 uint32_t imm32; // the immediate value to be compared with
2550 switch (encoding) {
2551 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002552 Rn = Bits32(opcode, 19, 16);
2553 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2554 if (Rn == 15)
2555 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002556 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002557 case eEncodingA1:
2558 Rn = Bits32(opcode, 19, 16);
2559 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2560 break;
2561 default:
2562 return false;
2563 }
2564 // Read the register value from the operand register Rn.
2565 uint32_t reg_val = ReadCoreReg(Rn, &success);
2566 if (!success)
2567 return false;
2568
Johnny Chen078fbc62011-02-22 19:48:22 +00002569 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002570
2571 EmulateInstruction::Context context;
2572 context.type = EmulateInstruction::eContextImmediate;
2573 context.SetNoArgs ();
2574 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2575 return false;
2576
2577 return true;
2578}
2579
2580// Compare Negative (register) adds a register value and an optionally-shifted register value.
2581// It updates the condition flags based on the result, and discards the result.
2582bool
2583EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2584{
2585#if 0
2586 // ARM pseudo code...
2587 if ConditionPassed() then
2588 EncodingSpecificOperations();
2589 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2590 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2591 APSR.N = result<31>;
2592 APSR.Z = IsZeroBit(result);
2593 APSR.C = carry;
2594 APSR.V = overflow;
2595#endif
2596
2597 bool success = false;
2598 const uint32_t opcode = OpcodeAsUnsigned (&success);
2599 if (!success)
2600 return false;
2601
2602 uint32_t Rn; // the first operand
2603 uint32_t Rm; // the second operand
2604 ARM_ShifterType shift_t;
2605 uint32_t shift_n; // the shift applied to the value read from Rm
2606 switch (encoding) {
2607 case eEncodingT1:
2608 Rn = Bits32(opcode, 2, 0);
2609 Rm = Bits32(opcode, 5, 3);
2610 shift_t = SRType_LSL;
2611 shift_n = 0;
2612 break;
2613 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002614 Rn = Bits32(opcode, 19, 16);
2615 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002616 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002617 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2618 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002619 return false;
2620 break;
2621 case eEncodingA1:
2622 Rn = Bits32(opcode, 19, 16);
2623 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002624 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002625 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002626 default:
2627 return false;
2628 }
2629 // Read the register value from register Rn.
2630 uint32_t val1 = ReadCoreReg(Rn, &success);
2631 if (!success)
2632 return false;
2633
2634 // Read the register value from register Rm.
2635 uint32_t val2 = ReadCoreReg(Rm, &success);
2636 if (!success)
2637 return false;
2638
2639 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002640 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002641
2642 EmulateInstruction::Context context;
2643 context.type = EmulateInstruction::eContextImmediate;
2644 context.SetNoArgs();
2645 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2646 return false;
2647
2648 return true;
2649}
2650
2651// Compare (immediate) subtracts an immediate value from a register value.
2652// It updates the condition flags based on the result, and discards the result.
2653bool
2654EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002655{
2656#if 0
2657 // ARM pseudo code...
2658 if ConditionPassed() then
2659 EncodingSpecificOperations();
2660 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2661 APSR.N = result<31>;
2662 APSR.Z = IsZeroBit(result);
2663 APSR.C = carry;
2664 APSR.V = overflow;
2665#endif
2666
2667 bool success = false;
2668 const uint32_t opcode = OpcodeAsUnsigned (&success);
2669 if (!success)
2670 return false;
2671
2672 uint32_t Rn; // the first operand
2673 uint32_t imm32; // the immediate value to be compared with
2674 switch (encoding) {
2675 case eEncodingT1:
2676 Rn = Bits32(opcode, 10, 8);
2677 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002678 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002679 case eEncodingT2:
2680 Rn = Bits32(opcode, 19, 16);
2681 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2682 if (Rn == 15)
2683 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002684 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002685 case eEncodingA1:
2686 Rn = Bits32(opcode, 19, 16);
2687 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002688 break;
2689 default:
2690 return false;
2691 }
2692 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002693 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002694 if (!success)
2695 return false;
2696
Johnny Chen10530c22011-02-17 22:37:12 +00002697 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2698
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002699 EmulateInstruction::Context context;
2700 context.type = EmulateInstruction::eContextImmediate;
2701 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002702 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2703 return false;
2704
Johnny Chend4dc4442011-02-11 02:02:56 +00002705 return true;
2706}
2707
Johnny Chen34075cb2011-02-22 01:56:31 +00002708// Compare (register) subtracts an optionally-shifted register value from a register value.
2709// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002710bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002711EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002712{
2713#if 0
2714 // ARM pseudo code...
2715 if ConditionPassed() then
2716 EncodingSpecificOperations();
2717 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2718 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2719 APSR.N = result<31>;
2720 APSR.Z = IsZeroBit(result);
2721 APSR.C = carry;
2722 APSR.V = overflow;
2723#endif
2724
2725 bool success = false;
2726 const uint32_t opcode = OpcodeAsUnsigned (&success);
2727 if (!success)
2728 return false;
2729
2730 uint32_t Rn; // the first operand
2731 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002732 ARM_ShifterType shift_t;
2733 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002734 switch (encoding) {
2735 case eEncodingT1:
2736 Rn = Bits32(opcode, 2, 0);
2737 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002738 shift_t = SRType_LSL;
2739 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002740 break;
2741 case eEncodingT2:
2742 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2743 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002744 shift_t = SRType_LSL;
2745 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002746 if (Rn < 8 && Rm < 8)
2747 return false;
2748 if (Rn == 15 || Rm == 15)
2749 return false;
2750 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002751 case eEncodingA1:
2752 Rn = Bits32(opcode, 19, 16);
2753 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002754 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002755 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002756 default:
2757 return false;
2758 }
2759 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002760 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002761 if (!success)
2762 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002763
Johnny Chene4a4d302011-02-11 21:53:58 +00002764 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002765 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002766 if (!success)
2767 return false;
2768
Johnny Chen34075cb2011-02-22 01:56:31 +00002769 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2770 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002771
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002772 EmulateInstruction::Context context;
2773 context.type = EmulateInstruction::eContextImmediate;
2774 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002775 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2776 return false;
2777
Johnny Chene4a4d302011-02-11 21:53:58 +00002778 return true;
2779}
2780
Johnny Chen82f16aa2011-02-15 20:10:55 +00002781// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2782// shifting in copies of its sign bit, and writes the result to the destination register. It can
2783// optionally update the condition flags based on the result.
2784bool
2785EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2786{
2787#if 0
2788 // ARM pseudo code...
2789 if ConditionPassed() then
2790 EncodingSpecificOperations();
2791 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2792 if d == 15 then // Can only occur for ARM encoding
2793 ALUWritePC(result); // setflags is always FALSE here
2794 else
2795 R[d] = result;
2796 if setflags then
2797 APSR.N = result<31>;
2798 APSR.Z = IsZeroBit(result);
2799 APSR.C = carry;
2800 // APSR.V unchanged
2801#endif
2802
Johnny Chen41a0a152011-02-16 01:27:54 +00002803 return EmulateShiftImm(encoding, SRType_ASR);
2804}
2805
2806// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2807// shifting in copies of its sign bit, and writes the result to the destination register.
2808// The variable number of bits is read from the bottom byte of a register. It can optionally update
2809// the condition flags based on the result.
2810bool
2811EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2812{
2813#if 0
2814 // ARM pseudo code...
2815 if ConditionPassed() then
2816 EncodingSpecificOperations();
2817 shift_n = UInt(R[m]<7:0>);
2818 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2819 R[d] = result;
2820 if setflags then
2821 APSR.N = result<31>;
2822 APSR.Z = IsZeroBit(result);
2823 APSR.C = carry;
2824 // APSR.V unchanged
2825#endif
2826
2827 return EmulateShiftReg(encoding, SRType_ASR);
2828}
2829
2830// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2831// shifting in zeros, and writes the result to the destination register. It can optionally
2832// update the condition flags based on the result.
2833bool
2834EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2835{
2836#if 0
2837 // ARM pseudo code...
2838 if ConditionPassed() then
2839 EncodingSpecificOperations();
2840 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2841 if d == 15 then // Can only occur for ARM encoding
2842 ALUWritePC(result); // setflags is always FALSE here
2843 else
2844 R[d] = result;
2845 if setflags then
2846 APSR.N = result<31>;
2847 APSR.Z = IsZeroBit(result);
2848 APSR.C = carry;
2849 // APSR.V unchanged
2850#endif
2851
2852 return EmulateShiftImm(encoding, SRType_LSL);
2853}
2854
2855// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2856// shifting in zeros, and writes the result to the destination register. The variable number
2857// of bits is read from the bottom byte of a register. It can optionally update the condition
2858// flags based on the result.
2859bool
2860EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2861{
2862#if 0
2863 // ARM pseudo code...
2864 if ConditionPassed() then
2865 EncodingSpecificOperations();
2866 shift_n = UInt(R[m]<7:0>);
2867 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2868 R[d] = result;
2869 if setflags then
2870 APSR.N = result<31>;
2871 APSR.Z = IsZeroBit(result);
2872 APSR.C = carry;
2873 // APSR.V unchanged
2874#endif
2875
2876 return EmulateShiftReg(encoding, SRType_LSL);
2877}
2878
2879// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2880// shifting in zeros, and writes the result to the destination register. It can optionally
2881// update the condition flags based on the result.
2882bool
2883EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2884{
2885#if 0
2886 // ARM pseudo code...
2887 if ConditionPassed() then
2888 EncodingSpecificOperations();
2889 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2890 if d == 15 then // Can only occur for ARM encoding
2891 ALUWritePC(result); // setflags is always FALSE here
2892 else
2893 R[d] = result;
2894 if setflags then
2895 APSR.N = result<31>;
2896 APSR.Z = IsZeroBit(result);
2897 APSR.C = carry;
2898 // APSR.V unchanged
2899#endif
2900
2901 return EmulateShiftImm(encoding, SRType_LSR);
2902}
2903
2904// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2905// shifting in zeros, and writes the result to the destination register. The variable number
2906// of bits is read from the bottom byte of a register. It can optionally update the condition
2907// flags based on the result.
2908bool
2909EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2910{
2911#if 0
2912 // ARM pseudo code...
2913 if ConditionPassed() then
2914 EncodingSpecificOperations();
2915 shift_n = UInt(R[m]<7:0>);
2916 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2917 R[d] = result;
2918 if setflags then
2919 APSR.N = result<31>;
2920 APSR.Z = IsZeroBit(result);
2921 APSR.C = carry;
2922 // APSR.V unchanged
2923#endif
2924
2925 return EmulateShiftReg(encoding, SRType_LSR);
2926}
2927
Johnny Cheneeab4852011-02-16 22:14:44 +00002928// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2929// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2930// It can optionally update the condition flags based on the result.
2931bool
2932EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2933{
2934#if 0
2935 // ARM pseudo code...
2936 if ConditionPassed() then
2937 EncodingSpecificOperations();
2938 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2939 if d == 15 then // Can only occur for ARM encoding
2940 ALUWritePC(result); // setflags is always FALSE here
2941 else
2942 R[d] = result;
2943 if setflags then
2944 APSR.N = result<31>;
2945 APSR.Z = IsZeroBit(result);
2946 APSR.C = carry;
2947 // APSR.V unchanged
2948#endif
2949
2950 return EmulateShiftImm(encoding, SRType_ROR);
2951}
2952
2953// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2954// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2955// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2956// flags based on the result.
2957bool
2958EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2959{
2960#if 0
2961 // ARM pseudo code...
2962 if ConditionPassed() then
2963 EncodingSpecificOperations();
2964 shift_n = UInt(R[m]<7:0>);
2965 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2966 R[d] = result;
2967 if setflags then
2968 APSR.N = result<31>;
2969 APSR.Z = IsZeroBit(result);
2970 APSR.C = carry;
2971 // APSR.V unchanged
2972#endif
2973
2974 return EmulateShiftReg(encoding, SRType_ROR);
2975}
2976
2977// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2978// with the carry flag shifted into bit [31].
2979//
2980// RRX can optionally update the condition flags based on the result.
2981// In that case, bit [0] is shifted into the carry flag.
2982bool
2983EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2984{
2985#if 0
2986 // ARM pseudo code...
2987 if ConditionPassed() then
2988 EncodingSpecificOperations();
2989 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2990 if d == 15 then // Can only occur for ARM encoding
2991 ALUWritePC(result); // setflags is always FALSE here
2992 else
2993 R[d] = result;
2994 if setflags then
2995 APSR.N = result<31>;
2996 APSR.Z = IsZeroBit(result);
2997 APSR.C = carry;
2998 // APSR.V unchanged
2999#endif
3000
3001 return EmulateShiftImm(encoding, SRType_RRX);
3002}
3003
Johnny Chen41a0a152011-02-16 01:27:54 +00003004bool
3005EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
3006{
3007 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
3008
Johnny Chen82f16aa2011-02-15 20:10:55 +00003009 bool success = false;
3010 const uint32_t opcode = OpcodeAsUnsigned (&success);
3011 if (!success)
3012 return false;
3013
3014 if (ConditionPassed())
3015 {
Johnny Chene7f89532011-02-15 23:22:46 +00003016 uint32_t Rd; // the destination register
3017 uint32_t Rm; // the first operand register
3018 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003019 uint32_t carry; // the carry bit after the shift operation
3020 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003021
3022 // Special case handling!
3023 // A8.6.139 ROR (immediate) -- Encoding T1
3024 if (shift_type == SRType_ROR && encoding == eEncodingT1)
3025 {
3026 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3027 // have the same decoding of bit fields as the other Thumb2 shift operations.
3028 encoding = eEncodingT2;
3029 }
3030
Johnny Chen82f16aa2011-02-15 20:10:55 +00003031 switch (encoding) {
3032 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003033 // Due to the above special case handling!
3034 assert(shift_type != SRType_ROR);
3035
Johnny Chen82f16aa2011-02-15 20:10:55 +00003036 Rd = Bits32(opcode, 2, 0);
3037 Rm = Bits32(opcode, 5, 3);
3038 setflags = !InITBlock();
3039 imm5 = Bits32(opcode, 10, 6);
3040 break;
3041 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003042 // A8.6.141 RRX
3043 assert(shift_type != SRType_RRX);
3044
Johnny Chen82f16aa2011-02-15 20:10:55 +00003045 Rd = Bits32(opcode, 11, 8);
3046 Rm = Bits32(opcode, 3, 0);
3047 setflags = BitIsSet(opcode, 20);
3048 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3049 if (BadReg(Rd) || BadReg(Rm))
3050 return false;
3051 break;
3052 case eEncodingA1:
3053 Rd = Bits32(opcode, 15, 12);
3054 Rm = Bits32(opcode, 3, 0);
3055 setflags = BitIsSet(opcode, 20);
3056 imm5 = Bits32(opcode, 11, 7);
3057 break;
3058 default:
3059 return false;
3060 }
3061
Johnny Cheneeab4852011-02-16 22:14:44 +00003062 // A8.6.139 ROR (immediate)
3063 if (shift_type == SRType_ROR && imm5 == 0)
3064 shift_type = SRType_RRX;
3065
Johnny Chen82f16aa2011-02-15 20:10:55 +00003066 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003067 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003068 if (!success)
3069 return false;
3070
Johnny Cheneeab4852011-02-16 22:14:44 +00003071 // Decode the shift amount if not RRX.
3072 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003073
Johnny Chene97c0d52011-02-18 19:32:20 +00003074 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003075
3076 // The context specifies that an immediate is to be moved into Rd.
3077 EmulateInstruction::Context context;
3078 context.type = EmulateInstruction::eContextImmediate;
3079 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003080
Johnny Chen10530c22011-02-17 22:37:12 +00003081 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003082 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003083 }
3084 return true;
3085}
3086
Johnny Chene7f89532011-02-15 23:22:46 +00003087bool
Johnny Chen41a0a152011-02-16 01:27:54 +00003088EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003089{
Johnny Chen41a0a152011-02-16 01:27:54 +00003090 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003091
3092 bool success = false;
3093 const uint32_t opcode = OpcodeAsUnsigned (&success);
3094 if (!success)
3095 return false;
3096
3097 if (ConditionPassed())
3098 {
3099 uint32_t Rd; // the destination register
3100 uint32_t Rn; // the first operand register
3101 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3102 uint32_t carry; // the carry bit after the shift operation
3103 bool setflags;
3104 switch (encoding) {
3105 case eEncodingT1:
3106 Rd = Bits32(opcode, 2, 0);
3107 Rn = Rd;
3108 Rm = Bits32(opcode, 5, 3);
3109 setflags = !InITBlock();
3110 break;
3111 case eEncodingT2:
3112 Rd = Bits32(opcode, 11, 8);
3113 Rn = Bits32(opcode, 19, 16);
3114 Rm = Bits32(opcode, 3, 0);
3115 setflags = BitIsSet(opcode, 20);
3116 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3117 return false;
3118 break;
3119 case eEncodingA1:
3120 Rd = Bits32(opcode, 15, 12);
3121 Rn = Bits32(opcode, 3, 0);
3122 Rm = Bits32(opcode, 11, 8);
3123 setflags = BitIsSet(opcode, 20);
3124 if (Rd == 15 || Rn == 15 || Rm == 15)
3125 return false;
3126 break;
3127 default:
3128 return false;
3129 }
3130
3131 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003132 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003133 if (!success)
3134 return false;
3135 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003136 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003137 if (!success)
3138 return false;
3139
3140 // Get the shift amount.
3141 uint32_t amt = Bits32(val, 7, 0);
3142
Johnny Chene97c0d52011-02-18 19:32:20 +00003143 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003144
3145 // The context specifies that an immediate is to be moved into Rd.
3146 EmulateInstruction::Context context;
3147 context.type = EmulateInstruction::eContextImmediate;
3148 context.SetNoArgs ();
3149
Johnny Chen10530c22011-02-17 22:37:12 +00003150 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003151 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003152 }
3153 return true;
3154}
3155
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003156// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003157// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003158// can be written back to the base register.
3159bool
3160EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
3161{
3162#if 0
3163 // ARM pseudo code...
3164 if ConditionPassed()
3165 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3166 address = R[n];
3167
3168 for i = 0 to 14
3169 if registers<i> == '1' then
3170 R[i] = MemA[address, 4]; address = address + 4;
3171 if registers<15> == '1' then
3172 LoadWritePC (MemA[address, 4]);
3173
3174 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3175 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3176
3177#endif
3178
3179 bool success = false;
3180 const uint32_t opcode = OpcodeAsUnsigned (&success);
3181 if (!success)
3182 return false;
3183
3184 if (ConditionPassed())
3185 {
3186 uint32_t n;
3187 uint32_t registers = 0;
3188 bool wback;
3189 const uint32_t addr_byte_size = GetAddressByteSize();
3190 switch (encoding)
3191 {
3192 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003193 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003194 n = Bits32 (opcode, 10, 8);
3195 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003196 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003197 wback = BitIsClear (registers, n);
3198 // if BitCount(registers) < 1 then UNPREDICTABLE;
3199 if (BitCount(registers) < 1)
3200 return false;
3201 break;
3202 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003203 // if W == ’1’ && Rn == ’1101’ then SEE POP;
3204 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003205 n = Bits32 (opcode, 19, 16);
3206 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003207 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003208 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003209
3210 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003211 if ((n == 15)
3212 || (BitCount (registers) < 2)
3213 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3214 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003215
3216 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003217 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003218 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003219
3220 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003221 if (wback
3222 && BitIsSet (registers, n))
3223 return false;
3224 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003225
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003226 case eEncodingA1:
3227 n = Bits32 (opcode, 19, 16);
3228 registers = Bits32 (opcode, 15, 0);
3229 wback = BitIsSet (opcode, 21);
3230 if ((n == 15)
3231 || (BitCount (registers) < 1))
3232 return false;
3233 break;
3234 default:
3235 return false;
3236 }
3237
3238 int32_t offset = 0;
3239 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3240 if (!success)
3241 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003242
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003243 EmulateInstruction::Context context;
3244 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3245 Register dwarf_reg;
3246 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3247 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003248
3249 for (int i = 0; i < 14; ++i)
3250 {
3251 if (BitIsSet (registers, i))
3252 {
Caroline Tice85aab332011-02-08 23:56:10 +00003253 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003254 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003255 if (wback && (n == 13)) // Pop Instruction
3256 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3257
3258 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003259 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003260 if (!success)
3261 return false;
3262
3263 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3264 return false;
3265
3266 offset += addr_byte_size;
3267 }
3268 }
3269
3270 if (BitIsSet (registers, 15))
3271 {
3272 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003273 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003274 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003275 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003276 if (!success)
3277 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003278 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003279 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003280 return false;
3281 }
3282
3283 if (wback && BitIsClear (registers, n))
3284 {
Caroline Ticefa172202011-02-11 22:49:54 +00003285 // R[n] = R[n] + 4 * BitCount (registers)
3286 int32_t offset = addr_byte_size * BitCount (registers);
3287 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003288 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003289
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003290 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3291 return false;
3292 }
3293 if (wback && BitIsSet (registers, n))
3294 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003295 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003296 }
3297 return true;
3298}
Caroline Tice713c2662011-02-11 17:59:55 +00003299
3300// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3301// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3302// can optionally be written back tot he base registers.
3303bool
3304EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
3305{
3306#if 0
3307 // ARM pseudo code...
3308 if ConditionPassed() then
3309 EncodingSpecificOperations();
3310 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003311
Caroline Tice713c2662011-02-11 17:59:55 +00003312 for i = 0 to 14
3313 if registers<i> == ’1’ then
3314 R[i] = MemA[address,4]; address = address + 4;
3315
3316 if registers<15> == ’1’ then
3317 LoadWritePC(MemA[address,4]);
3318
3319 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3320 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3321#endif
3322
3323 bool success = false;
3324 const uint32_t opcode = OpcodeAsUnsigned (&success);
3325 if (!success)
3326 return false;
3327
3328 if (ConditionPassed())
3329 {
3330 uint32_t n;
3331 uint32_t registers = 0;
3332 bool wback;
3333 const uint32_t addr_byte_size = GetAddressByteSize();
3334
3335 // EncodingSpecificOperations();
3336 switch (encoding)
3337 {
3338 case eEncodingA1:
3339 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3340 n = Bits32 (opcode, 19, 16);
3341 registers = Bits32 (opcode, 15, 0);
3342 wback = BitIsSet (opcode, 21);
3343
3344 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3345 if ((n == 15) || (BitCount (registers) < 1))
3346 return false;
3347
3348 break;
3349
3350 default:
3351 return false;
3352 }
3353 // address = R[n] - 4*BitCount(registers) + 4;
3354
3355 int32_t offset = 0;
3356 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3357
3358 if (!success)
3359 return false;
3360
3361 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3362
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003363 EmulateInstruction::Context context;
3364 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3365 Register dwarf_reg;
3366 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3367 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003368
3369 // for i = 0 to 14
3370 for (int i = 0; i < 14; ++i)
3371 {
3372 // if registers<i> == ’1’ then
3373 if (BitIsSet (registers, i))
3374 {
3375 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003376 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003377 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003378 if (!success)
3379 return false;
3380 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3381 return false;
3382 offset += addr_byte_size;
3383 }
3384 }
3385
3386 // if registers<15> == ’1’ then
3387 // LoadWritePC(MemA[address,4]);
3388 if (BitIsSet (registers, 15))
3389 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003390 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003391 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003392 if (!success)
3393 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003394 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003395 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003396 return false;
3397 }
3398
3399 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3400 if (wback && BitIsClear (registers, n))
3401 {
Caroline Tice713c2662011-02-11 17:59:55 +00003402 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3403 if (!success)
3404 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003405
3406 offset = (addr_byte_size * BitCount (registers)) * -1;
3407 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003408 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003409 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003410 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3411 return false;
3412 }
3413
3414 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3415 if (wback && BitIsSet (registers, n))
3416 return WriteBits32Unknown (n);
3417 }
3418 return true;
3419}
3420
3421// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3422// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3423// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003424bool
3425EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3426{
3427#if 0
3428 // ARM pseudo code...
3429 if ConditionPassed() then
3430 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3431 address = R[n] - 4*BitCount(registers);
3432
3433 for i = 0 to 14
3434 if registers<i> == ’1’ then
3435 R[i] = MemA[address,4]; address = address + 4;
3436 if registers<15> == ’1’ then
3437 LoadWritePC(MemA[address,4]);
3438
3439 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3440 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3441#endif
3442
3443 bool success = false;
3444 const uint32_t opcode = OpcodeAsUnsigned (&success);
3445 if (!success)
3446 return false;
3447
3448 if (ConditionPassed())
3449 {
3450 uint32_t n;
3451 uint32_t registers = 0;
3452 bool wback;
3453 const uint32_t addr_byte_size = GetAddressByteSize();
3454 switch (encoding)
3455 {
3456 case eEncodingT1:
3457 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3458 n = Bits32 (opcode, 19, 16);
3459 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003460 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003461 wback = BitIsSet (opcode, 21);
3462
3463 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3464 if ((n == 15)
3465 || (BitCount (registers) < 2)
3466 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3467 return false;
3468
3469 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003470 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003471 return false;
3472
3473 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3474 if (wback && BitIsSet (registers, n))
3475 return false;
3476
3477 break;
3478
3479 case eEncodingA1:
3480 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3481 n = Bits32 (opcode, 19, 16);
3482 registers = Bits32 (opcode, 15, 0);
3483 wback = BitIsSet (opcode, 21);
3484
3485 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3486 if ((n == 15) || (BitCount (registers) < 1))
3487 return false;
3488
3489 break;
3490
3491 default:
3492 return false;
3493 }
3494
Caroline Tice713c2662011-02-11 17:59:55 +00003495 // address = R[n] - 4*BitCount(registers);
3496
Caroline Tice0b29e242011-02-08 23:16:02 +00003497 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003498 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3499
3500 if (!success)
3501 return false;
3502
3503 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003504 EmulateInstruction::Context context;
3505 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3506 Register dwarf_reg;
3507 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3508 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003509
3510 for (int i = 0; i < 14; ++i)
3511 {
3512 if (BitIsSet (registers, i))
3513 {
3514 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003515 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003516 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003517 if (!success)
3518 return false;
3519
3520 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3521 return false;
3522
3523 offset += addr_byte_size;
3524 }
3525 }
3526
3527 // if registers<15> == ’1’ then
3528 // LoadWritePC(MemA[address,4]);
3529 if (BitIsSet (registers, 15))
3530 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003531 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003532 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003533 if (!success)
3534 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003535 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003536 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003537 return false;
3538 }
3539
3540 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3541 if (wback && BitIsClear (registers, n))
3542 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003543 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3544 if (!success)
3545 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003546
3547 offset = (addr_byte_size * BitCount (registers)) * -1;
3548 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003549 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003550 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003551 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3552 return false;
3553 }
3554
3555 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3556 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003557 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003558 }
3559 return true;
3560}
Caroline Tice85aab332011-02-08 23:56:10 +00003561
Caroline Tice713c2662011-02-11 17:59:55 +00003562// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3563// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3564// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003565bool
3566EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3567{
3568#if 0
3569 if ConditionPassed() then
3570 EncodingSpecificOperations();
3571 address = R[n] + 4;
3572
3573 for i = 0 to 14
3574 if registers<i> == ’1’ then
3575 R[i] = MemA[address,4]; address = address + 4;
3576 if registers<15> == ’1’ then
3577 LoadWritePC(MemA[address,4]);
3578
3579 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3580 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3581#endif
3582
3583 bool success = false;
3584 const uint32_t opcode = OpcodeAsUnsigned (&success);
3585 if (!success)
3586 return false;
3587
3588 if (ConditionPassed())
3589 {
3590 uint32_t n;
3591 uint32_t registers = 0;
3592 bool wback;
3593 const uint32_t addr_byte_size = GetAddressByteSize();
3594 switch (encoding)
3595 {
3596 case eEncodingA1:
3597 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3598 n = Bits32 (opcode, 19, 16);
3599 registers = Bits32 (opcode, 15, 0);
3600 wback = BitIsSet (opcode, 21);
3601
3602 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3603 if ((n == 15) || (BitCount (registers) < 1))
3604 return false;
3605
3606 break;
3607 default:
3608 return false;
3609 }
3610 // address = R[n] + 4;
3611
3612 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003613 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3614
3615 if (!success)
3616 return false;
3617
3618 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003619
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003620 EmulateInstruction::Context context;
3621 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3622 Register dwarf_reg;
3623 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3624 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003625
3626 for (int i = 0; i < 14; ++i)
3627 {
3628 if (BitIsSet (registers, i))
3629 {
3630 // R[i] = MemA[address,4]; address = address + 4;
3631
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003632 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003633 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003634 if (!success)
3635 return false;
3636
3637 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3638 return false;
3639
3640 offset += addr_byte_size;
3641 }
3642 }
3643
3644 // if registers<15> == ’1’ then
3645 // LoadWritePC(MemA[address,4]);
3646 if (BitIsSet (registers, 15))
3647 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003648 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003649 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003650 if (!success)
3651 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003652 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003653 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003654 return false;
3655 }
3656
3657 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3658 if (wback && BitIsClear (registers, n))
3659 {
Caroline Tice85aab332011-02-08 23:56:10 +00003660 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3661 if (!success)
3662 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003663
3664 offset = addr_byte_size * BitCount (registers);
3665 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003666 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003667 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003668 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3669 return false;
3670 }
3671
3672 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3673 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003674 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003675 }
3676 return true;
3677}
Caroline Tice0b29e242011-02-08 23:16:02 +00003678
Johnny Chenef21b592011-02-10 01:52:38 +00003679// Load Register (immediate) calculates an address from a base register value and
3680// an immediate offset, loads a word from memory, and writes to a register.
3681// LDR (immediate, Thumb)
3682bool
3683EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3684{
3685#if 0
3686 // ARM pseudo code...
3687 if (ConditionPassed())
3688 {
3689 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3690 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3691 address = if index then offset_addr else R[n];
3692 data = MemU[address,4];
3693 if wback then R[n] = offset_addr;
3694 if t == 15 then
3695 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3696 elsif UnalignedSupport() || address<1:0> = '00' then
3697 R[t] = data;
3698 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3699 }
3700#endif
3701
3702 bool success = false;
3703 const uint32_t opcode = OpcodeAsUnsigned (&success);
3704 if (!success)
3705 return false;
3706
3707 if (ConditionPassed())
3708 {
3709 uint32_t Rt; // the destination register
3710 uint32_t Rn; // the base register
3711 uint32_t imm32; // the immediate offset used to form the address
3712 addr_t offset_addr; // the offset address
3713 addr_t address; // the calculated address
3714 uint32_t data; // the literal data value from memory load
3715 bool add, index, wback;
3716 switch (encoding) {
3717 case eEncodingT1:
3718 Rt = Bits32(opcode, 5, 3);
3719 Rn = Bits32(opcode, 2, 0);
3720 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3721 // index = TRUE; add = TRUE; wback = FALSE
3722 add = true;
3723 index = true;
3724 wback = false;
3725 break;
3726 default:
3727 return false;
3728 }
3729 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3730 if (!success)
3731 return false;
3732 if (add)
3733 offset_addr = base + imm32;
3734 else
3735 offset_addr = base - imm32;
3736
3737 address = (index ? offset_addr : base);
3738
3739 if (wback)
3740 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003741 EmulateInstruction::Context ctx;
3742 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3743 Register dwarf_reg;
3744 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3745 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3746
Johnny Chenef21b592011-02-10 01:52:38 +00003747 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3748 return false;
3749 }
3750
3751 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003752 EmulateInstruction::Context context;
3753 context.type = EmulateInstruction::eContextImmediate;
3754 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003755
3756 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003757 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003758 if (!success)
3759 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003760
3761 if (Rt == 15)
3762 {
3763 if (Bits32(address, 1, 0) == 0)
3764 {
Johnny Chen668b4512011-02-15 21:08:58 +00003765 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003766 return false;
3767 }
3768 else
3769 return false;
3770 }
3771 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3772 {
3773 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3774 return false;
3775 }
3776 else
3777 return false;
3778 }
3779 return true;
3780}
3781
Caroline Ticeaf556562011-02-15 18:42:15 +00003782// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3783// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3784// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003785bool
3786EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3787{
3788#if 0
3789 if ConditionPassed() then
3790 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3791 address = R[n];
3792
3793 for i = 0 to 14
3794 if registers<i> == ’1’ then
3795 if i == n && wback && i != LowestSetBit(registers) then
3796 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3797 else
3798 MemA[address,4] = R[i];
3799 address = address + 4;
3800
3801 if registers<15> == ’1’ then // Only possible for encoding A1
3802 MemA[address,4] = PCStoreValue();
3803 if wback then R[n] = R[n] + 4*BitCount(registers);
3804#endif
3805
3806 bool success = false;
3807 const uint32_t opcode = OpcodeAsUnsigned (&success);
3808 if (!success)
3809 return false;
3810
3811 if (ConditionPassed ())
3812 {
3813 uint32_t n;
3814 uint32_t registers = 0;
3815 bool wback;
3816 const uint32_t addr_byte_size = GetAddressByteSize();
3817
3818 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3819 switch (encoding)
3820 {
3821 case eEncodingT1:
3822 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3823 n = Bits32 (opcode, 10, 8);
3824 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003825 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003826 wback = true;
3827
3828 // if BitCount(registers) < 1 then UNPREDICTABLE;
3829 if (BitCount (registers) < 1)
3830 return false;
3831
3832 break;
3833
3834 case eEncodingT2:
3835 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3836 n = Bits32 (opcode, 19, 16);
3837 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003838 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003839 wback = BitIsSet (opcode, 21);
3840
3841 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3842 if ((n == 15) || (BitCount (registers) < 2))
3843 return false;
3844
3845 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3846 if (wback && BitIsSet (registers, n))
3847 return false;
3848
3849 break;
3850
3851 case eEncodingA1:
3852 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3853 n = Bits32 (opcode, 19, 16);
3854 registers = Bits32 (opcode, 15, 0);
3855 wback = BitIsSet (opcode, 21);
3856
3857 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3858 if ((n == 15) || (BitCount (registers) < 1))
3859 return false;
3860
3861 break;
3862
3863 default:
3864 return false;
3865 }
3866
3867 // address = R[n];
3868 int32_t offset = 0;
3869 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3870 if (!success)
3871 return false;
3872
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003873 EmulateInstruction::Context context;
3874 context.type = EmulateInstruction::eContextRegisterStore;
3875 Register base_reg;
3876 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003877
3878 // for i = 0 to 14
3879 for (int i = 0; i < 14; ++i)
3880 {
3881 int lowest_set_bit = 14;
3882 // if registers<i> == ’1’ then
3883 if (BitIsSet (registers, i))
3884 {
3885 if (i < lowest_set_bit)
3886 lowest_set_bit = i;
3887 // if i == n && wback && i != LowestSetBit(registers) then
3888 if ((i == n) && wback && (i != lowest_set_bit))
3889 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3890 WriteBits32UnknownToMemory (address + offset);
3891 else
3892 {
3893 // MemA[address,4] = R[i];
3894 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3895 if (!success)
3896 return false;
3897
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003898 Register data_reg;
3899 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3900 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003901 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003902 return false;
3903 }
3904
3905 // address = address + 4;
3906 offset += addr_byte_size;
3907 }
3908 }
3909
3910 // if registers<15> == ’1’ then // Only possible for encoding A1
3911 // MemA[address,4] = PCStoreValue();
3912 if (BitIsSet (registers, 15))
3913 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003914 Register pc_reg;
3915 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3916 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00003917 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticefa172202011-02-11 22:49:54 +00003918 if (!success)
3919 return false;
3920
Caroline Tice8d681f52011-03-17 23:50:16 +00003921 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003922 return false;
3923 }
3924
3925 // if wback then R[n] = R[n] + 4*BitCount(registers);
3926 if (wback)
3927 {
3928 offset = addr_byte_size * BitCount (registers);
3929 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003930 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003931 addr_t data = address + offset;
3932 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3933 return false;
3934 }
3935 }
3936 return true;
3937}
3938
Caroline Ticeaf556562011-02-15 18:42:15 +00003939// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3940// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3941// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003942bool
3943EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3944{
3945#if 0
3946 if ConditionPassed() then
3947 EncodingSpecificOperations();
3948 address = R[n] - 4*BitCount(registers) + 4;
3949
3950 for i = 0 to 14
3951 if registers<i> == ’1’ then
3952 if i == n && wback && i != LowestSetBit(registers) then
3953 MemA[address,4] = bits(32) UNKNOWN;
3954 else
3955 MemA[address,4] = R[i];
3956 address = address + 4;
3957
3958 if registers<15> == ’1’ then
3959 MemA[address,4] = PCStoreValue();
3960
3961 if wback then R[n] = R[n] - 4*BitCount(registers);
3962#endif
3963
3964 bool success = false;
3965 const uint32_t opcode = OpcodeAsUnsigned (&success);
3966 if (!success)
3967 return false;
3968
3969 if (ConditionPassed ())
3970 {
3971 uint32_t n;
3972 uint32_t registers = 0;
3973 bool wback;
3974 const uint32_t addr_byte_size = GetAddressByteSize();
3975
3976 // EncodingSpecificOperations();
3977 switch (encoding)
3978 {
3979 case eEncodingA1:
3980 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3981 n = Bits32 (opcode, 19, 16);
3982 registers = Bits32 (opcode, 15, 0);
3983 wback = BitIsSet (opcode, 21);
3984
3985 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3986 if ((n == 15) || (BitCount (registers) < 1))
3987 return false;
3988 break;
3989 default:
3990 return false;
3991 }
3992
3993 // address = R[n] - 4*BitCount(registers) + 4;
3994 int32_t offset = 0;
3995 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3996 if (!success)
3997 return false;
3998
3999 address = address - (addr_byte_size * BitCount (registers)) + 4;
4000
4001 EmulateInstruction::Context context;
4002 context.type = EmulateInstruction::eContextRegisterStore;
4003 Register base_reg;
4004 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4005
4006 // for i = 0 to 14
4007 for (int i = 0; i < 14; ++i)
4008 {
4009 int lowest_bit_set = 14;
4010 // if registers<i> == ’1’ then
4011 if (BitIsSet (registers, i))
4012 {
4013 if (i < lowest_bit_set)
4014 lowest_bit_set = i;
4015 //if i == n && wback && i != LowestSetBit(registers) then
4016 if ((i == n) && wback && (i != lowest_bit_set))
4017 // MemA[address,4] = bits(32) UNKNOWN;
4018 WriteBits32UnknownToMemory (address + offset);
4019 else
4020 {
4021 // MemA[address,4] = R[i];
4022 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4023 if (!success)
4024 return false;
4025
4026 Register data_reg;
4027 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4028 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004029 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004030 return false;
4031 }
4032
4033 // address = address + 4;
4034 offset += addr_byte_size;
4035 }
4036 }
4037
4038 // if registers<15> == ’1’ then
4039 // MemA[address,4] = PCStoreValue();
4040 if (BitIsSet (registers, 15))
4041 {
4042 Register pc_reg;
4043 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4044 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004045 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Tice1511f502011-02-15 00:19:42 +00004046 if (!success)
4047 return false;
4048
Caroline Tice8d681f52011-03-17 23:50:16 +00004049 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004050 return false;
4051 }
4052
4053 // if wback then R[n] = R[n] - 4*BitCount(registers);
4054 if (wback)
4055 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004056 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004057 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4058 context.SetImmediateSigned (offset);
4059 addr_t data = address + offset;
4060 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4061 return false;
4062 }
4063 }
4064 return true;
4065}
4066
Caroline Ticeaf556562011-02-15 18:42:15 +00004067// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4068// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4069// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004070bool
4071EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
4072{
4073#if 0
4074 if ConditionPassed() then
4075 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4076 address = R[n] - 4*BitCount(registers);
4077
4078 for i = 0 to 14
4079 if registers<i> == ’1’ then
4080 if i == n && wback && i != LowestSetBit(registers) then
4081 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4082 else
4083 MemA[address,4] = R[i];
4084 address = address + 4;
4085
4086 if registers<15> == ’1’ then // Only possible for encoding A1
4087 MemA[address,4] = PCStoreValue();
4088
4089 if wback then R[n] = R[n] - 4*BitCount(registers);
4090#endif
4091
4092
4093 bool success = false;
4094 const uint32_t opcode = OpcodeAsUnsigned (&success);
4095 if (!success)
4096 return false;
4097
4098 if (ConditionPassed ())
4099 {
4100 uint32_t n;
4101 uint32_t registers = 0;
4102 bool wback;
4103 const uint32_t addr_byte_size = GetAddressByteSize();
4104
4105 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4106 switch (encoding)
4107 {
4108 case eEncodingT1:
4109 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
4110 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4111 {
4112 // See PUSH
4113 }
4114 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
4115 n = Bits32 (opcode, 19, 16);
4116 registers = Bits32 (opcode, 15, 0);
4117 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4118 wback = BitIsSet (opcode, 21);
4119 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4120 if ((n == 15) || BitCount (registers) < 2)
4121 return false;
4122 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
4123 if (wback && BitIsSet (registers, n))
4124 return false;
4125 break;
4126
4127 case eEncodingA1:
4128 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4129 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4130 {
4131 // See Push
4132 }
4133 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4134 n = Bits32 (opcode, 19, 16);
4135 registers = Bits32 (opcode, 15, 0);
4136 wback = BitIsSet (opcode, 21);
4137 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4138 if ((n == 15) || BitCount (registers) < 1)
4139 return false;
4140 break;
4141
4142 default:
4143 return false;
4144 }
4145
4146 // address = R[n] - 4*BitCount(registers);
4147
4148 int32_t offset = 0;
4149 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4150 if (!success)
4151 return false;
4152
4153 address = address - (addr_byte_size * BitCount (registers));
4154
4155 EmulateInstruction::Context context;
4156 context.type = EmulateInstruction::eContextRegisterStore;
4157 Register base_reg;
4158 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4159
4160 // for i = 0 to 14
4161 for (int i = 0; i < 14; ++i)
4162 {
4163 uint32_t lowest_set_bit = 14;
4164 // if registers<i> == ’1’ then
4165 if (BitIsSet (registers, i))
4166 {
4167 if (i < lowest_set_bit)
4168 lowest_set_bit = i;
4169 // if i == n && wback && i != LowestSetBit(registers) then
4170 if ((i == n) && wback && (i != lowest_set_bit))
4171 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4172 WriteBits32UnknownToMemory (address + offset);
4173 else
4174 {
4175 // MemA[address,4] = R[i];
4176 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4177 if (!success)
4178 return false;
4179
4180 Register data_reg;
4181 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4182 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004183 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004184 return false;
4185 }
4186
4187 // address = address + 4;
4188 offset += addr_byte_size;
4189 }
4190 }
4191
4192 // if registers<15> == ’1’ then // Only possible for encoding A1
4193 // MemA[address,4] = PCStoreValue();
4194 if (BitIsSet (registers, 15))
4195 {
4196 Register pc_reg;
4197 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4198 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004199 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004200 if (!success)
4201 return false;
4202
Caroline Tice8d681f52011-03-17 23:50:16 +00004203 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004204 return false;
4205 }
4206
4207 // if wback then R[n] = R[n] - 4*BitCount(registers);
4208 if (wback)
4209 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004210 offset = (addr_byte_size * BitCount (registers)) * -1;
4211 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4212 context.SetImmediateSigned (offset);
4213 addr_t data = address + offset;
4214 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4215 return false;
4216 }
4217 }
4218 return true;
4219}
4220
4221// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4222// from a base register. The consecutive memory locations start just above this address, and the address of the last
4223// of those locations can optionally be written back to the base register.
4224bool
4225EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
4226{
4227#if 0
4228 if ConditionPassed() then
4229 EncodingSpecificOperations();
4230 address = R[n] + 4;
4231
4232 for i = 0 to 14
4233 if registers<i> == ’1’ then
4234 if i == n && wback && i != LowestSetBit(registers) then
4235 MemA[address,4] = bits(32) UNKNOWN;
4236 else
4237 MemA[address,4] = R[i];
4238 address = address + 4;
4239
4240 if registers<15> == ’1’ then
4241 MemA[address,4] = PCStoreValue();
4242
4243 if wback then R[n] = R[n] + 4*BitCount(registers);
4244#endif
4245
4246 bool success = false;
4247 const uint32_t opcode = OpcodeAsUnsigned (&success);
4248 if (!success)
4249 return false;
4250
4251 if (ConditionPassed())
4252 {
4253 uint32_t n;
4254 uint32_t registers = 0;
4255 bool wback;
4256 const uint32_t addr_byte_size = GetAddressByteSize();
4257
4258 // EncodingSpecificOperations();
4259 switch (encoding)
4260 {
4261 case eEncodingA1:
4262 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4263 n = Bits32 (opcode, 19, 16);
4264 registers = Bits32 (opcode, 15, 0);
4265 wback = BitIsSet (opcode, 21);
4266
4267 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4268 if ((n == 15) && (BitCount (registers) < 1))
4269 return false;
4270 break;
4271 default:
4272 return false;
4273 }
4274 // address = R[n] + 4;
4275
4276 int32_t offset = 0;
4277 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4278 if (!success)
4279 return false;
4280
4281 address = address + addr_byte_size;
4282
4283 EmulateInstruction::Context context;
4284 context.type = EmulateInstruction::eContextRegisterStore;
4285 Register base_reg;
4286 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4287
4288 uint32_t lowest_set_bit = 14;
4289 // for i = 0 to 14
4290 for (int i = 0; i < 14; ++i)
4291 {
4292 // if registers<i> == ’1’ then
4293 if (BitIsSet (registers, i))
4294 {
4295 if (i < lowest_set_bit)
4296 lowest_set_bit = i;
4297 // if i == n && wback && i != LowestSetBit(registers) then
4298 if ((i == n) && wback && (i != lowest_set_bit))
4299 // MemA[address,4] = bits(32) UNKNOWN;
4300 WriteBits32UnknownToMemory (address + offset);
4301 // else
4302 else
4303 {
4304 // MemA[address,4] = R[i];
4305 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4306 if (!success)
4307 return false;
4308
4309 Register data_reg;
4310 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4311 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004312 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004313 return false;
4314 }
4315
4316 // address = address + 4;
4317 offset += addr_byte_size;
4318 }
4319 }
4320
4321 // if registers<15> == ’1’ then
4322 // MemA[address,4] = PCStoreValue();
4323 if (BitIsSet (registers, 15))
4324 {
4325 Register pc_reg;
4326 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4327 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Tice8d681f52011-03-17 23:50:16 +00004328 const uint32_t pc = ReadCoreReg (PC_REG, &success);
Caroline Ticeaf556562011-02-15 18:42:15 +00004329 if (!success)
4330 return false;
4331
Caroline Tice8d681f52011-03-17 23:50:16 +00004332 if (!MemAWrite (context, address + offset, pc, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004333 return false;
4334 }
4335
4336 // if wback then R[n] = R[n] + 4*BitCount(registers);
4337 if (wback)
4338 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004339 offset = addr_byte_size * BitCount (registers);
4340 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4341 context.SetImmediateSigned (offset);
4342 addr_t data = address + offset;
4343 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4344 return false;
4345 }
4346 }
4347 return true;
4348}
Caroline Tice7fac8572011-02-15 22:53:54 +00004349
4350// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4351// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4352bool
4353EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4354{
4355#if 0
4356 if ConditionPassed() then
4357 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4358 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4359 address = if index then offset_addr else R[n];
4360 if UnalignedSupport() || address<1:0> == ’00’ then
4361 MemU[address,4] = R[t];
4362 else // Can only occur before ARMv7
4363 MemU[address,4] = bits(32) UNKNOWN;
4364 if wback then R[n] = offset_addr;
4365#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004366
Caroline Tice7fac8572011-02-15 22:53:54 +00004367 bool success = false;
4368 const uint32_t opcode = OpcodeAsUnsigned (&success);
4369 if (!success)
4370 return false;
4371
4372 if (ConditionPassed())
4373 {
4374 const uint32_t addr_byte_size = GetAddressByteSize();
4375
4376 uint32_t t;
4377 uint32_t n;
4378 uint32_t imm32;
4379 bool index;
4380 bool add;
4381 bool wback;
4382 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4383 switch (encoding)
4384 {
4385 case eEncodingT1:
4386 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4387 t = Bits32 (opcode, 2, 0);
4388 n = Bits32 (opcode, 5, 3);
4389 imm32 = Bits32 (opcode, 10, 6) << 2;
4390
4391 // index = TRUE; add = TRUE; wback = FALSE;
4392 index = true;
4393 add = false;
4394 wback = false;
4395 break;
4396
4397 case eEncodingT2:
4398 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4399 t = Bits32 (opcode, 10, 8);
4400 n = 13;
4401 imm32 = Bits32 (opcode, 7, 0) << 2;
4402
4403 // index = TRUE; add = TRUE; wback = FALSE;
4404 index = true;
4405 add = true;
4406 wback = false;
4407 break;
4408
4409 case eEncodingT3:
4410 // if Rn == ’1111’ then UNDEFINED;
4411 if (Bits32 (opcode, 19, 16) == 15)
4412 return false;
4413
4414 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4415 t = Bits32 (opcode, 15, 12);
4416 n = Bits32 (opcode, 19, 16);
4417 imm32 = Bits32 (opcode, 11, 0);
4418
4419 // index = TRUE; add = TRUE; wback = FALSE;
4420 index = true;
4421 add = true;
4422 wback = false;
4423
4424 // if t == 15 then UNPREDICTABLE;
4425 if (t == 15)
4426 return false;
4427 break;
4428
4429 case eEncodingT4:
4430 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4431 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4432 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4433 if ((Bits32 (opcode, 19, 16) == 15)
4434 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4435 return false;
4436
4437 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4438 t = Bits32 (opcode, 15, 12);
4439 n = Bits32 (opcode, 19, 16);
4440 imm32 = Bits32 (opcode, 7, 0);
4441
4442 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4443 index = BitIsSet (opcode, 10);
4444 add = BitIsSet (opcode, 9);
4445 wback = BitIsSet (opcode, 8);
4446
4447 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4448 if ((t == 15) || (wback && (n == t)))
4449 return false;
4450 break;
4451
4452 default:
4453 return false;
4454 }
4455
4456 addr_t offset_addr;
4457 addr_t address;
4458
4459 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4460 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4461 if (!success)
4462 return false;
4463
4464 if (add)
4465 offset_addr = base_address + imm32;
4466 else
4467 offset_addr = base_address - imm32;
4468
4469 // address = if index then offset_addr else R[n];
4470 if (index)
4471 address = offset_addr;
4472 else
4473 address = base_address;
4474
4475 EmulateInstruction::Context context;
4476 context.type = eContextRegisterStore;
4477 Register base_reg;
4478 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4479
4480 // if UnalignedSupport() || address<1:0> == ’00’ then
4481 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4482 {
4483 // MemU[address,4] = R[t];
4484 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4485 if (!success)
4486 return false;
4487
4488 Register data_reg;
4489 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4490 int32_t offset = address - base_address;
4491 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004492 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004493 return false;
4494 }
4495 else
4496 {
4497 // MemU[address,4] = bits(32) UNKNOWN;
4498 WriteBits32UnknownToMemory (address);
4499 }
4500
4501 // if wback then R[n] = offset_addr;
4502 if (wback)
4503 {
4504 context.type = eContextRegisterLoad;
4505 context.SetAddress (offset_addr);
4506 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4507 return false;
4508 }
4509 }
4510 return true;
4511}
Caroline Ticeaf556562011-02-15 18:42:15 +00004512
Caroline Tice3fd63e92011-02-16 00:33:43 +00004513// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4514// word from a register to memory. The offset register value can optionally be shifted.
4515bool
4516EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4517{
4518#if 0
4519 if ConditionPassed() then
4520 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4521 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4522 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4523 address = if index then offset_addr else R[n];
4524 if t == 15 then // Only possible for encoding A1
4525 data = PCStoreValue();
4526 else
4527 data = R[t];
4528 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4529 MemU[address,4] = data;
4530 else // Can only occur before ARMv7
4531 MemU[address,4] = bits(32) UNKNOWN;
4532 if wback then R[n] = offset_addr;
4533#endif
4534
4535 bool success = false;
4536 const uint32_t opcode = OpcodeAsUnsigned (&success);
4537 if (!success)
4538 return false;
4539
4540 if (ConditionPassed())
4541 {
4542 const uint32_t addr_byte_size = GetAddressByteSize();
4543
4544 uint32_t t;
4545 uint32_t n;
4546 uint32_t m;
4547 ARM_ShifterType shift_t;
4548 uint32_t shift_n;
4549 bool index;
4550 bool add;
4551 bool wback;
4552
4553 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4554 switch (encoding)
4555 {
4556 case eEncodingT1:
4557 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4558 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4559 t = Bits32 (opcode, 2, 0);
4560 n = Bits32 (opcode, 5, 3);
4561 m = Bits32 (opcode, 8, 6);
4562
4563 // index = TRUE; add = TRUE; wback = FALSE;
4564 index = true;
4565 add = true;
4566 wback = false;
4567
4568 // (shift_t, shift_n) = (SRType_LSL, 0);
4569 shift_t = SRType_LSL;
4570 shift_n = 0;
4571 break;
4572
4573 case eEncodingT2:
4574 // if Rn == ’1111’ then UNDEFINED;
4575 if (Bits32 (opcode, 19, 16) == 15)
4576 return false;
4577
4578 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4579 t = Bits32 (opcode, 15, 12);
4580 n = Bits32 (opcode, 19, 16);
4581 m = Bits32 (opcode, 3, 0);
4582
4583 // index = TRUE; add = TRUE; wback = FALSE;
4584 index = true;
4585 add = true;
4586 wback = false;
4587
4588 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4589 shift_t = SRType_LSL;
4590 shift_n = Bits32 (opcode, 5, 4);
4591
4592 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4593 if ((t == 15) || (BadReg (m)))
4594 return false;
4595 break;
4596
4597 case eEncodingA1:
4598 {
4599 // if P == ’0’ && W == ’1’ then SEE STRT;
4600 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4601 t = Bits32 (opcode, 15, 12);
4602 n = Bits32 (opcode, 19, 16);
4603 m = Bits32 (opcode, 3, 0);
4604
4605 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4606 index = BitIsSet (opcode, 24);
4607 add = BitIsSet (opcode, 23);
4608 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4609
4610 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4611 uint32_t typ = Bits32 (opcode, 6, 5);
4612 uint32_t imm5 = Bits32 (opcode, 11, 7);
4613 shift_n = DecodeImmShift(typ, imm5, shift_t);
4614
4615 // if m == 15 then UNPREDICTABLE;
4616 if (m == 15)
4617 return false;
4618
4619 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4620 if (wback && ((n == 15) || (n == t)))
4621 return false;
4622
4623 break;
4624 }
4625 default:
4626 return false;
4627 }
4628
4629 addr_t offset_addr;
4630 addr_t address;
4631 int32_t offset = 0;
4632
4633 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4634 if (!success)
4635 return false;
4636
4637 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4638 if (!success)
4639 return false;
4640
4641 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004642 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004643
4644 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4645 if (add)
4646 offset_addr = base_address + offset;
4647 else
4648 offset_addr = base_address - offset;
4649
4650 // address = if index then offset_addr else R[n];
4651 if (index)
4652 address = offset_addr;
4653 else
4654 address = base_address;
4655
4656 uint32_t data;
4657 // if t == 15 then // Only possible for encoding A1
4658 if (t == 15)
4659 // data = PCStoreValue();
Caroline Tice8d681f52011-03-17 23:50:16 +00004660 data = ReadCoreReg (PC_REG, &success);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004661 else
4662 // data = R[t];
4663 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4664
4665 if (!success)
4666 return false;
4667
4668 EmulateInstruction::Context context;
4669 context.type = eContextRegisterStore;
4670
4671 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4672 if (UnalignedSupport ()
4673 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4674 || CurrentInstrSet() == eModeARM)
4675 {
4676 // MemU[address,4] = data;
4677
4678 Register base_reg;
4679 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4680
4681 Register data_reg;
4682 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4683
4684 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004685 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004686 return false;
4687
4688 }
4689 else
4690 // MemU[address,4] = bits(32) UNKNOWN;
4691 WriteBits32UnknownToMemory (address);
4692
4693 // if wback then R[n] = offset_addr;
4694 if (wback)
4695 {
4696 context.type = eContextRegisterLoad;
4697 context.SetAddress (offset_addr);
4698 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4699 return false;
4700 }
4701
4702 }
4703 return true;
4704}
Caroline Tice73a29de2011-02-16 20:22:22 +00004705
4706bool
4707EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4708{
4709#if 0
4710 if ConditionPassed() then
4711 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4712 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4713 address = if index then offset_addr else R[n];
4714 MemU[address,1] = R[t]<7:0>;
4715 if wback then R[n] = offset_addr;
4716#endif
4717
4718
4719 bool success = false;
4720 const uint32_t opcode = OpcodeAsUnsigned (&success);
4721 if (!success)
4722 return false;
4723
4724 if (ConditionPassed ())
4725 {
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:
4748 // if Rn == ’1111’ then UNDEFINED;
4749 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:
4768 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4769 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4770 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
4778 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4779 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
4847EmulateInstructionARM::EmulateSTRHRegister (ARMEncoding encoding)
4848{
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];
4855 if UnalignedSupport() || address<0> == ’0’ then
4856 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;
4863 const uint32_t opcode = OpcodeAsUnsigned (&success);
4864 if (!success)
4865 return false;
4866
4867 if (ConditionPassed ())
4868 {
4869 uint32_t t;
4870 uint32_t n;
4871 uint32_t m;
4872 bool index;
4873 bool add;
4874 bool wback;
4875 ARM_ShifterType shift_t;
4876 uint32_t shift_n;
4877
4878 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4879 switch (encoding)
4880 {
4881 case eEncodingT1:
4882 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4883 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4884 t = Bits32 (opcode, 2, 0);
4885 n = Bits32 (opcode, 5, 3);
4886 m = Bits32 (opcode, 8, 6);
4887
4888 // index = TRUE; add = TRUE; wback = FALSE;
4889 index = true;
4890 add = true;
4891 wback = false;
4892
4893 // (shift_t, shift_n) = (SRType_LSL, 0);
4894 shift_t = SRType_LSL;
4895 shift_n = 0;
4896
4897 break;
4898
4899 case eEncodingT2:
4900 // if Rn == ’1111’ then UNDEFINED;
4901 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4902 t = Bits32 (opcode, 15, 12);
4903 n = Bits32 (opcode, 19, 16);
4904 m = Bits32 (opcode, 3, 0);
4905 if (n == 15)
4906 return false;
4907
4908 // index = TRUE; add = TRUE; wback = FALSE;
4909 index = true;
4910 add = true;
4911 wback = false;
4912
4913 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4914 shift_t = SRType_LSL;
4915 shift_n = Bits32 (opcode, 5, 4);
4916
4917 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
4918 if (BadReg (t) || BadReg (m))
4919 return false;
4920
4921 break;
4922
4923 case eEncodingA1:
4924 // if P == ’0’ && W == ’1’ then SEE STRHT;
4925 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4926 t = Bits32 (opcode, 15, 12);
4927 n = Bits32 (opcode, 19, 16);
4928 m = Bits32 (opcode, 3, 0);
4929
4930 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4931 index = BitIsSet (opcode, 24);
4932 add = BitIsSet (opcode, 23);
4933 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4934
4935 // (shift_t, shift_n) = (SRType_LSL, 0);
4936 shift_t = SRType_LSL;
4937 shift_n = 0;
4938
4939 // if t == 15 || m == 15 then UNPREDICTABLE;
4940 if ((t == 15) || (m == 15))
4941 return false;
4942
4943 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4944 if (wback && ((n == 15) || (n == t)))
4945 return false;
4946
4947 break;
4948
4949 default:
4950 return false;
4951 }
4952
4953 uint32_t Rm = ReadCoreReg (m, &success);
4954 if (!success)
4955 return false;
4956
4957 uint32_t Rn = ReadCoreReg (n, &success);
4958 if (!success)
4959 return false;
4960
4961 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
4962 uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
4963
4964 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4965 addr_t offset_addr;
4966 if (add)
4967 offset_addr = Rn + offset;
4968 else
4969 offset_addr = Rn - offset;
4970
4971 // address = if index then offset_addr else R[n];
4972 addr_t address;
4973 if (index)
4974 address = offset_addr;
4975 else
4976 address = Rn;
4977
4978 EmulateInstruction::Context context;
4979 context.type = eContextRegisterStore;
4980 Register base_reg;
4981 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4982 Register offset_reg;
4983 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4984
4985 // if UnalignedSupport() || address<0> == ’0’ then
4986 if (UnalignedSupport() || BitIsClear (address, 0))
4987 {
4988 // MemU[address,2] = R[t]<15:0>;
4989 uint32_t Rt = ReadCoreReg (t, &success);
4990 if (!success)
4991 return false;
4992
4993 EmulateInstruction::Context context;
4994 context.type = eContextRegisterStore;
4995 Register base_reg;
4996 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4997 Register offset_reg;
4998 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
4999 Register data_reg;
5000 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5001 context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
5002
5003 if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
5004 return false;
5005 }
5006 else // Can only occur before ARMv7
5007 {
5008 // MemU[address,2] = bits(16) UNKNOWN;
5009 }
5010
5011 // if wback then R[n] = offset_addr;
5012 if (wback)
5013 {
5014 context.type = eContextAdjustBaseRegister;
5015 context.SetAddress (offset_addr);
5016 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5017 return false;
5018 }
5019 }
5020
5021 return true;
5022}
Caroline Tice3fd63e92011-02-16 00:33:43 +00005023
Johnny Chen157b9592011-02-18 21:13:05 +00005024// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
5025// and writes the result to the destination register. It can optionally update the condition flags
5026// based on the result.
5027bool
5028EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
5029{
5030#if 0
5031 // ARM pseudo code...
5032 if ConditionPassed() then
5033 EncodingSpecificOperations();
5034 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5035 if d == 15 then // Can only occur for ARM encoding
5036 ALUWritePC(result); // setflags is always FALSE here
5037 else
5038 R[d] = result;
5039 if setflags then
5040 APSR.N = result<31>;
5041 APSR.Z = IsZeroBit(result);
5042 APSR.C = carry;
5043 APSR.V = overflow;
5044#endif
5045
5046 bool success = false;
5047 const uint32_t opcode = OpcodeAsUnsigned (&success);
5048 if (!success)
5049 return false;
5050
5051 if (ConditionPassed())
5052 {
5053 uint32_t Rd, Rn;
5054 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
5055 bool setflags;
5056 switch (encoding)
5057 {
5058 case eEncodingT1:
5059 Rd = Bits32(opcode, 11, 8);
5060 Rn = Bits32(opcode, 19, 16);
5061 setflags = BitIsSet(opcode, 20);
5062 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5063 if (BadReg(Rd) || BadReg(Rn))
5064 return false;
5065 break;
5066 case eEncodingA1:
5067 Rd = Bits32(opcode, 15, 12);
5068 Rn = Bits32(opcode, 19, 16);
5069 setflags = BitIsSet(opcode, 20);
5070 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5071 // TODO: Emulate SUBS PC, LR and related instructions.
5072 if (Rd == 15 && setflags)
5073 return false;
5074 break;
5075 default:
5076 return false;
5077 }
5078
5079 // Read the first operand.
5080 int32_t val1 = ReadCoreReg(Rn, &success);
5081 if (!success)
5082 return false;
5083
5084 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5085
5086 EmulateInstruction::Context context;
5087 context.type = EmulateInstruction::eContextImmediate;
5088 context.SetNoArgs ();
5089
5090 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5091 return false;
5092 }
5093 return true;
5094}
5095
5096// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
5097// register value, and writes the result to the destination register. It can optionally update the
5098// condition flags based on the result.
5099bool
5100EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
5101{
5102#if 0
5103 // ARM pseudo code...
5104 if ConditionPassed() then
5105 EncodingSpecificOperations();
5106 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5107 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5108 if d == 15 then // Can only occur for ARM encoding
5109 ALUWritePC(result); // setflags is always FALSE here
5110 else
5111 R[d] = result;
5112 if setflags then
5113 APSR.N = result<31>;
5114 APSR.Z = IsZeroBit(result);
5115 APSR.C = carry;
5116 APSR.V = overflow;
5117#endif
5118
5119 bool success = false;
5120 const uint32_t opcode = OpcodeAsUnsigned (&success);
5121 if (!success)
5122 return false;
5123
5124 if (ConditionPassed())
5125 {
5126 uint32_t Rd, Rn, Rm;
5127 ARM_ShifterType shift_t;
5128 uint32_t shift_n; // the shift applied to the value read from Rm
5129 bool setflags;
5130 switch (encoding)
5131 {
5132 case eEncodingT1:
5133 Rd = Rn = Bits32(opcode, 2, 0);
5134 Rm = Bits32(opcode, 5, 3);
5135 setflags = !InITBlock();
5136 shift_t = SRType_LSL;
5137 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005138 break;
Johnny Chen157b9592011-02-18 21:13:05 +00005139 case eEncodingT2:
5140 Rd = Bits32(opcode, 11, 8);
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 = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005145 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5146 return false;
5147 break;
5148 case eEncodingA1:
5149 Rd = Bits32(opcode, 15, 12);
5150 Rn = Bits32(opcode, 19, 16);
5151 Rm = Bits32(opcode, 3, 0);
5152 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005153 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00005154 // TODO: Emulate SUBS PC, LR and related instructions.
5155 if (Rd == 15 && setflags)
5156 return false;
5157 break;
5158 default:
5159 return false;
5160 }
5161
5162 // Read the first operand.
5163 int32_t val1 = ReadCoreReg(Rn, &success);
5164 if (!success)
5165 return false;
5166
5167 // Read the second operand.
5168 int32_t val2 = ReadCoreReg(Rm, &success);
5169 if (!success)
5170 return false;
5171
5172 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
5173 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5174
5175 EmulateInstruction::Context context;
5176 context.type = EmulateInstruction::eContextImmediate;
5177 context.SetNoArgs ();
5178
5179 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
5180 return false;
5181 }
5182 return true;
5183}
5184
Johnny Chena695f952011-02-23 21:24:25 +00005185// This instruction adds an immediate value to the PC value to form a PC-relative address,
5186// and writes the result to the destination register.
5187bool
5188EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
5189{
5190#if 0
5191 // ARM pseudo code...
5192 if ConditionPassed() then
5193 EncodingSpecificOperations();
5194 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5195 if d == 15 then // Can only occur for ARM encodings
5196 ALUWritePC(result);
5197 else
5198 R[d] = result;
5199#endif
5200
5201 bool success = false;
5202 const uint32_t opcode = OpcodeAsUnsigned (&success);
5203 if (!success)
5204 return false;
5205
5206 if (ConditionPassed())
5207 {
5208 uint32_t Rd;
5209 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5210 bool add;
5211 switch (encoding)
5212 {
5213 case eEncodingT1:
5214 Rd = Bits32(opcode, 10, 8);
5215 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5216 break;
5217 case eEncodingT2:
5218 case eEncodingT3:
5219 Rd = Bits32(opcode, 11, 8);
5220 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5221 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5222 if (BadReg(Rd))
5223 return false;
5224 break;
5225 case eEncodingA1:
5226 case eEncodingA2:
5227 Rd = Bits32(opcode, 15, 12);
5228 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5229 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5230 break;
5231 default:
5232 return false;
5233 }
5234
5235 // Read the PC value.
5236 uint32_t pc = ReadCoreReg(PC_REG, &success);
5237 if (!success)
5238 return false;
5239
5240 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5241
5242 EmulateInstruction::Context context;
5243 context.type = EmulateInstruction::eContextImmediate;
5244 context.SetNoArgs ();
5245
5246 if (!WriteCoreReg(context, result, Rd))
5247 return false;
5248 }
5249 return true;
5250}
5251
Johnny Chene97c0d52011-02-18 19:32:20 +00005252// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5253// to the destination register. It can optionally update the condition flags based on the result.
5254bool
5255EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
5256{
5257#if 0
5258 // ARM pseudo code...
5259 if ConditionPassed() then
5260 EncodingSpecificOperations();
5261 result = R[n] AND imm32;
5262 if d == 15 then // Can only occur for ARM encoding
5263 ALUWritePC(result); // setflags is always FALSE here
5264 else
5265 R[d] = result;
5266 if setflags then
5267 APSR.N = result<31>;
5268 APSR.Z = IsZeroBit(result);
5269 APSR.C = carry;
5270 // APSR.V unchanged
5271#endif
5272
5273 bool success = false;
5274 const uint32_t opcode = OpcodeAsUnsigned (&success);
5275 if (!success)
5276 return false;
5277
5278 if (ConditionPassed())
5279 {
5280 uint32_t Rd, Rn;
5281 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5282 bool setflags;
5283 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5284 switch (encoding)
5285 {
5286 case eEncodingT1:
5287 Rd = Bits32(opcode, 11, 8);
5288 Rn = Bits32(opcode, 19, 16);
5289 setflags = BitIsSet(opcode, 20);
5290 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005291 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005292 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005293 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005294 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5295 return false;
5296 break;
5297 case eEncodingA1:
5298 Rd = Bits32(opcode, 15, 12);
5299 Rn = Bits32(opcode, 19, 16);
5300 setflags = BitIsSet(opcode, 20);
5301 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5302 // TODO: Emulate SUBS PC, LR and related instructions.
5303 if (Rd == 15 && setflags)
5304 return false;
5305 break;
5306 default:
5307 return false;
5308 }
5309
Johnny Chene97c0d52011-02-18 19:32:20 +00005310 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005311 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005312 if (!success)
5313 return false;
5314
5315 uint32_t result = val1 & imm32;
5316
5317 EmulateInstruction::Context context;
5318 context.type = EmulateInstruction::eContextImmediate;
5319 context.SetNoArgs ();
5320
5321 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5322 return false;
5323 }
5324 return true;
5325}
5326
5327// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5328// and writes the result to the destination register. It can optionally update the condition flags
5329// based on the result.
5330bool
5331EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
5332{
5333#if 0
5334 // ARM pseudo code...
5335 if ConditionPassed() then
5336 EncodingSpecificOperations();
5337 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5338 result = R[n] AND shifted;
5339 if d == 15 then // Can only occur for ARM encoding
5340 ALUWritePC(result); // setflags is always FALSE here
5341 else
5342 R[d] = result;
5343 if setflags then
5344 APSR.N = result<31>;
5345 APSR.Z = IsZeroBit(result);
5346 APSR.C = carry;
5347 // APSR.V unchanged
5348#endif
5349
5350 bool success = false;
5351 const uint32_t opcode = OpcodeAsUnsigned (&success);
5352 if (!success)
5353 return false;
5354
5355 if (ConditionPassed())
5356 {
5357 uint32_t Rd, Rn, Rm;
5358 ARM_ShifterType shift_t;
5359 uint32_t shift_n; // the shift applied to the value read from Rm
5360 bool setflags;
5361 uint32_t carry;
5362 switch (encoding)
5363 {
5364 case eEncodingT1:
5365 Rd = Rn = Bits32(opcode, 2, 0);
5366 Rm = Bits32(opcode, 5, 3);
5367 setflags = !InITBlock();
5368 shift_t = SRType_LSL;
5369 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005370 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005371 case eEncodingT2:
5372 Rd = Bits32(opcode, 11, 8);
5373 Rn = Bits32(opcode, 19, 16);
5374 Rm = Bits32(opcode, 3, 0);
5375 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005376 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005377 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005378 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005379 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005380 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5381 return false;
5382 break;
5383 case eEncodingA1:
5384 Rd = Bits32(opcode, 15, 12);
5385 Rn = Bits32(opcode, 19, 16);
5386 Rm = Bits32(opcode, 3, 0);
5387 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005388 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005389 // TODO: Emulate SUBS PC, LR and related instructions.
5390 if (Rd == 15 && setflags)
5391 return false;
5392 break;
5393 default:
5394 return false;
5395 }
5396
Johnny Chene97c0d52011-02-18 19:32:20 +00005397 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005398 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005399 if (!success)
5400 return false;
5401
5402 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005403 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005404 if (!success)
5405 return false;
5406
5407 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5408 uint32_t result = val1 & shifted;
5409
5410 EmulateInstruction::Context context;
5411 context.type = EmulateInstruction::eContextImmediate;
5412 context.SetNoArgs ();
5413
5414 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5415 return false;
5416 }
5417 return true;
5418}
5419
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005420// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5421// immediate value, and writes the result to the destination register. It can optionally update the
5422// condition flags based on the result.
5423bool
5424EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
5425{
5426#if 0
5427 // ARM pseudo code...
5428 if ConditionPassed() then
5429 EncodingSpecificOperations();
5430 result = R[n] AND NOT(imm32);
5431 if d == 15 then // Can only occur for ARM encoding
5432 ALUWritePC(result); // setflags is always FALSE here
5433 else
5434 R[d] = result;
5435 if setflags then
5436 APSR.N = result<31>;
5437 APSR.Z = IsZeroBit(result);
5438 APSR.C = carry;
5439 // APSR.V unchanged
5440#endif
5441
5442 bool success = false;
5443 const uint32_t opcode = OpcodeAsUnsigned (&success);
5444 if (!success)
5445 return false;
5446
5447 if (ConditionPassed())
5448 {
5449 uint32_t Rd, Rn;
5450 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5451 bool setflags;
5452 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5453 switch (encoding)
5454 {
5455 case eEncodingT1:
5456 Rd = Bits32(opcode, 11, 8);
5457 Rn = Bits32(opcode, 19, 16);
5458 setflags = BitIsSet(opcode, 20);
5459 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5460 if (BadReg(Rd) || BadReg(Rn))
5461 return false;
5462 break;
5463 case eEncodingA1:
5464 Rd = Bits32(opcode, 15, 12);
5465 Rn = Bits32(opcode, 19, 16);
5466 setflags = BitIsSet(opcode, 20);
5467 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5468 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5469 // TODO: Emulate SUBS PC, LR and related instructions.
5470 if (Rd == 15 && setflags)
5471 return false;
5472 break;
5473 default:
5474 return false;
5475 }
5476
5477 // Read the first operand.
5478 uint32_t val1 = ReadCoreReg(Rn, &success);
5479 if (!success)
5480 return false;
5481
5482 uint32_t result = val1 & ~imm32;
5483
5484 EmulateInstruction::Context context;
5485 context.type = EmulateInstruction::eContextImmediate;
5486 context.SetNoArgs ();
5487
5488 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5489 return false;
5490 }
5491 return true;
5492}
5493
5494// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5495// optionally-shifted register value, and writes the result to the destination register.
5496// It can optionally update the condition flags based on the result.
5497bool
5498EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5499{
5500#if 0
5501 // ARM pseudo code...
5502 if ConditionPassed() then
5503 EncodingSpecificOperations();
5504 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5505 result = R[n] AND NOT(shifted);
5506 if d == 15 then // Can only occur for ARM encoding
5507 ALUWritePC(result); // setflags is always FALSE here
5508 else
5509 R[d] = result;
5510 if setflags then
5511 APSR.N = result<31>;
5512 APSR.Z = IsZeroBit(result);
5513 APSR.C = carry;
5514 // APSR.V unchanged
5515#endif
5516
5517 bool success = false;
5518 const uint32_t opcode = OpcodeAsUnsigned (&success);
5519 if (!success)
5520 return false;
5521
5522 if (ConditionPassed())
5523 {
5524 uint32_t Rd, Rn, Rm;
5525 ARM_ShifterType shift_t;
5526 uint32_t shift_n; // the shift applied to the value read from Rm
5527 bool setflags;
5528 uint32_t carry;
5529 switch (encoding)
5530 {
5531 case eEncodingT1:
5532 Rd = Rn = Bits32(opcode, 2, 0);
5533 Rm = Bits32(opcode, 5, 3);
5534 setflags = !InITBlock();
5535 shift_t = SRType_LSL;
5536 shift_n = 0;
5537 break;
5538 case eEncodingT2:
5539 Rd = Bits32(opcode, 11, 8);
5540 Rn = Bits32(opcode, 19, 16);
5541 Rm = Bits32(opcode, 3, 0);
5542 setflags = BitIsSet(opcode, 20);
5543 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5544 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5545 return false;
5546 break;
5547 case eEncodingA1:
5548 Rd = Bits32(opcode, 15, 12);
5549 Rn = Bits32(opcode, 19, 16);
5550 Rm = Bits32(opcode, 3, 0);
5551 setflags = BitIsSet(opcode, 20);
5552 shift_n = DecodeImmShiftARM(opcode, shift_t);
5553 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5554 // TODO: Emulate SUBS PC, LR and related instructions.
5555 if (Rd == 15 && setflags)
5556 return false;
5557 break;
5558 default:
5559 return false;
5560 }
5561
5562 // Read the first operand.
5563 uint32_t val1 = ReadCoreReg(Rn, &success);
5564 if (!success)
5565 return false;
5566
5567 // Read the second operand.
5568 uint32_t val2 = ReadCoreReg(Rm, &success);
5569 if (!success)
5570 return false;
5571
5572 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5573 uint32_t result = val1 & ~shifted;
5574
5575 EmulateInstruction::Context context;
5576 context.type = EmulateInstruction::eContextImmediate;
5577 context.SetNoArgs ();
5578
5579 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5580 return false;
5581 }
5582 return true;
5583}
5584
Caroline Tice4d729c52011-02-18 00:55:53 +00005585// 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 +00005586// 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 +00005587bool
5588EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5589{
5590#if 0
5591 if ConditionPassed() then
5592 EncodingSpecificOperations();
5593 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5594 address = if index then offset_addr else R[n];
5595 data = MemU[address,4];
5596 if wback then R[n] = offset_addr;
5597 if t == 15 then
5598 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5599 elsif UnalignedSupport() || address<1:0> = ’00’ then
5600 R[t] = data;
5601 else // Can only apply before ARMv7
5602 R[t] = ROR(data, 8*UInt(address<1:0>));
5603#endif
5604
5605 bool success = false;
5606 const uint32_t opcode = OpcodeAsUnsigned (&success);
5607 if (!success)
5608 return false;
5609
5610 if (ConditionPassed ())
5611 {
5612 const uint32_t addr_byte_size = GetAddressByteSize();
5613
5614 uint32_t t;
5615 uint32_t n;
5616 uint32_t imm32;
5617 bool index;
5618 bool add;
5619 bool wback;
5620
5621 switch (encoding)
5622 {
5623 case eEncodingA1:
5624 // if Rn == ’1111’ then SEE LDR (literal);
5625 // if P == ’0’ && W == ’1’ then SEE LDRT;
5626 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5627 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5628 t = Bits32 (opcode, 15, 12);
5629 n = Bits32 (opcode, 19, 16);
5630 imm32 = Bits32 (opcode, 11, 0);
5631
5632 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5633 index = BitIsSet (opcode, 24);
5634 add = BitIsSet (opcode, 23);
5635 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5636
5637 // if wback && n == t then UNPREDICTABLE;
5638 if (wback && (n == t))
5639 return false;
5640
5641 break;
5642
5643 default:
5644 return false;
5645 }
5646
5647 addr_t address;
5648 addr_t offset_addr;
Caroline Tice8d681f52011-03-17 23:50:16 +00005649 addr_t base_address = ReadCoreReg (n, &success);
Caroline Tice4d729c52011-02-18 00:55:53 +00005650 if (!success)
5651 return false;
5652
5653 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5654 if (add)
Caroline Tice8d681f52011-03-17 23:50:16 +00005655 offset_addr = base_address + imm32;
Caroline Tice4d729c52011-02-18 00:55:53 +00005656 else
5657 offset_addr = base_address - imm32;
5658
5659 // address = if index then offset_addr else R[n];
5660 if (index)
5661 address = offset_addr;
5662 else
5663 address = base_address;
5664
5665 // data = MemU[address,4];
5666
5667 Register base_reg;
5668 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5669
5670 EmulateInstruction::Context context;
5671 context.type = eContextRegisterLoad;
5672 context.SetRegisterPlusOffset (base_reg, address - base_address);
5673
5674 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5675 if (!success)
5676 return false;
5677
5678 // if wback then R[n] = offset_addr;
5679 if (wback)
5680 {
5681 context.type = eContextAdjustBaseRegister;
5682 context.SetAddress (offset_addr);
5683 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5684 return false;
5685 }
5686
5687 // if t == 15 then
5688 if (t == 15)
5689 {
5690 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5691 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5692 {
5693 // LoadWritePC (data);
5694 context.type = eContextRegisterLoad;
5695 context.SetRegisterPlusOffset (base_reg, address - base_address);
5696 LoadWritePC (context, data);
5697 }
5698 else
5699 return false;
5700 }
5701 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5702 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5703 {
5704 // R[t] = data;
5705 context.type = eContextRegisterLoad;
5706 context.SetRegisterPlusOffset (base_reg, address - base_address);
5707 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5708 return false;
5709 }
5710 // else // Can only apply before ARMv7
5711 else
5712 {
5713 // R[t] = ROR(data, 8*UInt(address<1:0>));
5714 data = ROR (data, Bits32 (address, 1, 0));
5715 context.type = eContextRegisterLoad;
5716 context.SetImmediate (data);
5717 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5718 return false;
5719 }
5720
5721 }
5722 return true;
5723}
5724
Caroline Ticefe479112011-02-18 18:52:37 +00005725// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5726// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5727bool
5728EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5729{
5730#if 0
5731 if ConditionPassed() then
5732 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5733 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5734 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5735 address = if index then offset_addr else R[n];
5736 data = MemU[address,4];
5737 if wback then R[n] = offset_addr;
5738 if t == 15 then
5739 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5740 elsif UnalignedSupport() || address<1:0> = ’00’ then
5741 R[t] = data;
5742 else // Can only apply before ARMv7
5743 if CurrentInstrSet() == InstrSet_ARM then
5744 R[t] = ROR(data, 8*UInt(address<1:0>));
5745 else
5746 R[t] = bits(32) UNKNOWN;
5747#endif
5748
5749 bool success = false;
5750 const uint32_t opcode = OpcodeAsUnsigned (&success);
5751 if (!success)
5752 return false;
5753
5754 if (ConditionPassed ())
5755 {
5756 const uint32_t addr_byte_size = GetAddressByteSize();
5757
5758 uint32_t t;
5759 uint32_t n;
5760 uint32_t m;
5761 bool index;
5762 bool add;
5763 bool wback;
5764 ARM_ShifterType shift_t;
5765 uint32_t shift_n;
5766
5767 switch (encoding)
5768 {
5769 case eEncodingT1:
5770 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5771 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5772 t = Bits32 (opcode, 2, 0);
5773 n = Bits32 (opcode, 5, 3);
5774 m = Bits32 (opcode, 8, 6);
5775
5776 // index = TRUE; add = TRUE; wback = FALSE;
5777 index = true;
5778 add = true;
5779 wback = false;
5780
5781 // (shift_t, shift_n) = (SRType_LSL, 0);
5782 shift_t = SRType_LSL;
5783 shift_n = 0;
5784
5785 break;
5786
5787 case eEncodingT2:
5788 // if Rn == ’1111’ then SEE LDR (literal);
5789 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5790 t = Bits32 (opcode, 15, 12);
5791 n = Bits32 (opcode, 19, 16);
5792 m = Bits32 (opcode, 3, 0);
5793
5794 // index = TRUE; add = TRUE; wback = FALSE;
5795 index = true;
5796 add = true;
5797 wback = false;
5798
5799 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5800 shift_t = SRType_LSL;
5801 shift_n = Bits32 (opcode, 5, 4);
5802
5803 // if BadReg(m) then UNPREDICTABLE;
5804 if (BadReg (m))
5805 return false;
5806
5807 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5808 if ((t == 15) && InITBlock() && !LastInITBlock())
5809 return false;
5810
5811 break;
5812
5813 case eEncodingA1:
5814 {
5815 // if P == ’0’ && W == ’1’ then SEE LDRT;
5816 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5817 t = Bits32 (opcode, 15, 12);
5818 n = Bits32 (opcode, 19, 16);
5819 m = Bits32 (opcode, 3, 0);
5820
5821 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5822 index = BitIsSet (opcode, 24);
5823 add = BitIsSet (opcode, 23);
5824 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5825
5826 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5827 uint32_t type = Bits32 (opcode, 6, 5);
5828 uint32_t imm5 = Bits32 (opcode, 11, 7);
5829 shift_n = DecodeImmShift (type, imm5, shift_t);
5830
5831 // if m == 15 then UNPREDICTABLE;
5832 if (m == 15)
5833 return false;
5834
5835 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5836 if (wback && ((n == 15) || (n == t)))
5837 return false;
5838 }
5839 break;
5840
5841
5842 default:
5843 return false;
5844 }
5845
5846 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5847 if (!success)
5848 return false;
5849
5850 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5851 if (!success)
5852 return false;
5853
5854 addr_t offset_addr;
5855 addr_t address;
5856
5857 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR".
Johnny Chen90e607b2011-02-23 00:07:09 +00005858 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005859
5860 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5861 if (add)
5862 offset_addr = Rn + offset;
5863 else
5864 offset_addr = Rn - offset;
5865
5866 // address = if index then offset_addr else R[n];
5867 if (index)
5868 address = offset_addr;
5869 else
5870 address = Rn;
5871
5872 // data = MemU[address,4];
5873 Register base_reg;
5874 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5875
5876 EmulateInstruction::Context context;
5877 context.type = eContextRegisterLoad;
5878 context.SetRegisterPlusOffset (base_reg, address - Rn);
5879
5880 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5881 if (!success)
5882 return false;
5883
5884 // if wback then R[n] = offset_addr;
5885 if (wback)
5886 {
5887 context.type = eContextAdjustBaseRegister;
5888 context.SetAddress (offset_addr);
5889 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5890 return false;
5891 }
5892
5893 // if t == 15 then
5894 if (t == 15)
5895 {
5896 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5897 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5898 {
5899 context.type = eContextRegisterLoad;
5900 context.SetRegisterPlusOffset (base_reg, address - Rn);
5901 LoadWritePC (context, data);
5902 }
5903 else
5904 return false;
5905 }
5906 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5907 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5908 {
5909 // R[t] = data;
5910 context.type = eContextRegisterLoad;
5911 context.SetRegisterPlusOffset (base_reg, address - Rn);
5912 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5913 return false;
5914 }
5915 else // Can only apply before ARMv7
5916 {
5917 // if CurrentInstrSet() == InstrSet_ARM then
5918 if (CurrentInstrSet () == eModeARM)
5919 {
5920 // R[t] = ROR(data, 8*UInt(address<1:0>));
5921 data = ROR (data, Bits32 (address, 1, 0));
5922 context.type = eContextRegisterLoad;
5923 context.SetImmediate (data);
5924 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5925 return false;
5926 }
5927 else
5928 {
5929 // R[t] = bits(32) UNKNOWN;
5930 WriteBits32Unknown (t);
5931 }
5932 }
5933 }
5934 return true;
5935}
Caroline Tice21b604b2011-02-18 21:06:04 +00005936
5937// LDRB (immediate, Thumb)
5938bool
5939EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5940{
5941#if 0
5942 if ConditionPassed() then
5943 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5944 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5945 address = if index then offset_addr else R[n];
5946 R[t] = ZeroExtend(MemU[address,1], 32);
5947 if wback then R[n] = offset_addr;
5948#endif
5949
5950 bool success = false;
5951 const uint32_t opcode = OpcodeAsUnsigned (&success);
5952 if (!success)
5953 return false;
5954
5955 if (ConditionPassed ())
5956 {
5957 uint32_t t;
5958 uint32_t n;
5959 uint32_t imm32;
5960 bool index;
5961 bool add;
5962 bool wback;
5963
5964 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5965 switch (encoding)
5966 {
5967 case eEncodingT1:
5968 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5969 t = Bits32 (opcode, 2, 0);
5970 n = Bits32 (opcode, 5, 3);
5971 imm32 = Bits32 (opcode, 10, 6);
5972
5973 // index = TRUE; add = TRUE; wback = FALSE;
5974 index = true;
5975 add = true;
5976 wback= false;
5977
5978 break;
5979
5980 case eEncodingT2:
5981 // if Rt == ’1111’ then SEE PLD;
5982 // if Rn == ’1111’ then SEE LDRB (literal);
5983 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5984 t = Bits32 (opcode, 15, 12);
5985 n = Bits32 (opcode, 19, 16);
5986 imm32 = Bits32 (opcode, 11, 0);
5987
5988 // index = TRUE; add = TRUE; wback = FALSE;
5989 index = true;
5990 add = true;
5991 wback = false;
5992
5993 // if t == 13 then UNPREDICTABLE;
5994 if (t == 13)
5995 return false;
5996
5997 break;
5998
5999 case eEncodingT3:
6000 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
6001 // if Rn == ’1111’ then SEE LDRB (literal);
6002 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
6003 // if P == ’0’ && W == ’0’ then UNDEFINED;
6004 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6005 return false;
6006
6007 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6008 t = Bits32 (opcode, 15, 12);
6009 n = Bits32 (opcode, 19, 16);
6010 imm32 = Bits32 (opcode, 7, 0);
6011
6012 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6013 index = BitIsSet (opcode, 10);
6014 add = BitIsSet (opcode, 9);
6015 wback = BitIsSet (opcode, 8);
6016
6017 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6018 if (BadReg (t) || (wback && (n == t)))
6019 return false;
6020
6021 break;
6022
6023 default:
6024 return false;
6025 }
6026
6027 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6028 if (!success)
6029 return false;
6030
6031 addr_t address;
6032 addr_t offset_addr;
6033
6034 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6035 if (add)
6036 offset_addr = Rn + imm32;
6037 else
6038 offset_addr = Rn - imm32;
6039
6040 // address = if index then offset_addr else R[n];
6041 if (index)
6042 address = offset_addr;
6043 else
6044 address = Rn;
6045
6046 // R[t] = ZeroExtend(MemU[address,1], 32);
6047 Register base_reg;
6048 Register data_reg;
6049 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6050 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
6051
6052 EmulateInstruction::Context context;
6053 context.type = eContextRegisterLoad;
6054 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
6055
6056 uint64_t data = MemURead (context, address, 1, 0, &success);
6057 if (!success)
6058 return false;
6059
6060 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6061 return false;
6062
6063 // if wback then R[n] = offset_addr;
6064 if (wback)
6065 {
6066 context.type = eContextAdjustBaseRegister;
6067 context.SetAddress (offset_addr);
6068 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6069 return false;
6070 }
6071 }
6072 return true;
6073}
Caroline Ticef55261f2011-02-18 22:24:22 +00006074
6075// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6076// zero-extends it to form a 32-bit word and writes it to a register.
6077bool
6078EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
6079{
6080#if 0
6081 if ConditionPassed() then
6082 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6083 base = Align(PC,4);
6084 address = if add then (base + imm32) else (base - imm32);
6085 R[t] = ZeroExtend(MemU[address,1], 32);
6086#endif
6087
6088 bool success = false;
6089 const uint32_t opcode = OpcodeAsUnsigned (&success);
6090 if (!success)
6091 return false;
6092
6093 if (ConditionPassed ())
6094 {
6095 uint32_t t;
6096 uint32_t imm32;
6097 bool add;
6098 switch (encoding)
6099 {
6100 case eEncodingT1:
6101 // if Rt == ’1111’ then SEE PLD;
6102 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6103 t = Bits32 (opcode, 15, 12);
6104 imm32 = Bits32 (opcode, 11, 0);
6105 add = BitIsSet (opcode, 23);
6106
6107 // if t == 13 then UNPREDICTABLE;
6108 if (t == 13)
6109 return false;
6110
6111 break;
6112
6113 case eEncodingA1:
6114 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6115 t = Bits32 (opcode, 15, 12);
6116 imm32 = Bits32 (opcode, 11, 0);
6117 add = BitIsSet (opcode, 23);
6118
6119 // if t == 15 then UNPREDICTABLE;
6120 if (t == 15)
6121 return false;
6122 break;
6123
6124 default:
6125 return false;
6126 }
6127
6128 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006129 uint32_t pc_val = ReadCoreReg (PC_REG, &success);
Caroline Ticef55261f2011-02-18 22:24:22 +00006130 if (!success)
6131 return false;
6132
6133 uint32_t base = AlignPC (pc_val);
6134
6135 addr_t address;
6136 // address = if add then (base + imm32) else (base - imm32);
6137 if (add)
6138 address = base + imm32;
6139 else
6140 address = base - imm32;
6141
6142 // R[t] = ZeroExtend(MemU[address,1], 32);
6143 EmulateInstruction::Context context;
6144 context.type = eContextRelativeBranchImmediate;
6145 context.SetImmediate (address - base);
6146
6147 uint64_t data = MemURead (context, address, 1, 0, &success);
6148 if (!success)
6149 return false;
6150
6151 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6152 return false;
6153 }
6154 return true;
6155}
Caroline Tice30fec122011-02-18 23:52:21 +00006156
6157// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
6158// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6159// optionally be shifted.
6160bool
6161EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
6162{
6163#if 0
6164 if ConditionPassed() then
6165 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6166 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6167 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6168 address = if index then offset_addr else R[n];
6169 R[t] = ZeroExtend(MemU[address,1],32);
6170 if wback then R[n] = offset_addr;
6171#endif
6172
6173 bool success = false;
6174 const uint32_t opcode = OpcodeAsUnsigned (&success);
6175 if (!success)
6176 return false;
6177
6178 if (ConditionPassed ())
6179 {
6180 uint32_t t;
6181 uint32_t n;
6182 uint32_t m;
6183 bool index;
6184 bool add;
6185 bool wback;
6186 ARM_ShifterType shift_t;
6187 uint32_t shift_n;
6188
6189 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6190 switch (encoding)
6191 {
6192 case eEncodingT1:
6193 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6194 t = Bits32 (opcode, 2, 0);
6195 n = Bits32 (opcode, 5, 3);
6196 m = Bits32 (opcode, 8, 6);
6197
6198 // index = TRUE; add = TRUE; wback = FALSE;
6199 index = true;
6200 add = true;
6201 wback = false;
6202
6203 // (shift_t, shift_n) = (SRType_LSL, 0);
6204 shift_t = SRType_LSL;
6205 shift_n = 0;
6206 break;
6207
6208 case eEncodingT2:
6209 // if Rt == ’1111’ then SEE PLD;
6210 // if Rn == ’1111’ then SEE LDRB (literal);
6211 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6212 t = Bits32 (opcode, 15, 12);
6213 n = Bits32 (opcode, 19, 16);
6214 m = Bits32 (opcode, 3, 0);
6215
6216 // index = TRUE; add = TRUE; wback = FALSE;
6217 index = true;
6218 add = true;
6219 wback = false;
6220
6221 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6222 shift_t = SRType_LSL;
6223 shift_n = Bits32 (opcode, 5, 4);
6224
6225 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6226 if ((t == 13) || BadReg (m))
6227 return false;
6228 break;
6229
6230 case eEncodingA1:
6231 {
6232 // if P == ’0’ && W == ’1’ then SEE LDRBT;
6233 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6234 t = Bits32 (opcode, 15, 12);
6235 n = Bits32 (opcode, 19, 16);
6236 m = Bits32 (opcode, 3, 0);
6237
6238 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6239 index = BitIsSet (opcode, 24);
6240 add = BitIsSet (opcode, 23);
6241 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6242
6243 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6244 uint32_t type = Bits32 (opcode, 6, 5);
6245 uint32_t imm5 = Bits32 (opcode, 11, 7);
6246 shift_n = DecodeImmShift (type, imm5, shift_t);
6247
6248 // if t == 15 || m == 15 then UNPREDICTABLE;
6249 if ((t == 15) || (m == 15))
6250 return false;
6251
6252 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6253 if (wback && ((n == 15) || (n == t)))
6254 return false;
6255 }
6256 break;
6257
6258 default:
6259 return false;
6260 }
6261
6262 addr_t offset_addr;
6263 addr_t address;
6264
6265 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6266 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6267 if (!success)
6268 return false;
6269
6270 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6271
6272 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6273 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6274 if (!success)
6275 return false;
6276
6277 if (add)
6278 offset_addr = Rn + offset;
6279 else
6280 offset_addr = Rn - offset;
6281
6282 // address = if index then offset_addr else R[n];
6283 if (index)
6284 address = offset_addr;
6285 else
6286 address = Rn;
6287
6288 // R[t] = ZeroExtend(MemU[address,1],32);
6289 Register base_reg;
6290 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6291
6292 EmulateInstruction::Context context;
6293 context.type = eContextRegisterLoad;
6294 context.SetRegisterPlusOffset (base_reg, address - Rn);
6295
6296 uint64_t data = MemURead (context, address, 1, 0, &success);
6297 if (!success)
6298 return false;
6299
6300 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6301 return false;
6302
6303 // if wback then R[n] = offset_addr;
6304 if (wback)
6305 {
6306 context.type = eContextAdjustBaseRegister;
6307 context.SetAddress (offset_addr);
6308 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6309 return false;
6310 }
6311 }
6312 return true;
6313}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006314
6315// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6316// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6317// post-indexed, or pre-indexed addressing.
6318bool
6319EmulateInstructionARM::EmulateLDRHImmediate (ARMEncoding encoding)
6320{
6321#if 0
6322 if ConditionPassed() then
6323 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6324 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6325 address = if index then offset_addr else R[n];
6326 data = MemU[address,2];
6327 if wback then R[n] = offset_addr;
6328 if UnalignedSupport() || address<0> = ’0’ then
6329 R[t] = ZeroExtend(data, 32);
6330 else // Can only apply before ARMv7
6331 R[t] = bits(32) UNKNOWN;
6332#endif
6333
6334
6335 bool success = false;
6336 const uint32_t opcode = OpcodeAsUnsigned (&success);
6337 if (!success)
6338 return false;
6339
6340 if (ConditionPassed())
6341 {
6342 uint32_t t;
6343 uint32_t n;
6344 uint32_t imm32;
6345 bool index;
6346 bool add;
6347 bool wback;
6348
6349 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6350 switch (encoding)
6351 {
6352 case eEncodingT1:
6353 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
6354 t = Bits32 (opcode, 2, 0);
6355 n = Bits32 (opcode, 5, 3);
6356 imm32 = Bits32 (opcode, 10, 6) << 1;
6357
6358 // index = TRUE; add = TRUE; wback = FALSE;
6359 index = true;
6360 add = true;
6361 wback = false;
6362
6363 break;
6364
6365 case eEncodingT2:
6366 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6367 // if Rn == ’1111’ then SEE LDRH (literal);
6368 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6369 t = Bits32 (opcode, 15, 12);
6370 n = Bits32 (opcode, 19, 16);
6371 imm32 = Bits32 (opcode, 11, 0);
6372
6373 // index = TRUE; add = TRUE; wback = FALSE;
6374 index = true;
6375 add = true;
6376 wback = false;
6377
6378 // if t == 13 then UNPREDICTABLE;
6379 if (t == 13)
6380 return false;
6381 break;
6382
6383 case eEncodingT3:
6384 // if Rn == ’1111’ then SEE LDRH (literal);
6385 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6386 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
6387 // if P == ’0’ && W == ’0’ then UNDEFINED;
6388 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6389 return false;
6390
6391 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6392 t = Bits32 (opcode, 15, 12);
6393 n = Bits32 (opcode, 19, 16);
6394 imm32 = Bits32 (opcode, 7, 0);
6395
6396 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6397 index = BitIsSet (opcode, 10);
6398 add = BitIsSet (opcode, 9);
6399 wback = BitIsSet (opcode, 8);
6400
6401 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6402 if (BadReg (t) || (wback && (n == t)))
6403 return false;
6404 break;
6405
6406 default:
6407 return false;
6408 }
6409
6410 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6411 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6412 if (!success)
6413 return false;
6414
6415 addr_t offset_addr;
6416 addr_t address;
6417
6418 if (add)
6419 offset_addr = Rn + imm32;
6420 else
6421 offset_addr = Rn - imm32;
6422
6423 // address = if index then offset_addr else R[n];
6424 if (index)
6425 address = offset_addr;
6426 else
6427 address = Rn;
6428
6429 // data = MemU[address,2];
6430 Register base_reg;
6431 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6432
6433 EmulateInstruction::Context context;
6434 context.type = eContextRegisterLoad;
6435 context.SetRegisterPlusOffset (base_reg, address - Rn);
6436
6437 uint64_t data = MemURead (context, address, 2, 0, &success);
6438 if (!success)
6439 return false;
6440
6441 // if wback then R[n] = offset_addr;
6442 if (wback)
6443 {
6444 context.type = eContextAdjustBaseRegister;
6445 context.SetAddress (offset_addr);
6446 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6447 return false;
6448 }
6449
6450 // if UnalignedSupport() || address<0> = ’0’ then
6451 if (UnalignedSupport () || BitIsClear (address, 0))
6452 {
6453 // R[t] = ZeroExtend(data, 32);
6454 context.type = eContextRegisterLoad;
6455 context.SetRegisterPlusOffset (base_reg, address - Rn);
6456 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6457 return false;
6458 }
6459 else // Can only apply before ARMv7
6460 {
6461 // R[t] = bits(32) UNKNOWN;
6462 WriteBits32Unknown (t);
6463 }
6464 }
6465 return true;
6466}
Caroline Ticefe479112011-02-18 18:52:37 +00006467
Caroline Tice952b5382011-02-28 23:15:24 +00006468// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6469// zero-extends it to form a 32-bit word, and writes it to a register.
6470bool
6471EmulateInstructionARM::EmulateLDRHLiteral (ARMEncoding encoding)
6472{
6473#if 0
6474 if ConditionPassed() then
6475 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6476 base = Align(PC,4);
6477 address = if add then (base + imm32) else (base - imm32);
6478 data = MemU[address,2];
6479 if UnalignedSupport() || address<0> = ’0’ then
6480 R[t] = ZeroExtend(data, 32);
6481 else // Can only apply before ARMv7
6482 R[t] = bits(32) UNKNOWN;
6483#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006484
Caroline Tice952b5382011-02-28 23:15:24 +00006485 bool success = false;
6486 const uint32_t opcode = OpcodeAsUnsigned (&success);
6487 if (!success)
6488 return false;
6489
6490 if (ConditionPassed())
6491 {
6492 uint32_t t;
6493 uint32_t imm32;
6494 bool add;
6495
6496 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6497 switch (encoding)
6498 {
6499 case eEncodingT1:
6500 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6501 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6502 t = Bits32 (opcode, 15, 12);
6503 imm32 = Bits32 (opcode, 11, 0);
6504 add = BitIsSet (opcode, 23);
6505
6506 // if t == 13 then UNPREDICTABLE;
6507 if (t == 13)
6508 return false;
6509
6510 break;
6511
6512 case eEncodingA1:
6513 {
6514 uint32_t imm4H = Bits32 (opcode, 11, 8);
6515 uint32_t imm4L = Bits32 (opcode, 3, 0);
6516
6517 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6518 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006519 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006520 add = BitIsSet (opcode, 23);
6521
6522 // if t == 15 then UNPREDICTABLE;
6523 if (t == 15)
6524 return false;
6525 break;
6526 }
6527
6528 default:
6529 return false;
6530 }
6531
6532 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006533 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice952b5382011-02-28 23:15:24 +00006534 if (!success)
6535 return false;
6536
6537 addr_t base = AlignPC (pc_value);
6538 addr_t address;
6539
6540 // address = if add then (base + imm32) else (base - imm32);
6541 if (add)
6542 address = base + imm32;
6543 else
6544 address = base - imm32;
6545
6546 // data = MemU[address,2];
6547 Register base_reg;
6548 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6549
6550 EmulateInstruction::Context context;
6551 context.type = eContextRegisterLoad;
6552 context.SetRegisterPlusOffset (base_reg, address - base);
6553
6554 uint64_t data = MemURead (context, address, 2, 0, &success);
6555 if (!success)
6556 return false;
6557
6558
6559 // if UnalignedSupport() || address<0> = ’0’ then
6560 if (UnalignedSupport () || BitIsClear (address, 0))
6561 {
6562 // R[t] = ZeroExtend(data, 32);
6563 context.type = eContextRegisterLoad;
6564 context.SetRegisterPlusOffset (base_reg, address - base);
6565 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6566 return false;
6567
6568 }
6569 else // Can only apply before ARMv7
6570 {
6571 // R[t] = bits(32) UNKNOWN;
6572 WriteBits32Unknown (t);
6573 }
6574 }
6575 return true;
6576}
6577
Caroline Tice0e6bc952011-03-01 18:00:42 +00006578// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6579// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6580// be shifted left by 0, 1, 2, or 3 bits.
6581bool
6582EmulateInstructionARM::EmulateLDRHRegister (ARMEncoding encoding)
6583{
6584#if 0
6585 if ConditionPassed() then
6586 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6587 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6588 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6589 address = if index then offset_addr else R[n];
6590 data = MemU[address,2];
6591 if wback then R[n] = offset_addr;
6592 if UnalignedSupport() || address<0> = ’0’ then
6593 R[t] = ZeroExtend(data, 32);
6594 else // Can only apply before ARMv7
6595 R[t] = bits(32) UNKNOWN;
6596#endif
6597
6598 bool success = false;
6599 const uint32_t opcode = OpcodeAsUnsigned (&success);
6600 if (!success)
6601 return false;
6602
6603 if (ConditionPassed())
6604 {
6605 uint32_t t;
6606 uint32_t n;
6607 uint32_t m;
6608 bool index;
6609 bool add;
6610 bool wback;
6611 ARM_ShifterType shift_t;
6612 uint32_t shift_n;
6613
6614 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6615 switch (encoding)
6616 {
6617 case eEncodingT1:
6618 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6619 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6620 t = Bits32 (opcode, 2, 0);
6621 n = Bits32 (opcode, 5, 3);
6622 m = Bits32 (opcode, 8, 6);
6623
6624 // index = TRUE; add = TRUE; wback = FALSE;
6625 index = true;
6626 add = true;
6627 wback = false;
6628
6629 // (shift_t, shift_n) = (SRType_LSL, 0);
6630 shift_t = SRType_LSL;
6631 shift_n = 0;
6632
6633 break;
6634
6635 case eEncodingT2:
6636 // if Rn == ’1111’ then SEE LDRH (literal);
6637 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6638 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6639 t = Bits32 (opcode, 15, 12);
6640 n = Bits32 (opcode, 19, 16);
6641 m = Bits32 (opcode, 3, 0);
6642
6643 // index = TRUE; add = TRUE; wback = FALSE;
6644 index = true;
6645 add = true;
6646 wback = false;
6647
6648 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6649 shift_t = SRType_LSL;
6650 shift_n = Bits32 (opcode, 5, 4);
6651
6652 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6653 if ((t == 13) || BadReg (m))
6654 return false;
6655 break;
6656
6657 case eEncodingA1:
6658 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6659 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6660 t = Bits32 (opcode, 15, 12);
6661 n = Bits32 (opcode, 19, 16);
6662 m = Bits32 (opcode, 3, 0);
6663
6664 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6665 index = BitIsSet (opcode, 24);
6666 add = BitIsSet (opcode, 23);
6667 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6668
6669 // (shift_t, shift_n) = (SRType_LSL, 0);
6670 shift_t = SRType_LSL;
6671 shift_n = 0;
6672
6673 // if t == 15 || m == 15 then UNPREDICTABLE;
6674 if ((t == 15) || (m == 15))
6675 return false;
6676
6677 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6678 if (wback && ((n == 15) || (n == t)))
6679 return false;
6680
6681 break;
6682
6683 default:
6684 return false;
6685 }
6686
6687 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6688
6689 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6690 if (!success)
6691 return false;
6692
6693 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6694
6695 addr_t offset_addr;
6696 addr_t address;
6697
6698 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6699 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6700 if (!success)
6701 return false;
6702
6703 if (add)
6704 offset_addr = Rn + offset;
6705 else
6706 offset_addr = Rn - offset;
6707
6708 // address = if index then offset_addr else R[n];
6709 if (index)
6710 address = offset_addr;
6711 else
6712 address = Rn;
6713
6714 // data = MemU[address,2];
6715 Register base_reg;
6716 Register offset_reg;
6717 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6718 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6719
6720 EmulateInstruction::Context context;
6721 context.type = eContextRegisterLoad;
6722 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6723 uint64_t data = MemURead (context, address, 2, 0, &success);
6724 if (!success)
6725 return false;
6726
6727 // if wback then R[n] = offset_addr;
6728 if (wback)
6729 {
6730 context.type = eContextAdjustBaseRegister;
6731 context.SetAddress (offset_addr);
6732 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6733 return false;
6734 }
6735
6736 // if UnalignedSupport() || address<0> = ’0’ then
6737 if (UnalignedSupport() || BitIsClear (address, 0))
6738 {
6739 // R[t] = ZeroExtend(data, 32);
6740 context.type = eContextRegisterLoad;
6741 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6742 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6743 return false;
6744 }
6745 else // Can only apply before ARMv7
6746 {
6747 // R[t] = bits(32) UNKNOWN;
6748 WriteBits32Unknown (t);
6749 }
6750 }
6751 return true;
6752}
6753
Caroline Ticea5e28af2011-03-01 21:53:03 +00006754// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6755// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6756// or pre-indexed addressing.
6757bool
6758EmulateInstructionARM::EmulateLDRSBImmediate (ARMEncoding encoding)
6759{
6760#if 0
6761 if ConditionPassed() then
6762 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6763 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6764 address = if index then offset_addr else R[n];
6765 R[t] = SignExtend(MemU[address,1], 32);
6766 if wback then R[n] = offset_addr;
6767#endif
6768
6769 bool success = false;
6770 const uint32_t opcode = OpcodeAsUnsigned (&success);
6771 if (!success)
6772 return false;
6773
6774 if (ConditionPassed ())
6775 {
6776 uint32_t t;
6777 uint32_t n;
6778 uint32_t imm32;
6779 bool index;
6780 bool add;
6781 bool wback;
6782
6783 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6784 switch (encoding)
6785 {
6786 case eEncodingT1:
6787 // if Rt == ’1111’ then SEE PLI;
6788 // if Rn == ’1111’ then SEE LDRSB (literal);
6789 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6790 t = Bits32 (opcode, 15, 12);
6791 n = Bits32 (opcode, 19, 16);
6792 imm32 = Bits32 (opcode, 11, 0);
6793
6794 // index = TRUE; add = TRUE; wback = FALSE;
6795 index = true;
6796 add = true;
6797 wback = false;
6798
6799 // if t == 13 then UNPREDICTABLE;
6800 if (t == 13)
6801 return false;
6802
6803 break;
6804
6805 case eEncodingT2:
6806 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6807 // if Rn == ’1111’ then SEE LDRSB (literal);
6808 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6809 // if P == ’0’ && W == ’0’ then UNDEFINED;
6810 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6811 return false;
6812
6813 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6814 t = Bits32 (opcode, 15, 12);
6815 n = Bits32 (opcode, 19, 16);
6816 imm32 = Bits32 (opcode, 7, 0);
6817
6818 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6819 index = BitIsSet (opcode, 10);
6820 add = BitIsSet (opcode, 9);
6821 wback = BitIsSet (opcode, 8);
6822
6823 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6824 if (BadReg (t) || (wback && (n == t)))
6825 return false;
6826
6827 break;
6828
6829 case eEncodingA1:
6830 {
6831 // if Rn == ’1111’ then SEE LDRSB (literal);
6832 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6833 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6834 t = Bits32 (opcode, 15, 12);
6835 n = Bits32 (opcode, 19, 16);
6836
6837 uint32_t imm4H = Bits32 (opcode, 11, 8);
6838 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006839 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006840
6841 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6842 index = BitIsSet (opcode, 24);
6843 add = BitIsSet (opcode, 23);
6844 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6845
6846 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6847 if ((t == 15) || (wback && (n == t)))
6848 return false;
6849
6850 break;
6851 }
6852
6853 default:
6854 return false;
6855 }
6856
6857 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6858 if (!success)
6859 return false;
6860
6861 addr_t offset_addr;
6862 addr_t address;
6863
6864 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6865 if (add)
6866 offset_addr = Rn + imm32;
6867 else
6868 offset_addr = Rn - imm32;
6869
6870 // address = if index then offset_addr else R[n];
6871 if (index)
6872 address = offset_addr;
6873 else
6874 address = Rn;
6875
6876 // R[t] = SignExtend(MemU[address,1], 32);
6877 Register base_reg;
6878 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6879
6880 EmulateInstruction::Context context;
6881 context.type = eContextRegisterLoad;
6882 context.SetRegisterPlusOffset (base_reg, address - Rn);
6883
6884 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6885 if (!success)
6886 return false;
6887
6888 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6889 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6890 return false;
6891
6892 // if wback then R[n] = offset_addr;
6893 if (wback)
6894 {
6895 context.type = eContextAdjustBaseRegister;
6896 context.SetAddress (offset_addr);
6897 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6898 return false;
6899 }
6900 }
6901
6902 return true;
6903}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006904
Caroline Tice5f593912011-03-01 22:25:17 +00006905// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6906// sign-extends it to form a 32-bit word, and writes tit to a register.
6907bool
6908EmulateInstructionARM::EmulateLDRSBLiteral (ARMEncoding encoding)
6909{
6910#if 0
6911 if ConditionPassed() then
6912 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6913 base = Align(PC,4);
6914 address = if add then (base + imm32) else (base - imm32);
6915 R[t] = SignExtend(MemU[address,1], 32);
6916#endif
6917
6918 bool success = false;
6919 const uint32_t opcode = OpcodeAsUnsigned (&success);
6920 if (!success)
6921 return false;
6922
6923 if (ConditionPassed ())
6924 {
6925 uint32_t t;
6926 uint32_t imm32;
6927 bool add;
6928
6929 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6930 switch (encoding)
6931 {
6932 case eEncodingT1:
6933 // if Rt == ’1111’ then SEE PLI;
6934 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6935 t = Bits32 (opcode, 15, 12);
6936 imm32 = Bits32 (opcode, 11, 0);
6937 add = BitIsSet (opcode, 23);
6938
6939 // if t == 13 then UNPREDICTABLE;
6940 if (t == 13)
6941 return false;
6942
6943 break;
6944
6945 case eEncodingA1:
6946 {
6947 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6948 t = Bits32 (opcode, 15, 12);
6949 uint32_t imm4H = Bits32 (opcode, 11, 8);
6950 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006951 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006952 add = BitIsSet (opcode, 23);
6953
6954 // if t == 15 then UNPREDICTABLE;
6955 if (t == 15)
6956 return false;
6957
6958 break;
6959 }
6960
6961 default:
6962 return false;
6963 }
6964
6965 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00006966 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Tice5f593912011-03-01 22:25:17 +00006967 if (!success)
6968 return false;
6969 uint64_t base = AlignPC (pc_value);
6970
6971 // address = if add then (base + imm32) else (base - imm32);
6972 addr_t address;
6973 if (add)
6974 address = base + imm32;
6975 else
6976 address = base - imm32;
6977
6978 // R[t] = SignExtend(MemU[address,1], 32);
6979 Register base_reg;
6980 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6981
6982 EmulateInstruction::Context context;
6983 context.type = eContextRegisterLoad;
6984 context.SetRegisterPlusOffset (base_reg, address - base);
6985
6986 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6987 if (!success)
6988 return false;
6989
6990 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6991 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6992 return false;
6993 }
6994 return true;
6995}
6996
Caroline Tice672f3112011-03-01 23:55:59 +00006997// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6998// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6999// shifted left by 0, 1, 2, or 3 bits.
7000bool
7001EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
7002{
7003#if 0
7004 if ConditionPassed() then
7005 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7006 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7007 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7008 address = if index then offset_addr else R[n];
7009 R[t] = SignExtend(MemU[address,1], 32);
7010 if wback then R[n] = offset_addr;
7011#endif
7012
7013 bool success = false;
7014 const uint32_t opcode = OpcodeAsUnsigned (&success);
7015 if (!success)
7016 return false;
7017
7018 if (ConditionPassed ())
7019 {
7020 uint32_t t;
7021 uint32_t n;
7022 uint32_t m;
7023 bool index;
7024 bool add;
7025 bool wback;
7026 ARM_ShifterType shift_t;
7027 uint32_t shift_n;
7028
7029 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7030 switch (encoding)
7031 {
7032 case eEncodingT1:
7033 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7034 t = Bits32 (opcode, 2, 0);
7035 n = Bits32 (opcode, 5, 3);
7036 m = Bits32 (opcode, 8, 6);
7037
7038 // index = TRUE; add = TRUE; wback = FALSE;
7039 index = true;
7040 add = true;
7041 wback = false;
7042
7043 // (shift_t, shift_n) = (SRType_LSL, 0);
7044 shift_t = SRType_LSL;
7045 shift_n = 0;
7046
7047 break;
7048
7049 case eEncodingT2:
7050 // if Rt == ’1111’ then SEE PLI;
7051 // if Rn == ’1111’ then SEE LDRSB (literal);
7052 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7053 t = Bits32 (opcode, 15, 12);
7054 n = Bits32 (opcode, 19, 16);
7055 m = Bits32 (opcode, 3, 0);
7056
7057 // index = TRUE; add = TRUE; wback = FALSE;
7058 index = true;
7059 add = true;
7060 wback = false;
7061
7062 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7063 shift_t = SRType_LSL;
7064 shift_n = Bits32 (opcode, 5, 4);
7065
7066 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7067 if ((t == 13) || BadReg (m))
7068 return false;
7069 break;
7070
7071 case eEncodingA1:
7072 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
7073 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7074 t = Bits32 (opcode, 15, 12);
7075 n = Bits32 (opcode, 19, 16);
7076 m = Bits32 (opcode, 3, 0);
7077
7078 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7079 index = BitIsSet (opcode, 24);
7080 add = BitIsSet (opcode, 23);
7081 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7082
7083 // (shift_t, shift_n) = (SRType_LSL, 0);
7084 shift_t = SRType_LSL;
7085 shift_n = 0;
7086
7087 // if t == 15 || m == 15 then UNPREDICTABLE;
7088 if ((t == 15) || (m == 15))
7089 return false;
7090
7091 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7092 if (wback && ((n == 15) || (n == t)))
7093 return false;
7094 break;
7095
7096 default:
7097 return false;
7098 }
7099
7100 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7101 if (!success)
7102 return false;
7103
7104 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7105 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7106
7107 addr_t offset_addr;
7108 addr_t address;
7109
7110 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7111 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7112 if (!success)
7113 return false;
7114
7115 if (add)
7116 offset_addr = Rn + offset;
7117 else
7118 offset_addr = Rn - offset;
7119
7120 // address = if index then offset_addr else R[n];
7121 if (index)
7122 address = offset_addr;
7123 else
7124 address = Rn;
7125
7126 // R[t] = SignExtend(MemU[address,1], 32);
7127 Register base_reg;
7128 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7129 Register offset_reg;
7130 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7131
7132 EmulateInstruction::Context context;
7133 context.type = eContextRegisterLoad;
7134 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7135
7136 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7137 if (!success)
7138 return false;
7139
7140 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7141 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7142 return false;
7143
7144 // if wback then R[n] = offset_addr;
7145 if (wback)
7146 {
7147 context.type = eContextAdjustBaseRegister;
7148 context.SetAddress (offset_addr);
7149 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7150 return false;
7151 }
7152 }
7153 return true;
7154}
7155
Caroline Tice78fb5632011-03-02 00:39:42 +00007156// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7157// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7158// pre-indexed addressing.
7159bool
7160EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
7161{
7162#if 0
7163 if ConditionPassed() then
7164 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7165 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7166 address = if index then offset_addr else R[n];
7167 data = MemU[address,2];
7168 if wback then R[n] = offset_addr;
7169 if UnalignedSupport() || address<0> = ’0’ then
7170 R[t] = SignExtend(data, 32);
7171 else // Can only apply before ARMv7
7172 R[t] = bits(32) UNKNOWN;
7173#endif
7174
7175 bool success = false;
7176 const uint32_t opcode = OpcodeAsUnsigned (&success);
7177 if (!success)
7178 return false;
7179
7180 if (ConditionPassed())
7181 {
7182 uint32_t t;
7183 uint32_t n;
7184 uint32_t imm32;
7185 bool index;
7186 bool add;
7187 bool wback;
7188
7189 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7190 switch (encoding)
7191 {
7192 case eEncodingT1:
7193 // if Rn == ’1111’ then SEE LDRSH (literal);
7194 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7195 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7196 t = Bits32 (opcode, 15, 12);
7197 n = Bits32 (opcode, 19, 16);
7198 imm32 = Bits32 (opcode, 11, 0);
7199
7200 // index = TRUE; add = TRUE; wback = FALSE;
7201 index = true;
7202 add = true;
7203 wback = false;
7204
7205 // if t == 13 then UNPREDICTABLE;
7206 if (t == 13)
7207 return false;
7208
7209 break;
7210
7211 case eEncodingT2:
7212 // if Rn == ’1111’ then SEE LDRSH (literal);
7213 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
7214 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
7215 // if P == ’0’ && W == ’0’ then UNDEFINED;
7216 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7217 return false;
7218
7219 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7220 t = Bits32 (opcode, 15, 12);
7221 n = Bits32 (opcode, 19, 16);
7222 imm32 = Bits32 (opcode, 7, 0);
7223
7224 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
7225 index = BitIsSet (opcode, 10);
7226 add = BitIsSet (opcode, 9);
7227 wback = BitIsSet (opcode, 8);
7228
7229 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7230 if (BadReg (t) || (wback && (n == t)))
7231 return false;
7232
7233 break;
7234
7235 case eEncodingA1:
7236 {
7237 // if Rn == ’1111’ then SEE LDRSH (literal);
7238 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7239 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7240 t = Bits32 (opcode, 15, 12);
7241 n = Bits32 (opcode, 19, 16);
7242 uint32_t imm4H = Bits32 (opcode, 11,8);
7243 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007244 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007245
7246 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7247 index = BitIsSet (opcode, 24);
7248 add = BitIsSet (opcode, 23);
7249 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7250
7251 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7252 if ((t == 15) || (wback && (n == t)))
7253 return false;
7254
7255 break;
7256 }
7257
7258 default:
7259 return false;
7260 }
7261
7262 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7263 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7264 if (!success)
7265 return false;
7266
7267 addr_t offset_addr;
7268 if (add)
7269 offset_addr = Rn + imm32;
7270 else
7271 offset_addr = Rn - imm32;
7272
7273 // address = if index then offset_addr else R[n];
7274 addr_t address;
7275 if (index)
7276 address = offset_addr;
7277 else
7278 address = Rn;
7279
7280 // data = MemU[address,2];
7281 Register base_reg;
7282 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7283
7284 EmulateInstruction::Context context;
7285 context.type = eContextRegisterLoad;
7286 context.SetRegisterPlusOffset (base_reg, address - Rn);
7287
7288 uint64_t data = MemURead (context, address, 2, 0, &success);
7289 if (!success)
7290 return false;
7291
7292 // if wback then R[n] = offset_addr;
7293 if (wback)
7294 {
7295 context.type = eContextAdjustBaseRegister;
7296 context.SetAddress (offset_addr);
7297 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7298 return false;
7299 }
7300
7301 // if UnalignedSupport() || address<0> = ’0’ then
7302 if (UnalignedSupport() || BitIsClear (address, 0))
7303 {
7304 // R[t] = SignExtend(data, 32);
7305 int64_t signed_data = llvm::SignExtend64<16>(data);
7306 context.type = eContextRegisterLoad;
7307 context.SetRegisterPlusOffset (base_reg, address - Rn);
7308 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7309 return false;
7310 }
7311 else // Can only apply before ARMv7
7312 {
7313 // R[t] = bits(32) UNKNOWN;
7314 WriteBits32Unknown (t);
7315 }
7316 }
7317 return true;
7318}
7319
Caroline Ticed2fac092011-03-02 19:45:34 +00007320// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7321// sign-extends it to from a 32-bit word, and writes it to a register.
7322bool
7323EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
7324{
7325#if 0
7326 if ConditionPassed() then
7327 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7328 base = Align(PC,4);
7329 address = if add then (base + imm32) else (base - imm32);
7330 data = MemU[address,2];
7331 if UnalignedSupport() || address<0> = ’0’ then
7332 R[t] = SignExtend(data, 32);
7333 else // Can only apply before ARMv7
7334 R[t] = bits(32) UNKNOWN;
7335#endif
7336
7337 bool success = false;
7338 const uint32_t opcode = OpcodeAsUnsigned (&success);
7339 if (!success)
7340 return false;
7341
7342 if (ConditionPassed())
7343 {
7344 uint32_t t;
7345 uint32_t imm32;
7346 bool add;
7347
7348 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7349 switch (encoding)
7350 {
7351 case eEncodingT1:
7352 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7353 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7354 t = Bits32 (opcode, 15, 12);
7355 imm32 = Bits32 (opcode, 11, 0);
7356 add = BitIsSet (opcode, 23);
7357
7358 // if t == 13 then UNPREDICTABLE;
7359 if (t == 13)
7360 return false;
7361
7362 break;
7363
7364 case eEncodingA1:
7365 {
7366 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7367 t = Bits32 (opcode, 15, 12);
7368 uint32_t imm4H = Bits32 (opcode, 11, 8);
7369 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007370 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007371 add = BitIsSet (opcode, 23);
7372
7373 // if t == 15 then UNPREDICTABLE;
7374 if (t == 15)
7375 return false;
7376
7377 break;
7378 }
7379 default:
7380 return false;
7381 }
7382
7383 // base = Align(PC,4);
Caroline Tice8d681f52011-03-17 23:50:16 +00007384 uint64_t pc_value = ReadCoreReg (PC_REG, &success);
Caroline Ticed2fac092011-03-02 19:45:34 +00007385 if (!success)
7386 return false;
7387
7388 uint64_t base = AlignPC (pc_value);
7389
7390 addr_t address;
7391 // address = if add then (base + imm32) else (base - imm32);
7392 if (add)
7393 address = base + imm32;
7394 else
7395 address = base - imm32;
7396
7397 // data = MemU[address,2];
7398 Register base_reg;
7399 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7400
7401 EmulateInstruction::Context context;
7402 context.type = eContextRegisterLoad;
7403 context.SetRegisterPlusOffset (base_reg, imm32);
7404
7405 uint64_t data = MemURead (context, address, 2, 0, &success);
7406 if (!success)
7407 return false;
7408
7409 // if UnalignedSupport() || address<0> = ’0’ then
7410 if (UnalignedSupport() || BitIsClear (address, 0))
7411 {
7412 // R[t] = SignExtend(data, 32);
7413 int64_t signed_data = llvm::SignExtend64<16>(data);
7414 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7415 return false;
7416 }
7417 else // Can only apply before ARMv7
7418 {
7419 // R[t] = bits(32) UNKNOWN;
7420 WriteBits32Unknown (t);
7421 }
7422 }
7423 return true;
7424}
7425
Caroline Tice291a3e92011-03-02 21:13:44 +00007426// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7427// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7428// shifted left by 0, 1, 2, or 3 bits.
7429bool
7430EmulateInstructionARM::EmulateLDRSHRegister (ARMEncoding encoding)
7431{
7432#if 0
7433 if ConditionPassed() then
7434 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7435 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7436 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7437 address = if index then offset_addr else R[n];
7438 data = MemU[address,2];
7439 if wback then R[n] = offset_addr;
7440 if UnalignedSupport() || address<0> = ’0’ then
7441 R[t] = SignExtend(data, 32);
7442 else // Can only apply before ARMv7
7443 R[t] = bits(32) UNKNOWN;
7444#endif
7445
7446 bool success = false;
7447 const uint32_t opcode = OpcodeAsUnsigned (&success);
7448 if (!success)
7449 return false;
7450
7451 if (ConditionPassed())
7452 {
7453 uint32_t t;
7454 uint32_t n;
7455 uint32_t m;
7456 bool index;
7457 bool add;
7458 bool wback;
7459 ARM_ShifterType shift_t;
7460 uint32_t shift_n;
7461
7462 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7463 switch (encoding)
7464 {
7465 case eEncodingT1:
7466 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7467 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7468 t = Bits32 (opcode, 2, 0);
7469 n = Bits32 (opcode, 5, 3);
7470 m = Bits32 (opcode, 8, 6);
7471
7472 // index = TRUE; add = TRUE; wback = FALSE;
7473 index = true;
7474 add = true;
7475 wback = false;
7476
7477 // (shift_t, shift_n) = (SRType_LSL, 0);
7478 shift_t = SRType_LSL;
7479 shift_n = 0;
7480
7481 break;
7482
7483 case eEncodingT2:
7484 // if Rn == ’1111’ then SEE LDRSH (literal);
7485 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7486 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7487 t = Bits32 (opcode, 15, 12);
7488 n = Bits32 (opcode, 19, 16);
7489 m = Bits32 (opcode, 3, 0);
7490
7491 // index = TRUE; add = TRUE; wback = FALSE;
7492 index = true;
7493 add = true;
7494 wback = false;
7495
7496 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7497 shift_t = SRType_LSL;
7498 shift_n = Bits32 (opcode, 5, 4);
7499
7500 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7501 if ((t == 13) || BadReg (m))
7502 return false;
7503
7504 break;
7505
7506 case eEncodingA1:
7507 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7508 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7509 t = Bits32 (opcode, 15, 12);
7510 n = Bits32 (opcode, 19, 16);
7511 m = Bits32 (opcode, 3, 0);
7512
7513 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7514 index = BitIsSet (opcode, 24);
7515 add = BitIsSet (opcode, 23);
7516 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7517
7518 // (shift_t, shift_n) = (SRType_LSL, 0);
7519 shift_t = SRType_LSL;
7520 shift_n = 0;
7521
7522 // if t == 15 || m == 15 then UNPREDICTABLE;
7523 if ((t == 15) || (m == 15))
7524 return false;
7525
7526 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7527 if (wback && ((n == 15) || (n == t)))
7528 return false;
7529
7530 break;
7531
7532 default:
7533 break;
7534 }
7535
7536 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7537 if (!success)
7538 return false;
7539
7540 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7541 if (!success)
7542 return false;
7543
7544 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7545 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7546
7547 addr_t offset_addr;
7548 addr_t address;
7549
7550 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7551 if (add)
7552 offset_addr = Rn + offset;
7553 else
7554 offset_addr = Rn - offset;
7555
7556 // address = if index then offset_addr else R[n];
7557 if (index)
7558 address = offset_addr;
7559 else
7560 address = Rn;
7561
7562 // data = MemU[address,2];
7563 Register base_reg;
7564 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7565
7566 Register offset_reg;
7567 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7568
7569 EmulateInstruction::Context context;
7570 context.type = eContextRegisterLoad;
7571 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7572
7573 uint64_t data = MemURead (context, address, 2, 0, &success);
7574 if (!success)
7575 return false;
7576
7577 // if wback then R[n] = offset_addr;
7578 if (wback)
7579 {
7580 context.type = eContextAdjustBaseRegister;
7581 context.SetAddress (offset_addr);
7582 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7583 return false;
7584 }
7585
7586 // if UnalignedSupport() || address<0> = ’0’ then
7587 if (UnalignedSupport() || BitIsClear (address, 0))
7588 {
7589 // R[t] = SignExtend(data, 32);
7590 context.type = eContextRegisterLoad;
7591 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7592
7593 int64_t signed_data = llvm::SignExtend64<16>(data);
7594 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7595 return false;
7596 }
7597 else // Can only apply before ARMv7
7598 {
7599 // R[t] = bits(32) UNKNOWN;
7600 WriteBits32Unknown (t);
7601 }
7602 }
7603 return true;
7604}
Caroline Tice6bf65162011-03-03 17:42:58 +00007605
7606// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7607// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7608bool
7609EmulateInstructionARM::EmulateSXTB (ARMEncoding encoding)
7610{
7611#if 0
7612 if ConditionPassed() then
7613 EncodingSpecificOperations();
7614 rotated = ROR(R[m], rotation);
7615 R[d] = SignExtend(rotated<7:0>, 32);
7616#endif
7617
7618 bool success = false;
7619 const uint32_t opcode = OpcodeAsUnsigned (&success);
7620 if (!success)
7621 return false;
7622
7623 if (ConditionPassed())
7624 {
7625 uint32_t d;
7626 uint32_t m;
7627 uint32_t rotation;
7628
7629 // EncodingSpecificOperations();
7630 switch (encoding)
7631 {
7632 case eEncodingT1:
7633 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7634 d = Bits32 (opcode, 2, 0);
7635 m = Bits32 (opcode, 5, 3);
7636 rotation = 0;
7637
7638 break;
7639
7640 case eEncodingT2:
7641 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7642 d = Bits32 (opcode, 11, 8);
7643 m = Bits32 (opcode, 3, 0);
7644 rotation = Bits32 (opcode, 5, 4) << 3;
7645
7646 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7647 if (BadReg (d) || BadReg (m))
7648 return false;
7649
7650 break;
7651
7652 case eEncodingA1:
7653 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7654 d = Bits32 (opcode, 15, 12);
7655 m = Bits32 (opcode, 3, 0);
7656 rotation = Bits32 (opcode, 11, 10) << 3;
7657
7658 // if d == 15 || m == 15 then UNPREDICTABLE;
7659 if ((d == 15) || (m == 15))
7660 return false;
7661
7662 break;
7663
7664 default:
7665 return false;
7666 }
7667
Caroline Tice868198b2011-03-03 18:04:49 +00007668 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7669 if (!success)
7670 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007671
7672 // rotated = ROR(R[m], rotation);
7673 uint64_t rotated = ROR (Rm, rotation);
7674
7675 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007676 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007677
7678 Register source_reg;
7679 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7680
7681 EmulateInstruction::Context context;
7682 context.type = eContextRegisterLoad;
7683 context.SetRegister (source_reg);
7684
Caroline Tice8ce96d92011-03-03 18:27:17 +00007685 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007686 return false;
7687 }
7688 return true;
7689}
Caroline Tice291a3e92011-03-02 21:13:44 +00007690
Caroline Tice868198b2011-03-03 18:04:49 +00007691// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7692// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7693bool
7694EmulateInstructionARM::EmulateSXTH (ARMEncoding encoding)
7695{
7696#if 0
7697 if ConditionPassed() then
7698 EncodingSpecificOperations();
7699 rotated = ROR(R[m], rotation);
7700 R[d] = SignExtend(rotated<15:0>, 32);
7701#endif
7702
7703 bool success = false;
7704 const uint32_t opcode = OpcodeAsUnsigned (&success);
7705 if (!success)
7706 return false;
7707
7708 if (ConditionPassed())
7709 {
7710 uint32_t d;
7711 uint32_t m;
7712 uint32_t rotation;
7713
7714 // EncodingSpecificOperations();
7715 switch (encoding)
7716 {
7717 case eEncodingT1:
7718 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7719 d = Bits32 (opcode, 2, 0);
7720 m = Bits32 (opcode, 5, 3);
7721 rotation = 0;
7722
7723 break;
7724
7725 case eEncodingT2:
7726 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7727 d = Bits32 (opcode, 11, 8);
7728 m = Bits32 (opcode, 3, 0);
7729 rotation = Bits32 (opcode, 5, 4) << 3;
7730
7731 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7732 if (BadReg (d) || BadReg (m))
7733 return false;
7734
7735 break;
7736
7737 case eEncodingA1:
7738 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7739 d = Bits32 (opcode, 15, 12);
7740 m = Bits32 (opcode, 3, 0);
7741 rotation = Bits32 (opcode, 11, 10) << 3;
7742
7743 // if d == 15 || m == 15 then UNPREDICTABLE;
7744 if ((d == 15) || (m == 15))
7745 return false;
7746
7747 break;
7748
7749 default:
7750 return false;
7751 }
7752
7753 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7754 if (!success)
7755 return false;
7756
7757 // rotated = ROR(R[m], rotation);
7758 uint64_t rotated = ROR (Rm, rotation);
7759
7760 // R[d] = SignExtend(rotated<15:0>, 32);
7761 Register source_reg;
7762 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7763
7764 EmulateInstruction::Context context;
7765 context.type = eContextRegisterLoad;
7766 context.SetRegister (source_reg);
7767
Caroline Tice8ce96d92011-03-03 18:27:17 +00007768 int64_t data = llvm::SignExtend64<16> (rotated);
7769 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007770 return false;
7771 }
7772
7773 return true;
7774}
7775
Caroline Tice8ce96d92011-03-03 18:27:17 +00007776// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7777// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7778bool
7779EmulateInstructionARM::EmulateUXTB (ARMEncoding encoding)
7780{
7781#if 0
7782 if ConditionPassed() then
7783 EncodingSpecificOperations();
7784 rotated = ROR(R[m], rotation);
7785 R[d] = ZeroExtend(rotated<7:0>, 32);
7786#endif
7787
7788 bool success = false;
7789 const uint32_t opcode = OpcodeAsUnsigned (&success);
7790 if (!success)
7791 return false;
7792
7793 if (ConditionPassed())
7794 {
7795 uint32_t d;
7796 uint32_t m;
7797 uint32_t rotation;
7798
7799 // EncodingSpecificOperations();
7800 switch (encoding)
7801 {
7802 case eEncodingT1:
7803 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7804 d = Bits32 (opcode, 2, 0);
7805 m = Bits32 (opcode, 5, 3);
7806 rotation = 0;
7807
7808 break;
7809
7810 case eEncodingT2:
7811 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7812 d = Bits32 (opcode, 11, 8);
7813 m = Bits32 (opcode, 3, 0);
7814 rotation = Bits32 (opcode, 5, 4) << 3;
7815
7816 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7817 if (BadReg (d) || BadReg (m))
7818 return false;
7819
7820 break;
7821
7822 case eEncodingA1:
7823 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7824 d = Bits32 (opcode, 15, 12);
7825 m = Bits32 (opcode, 3, 0);
7826 rotation = Bits32 (opcode, 11, 10) << 3;
7827
7828 // if d == 15 || m == 15 then UNPREDICTABLE;
7829 if ((d == 15) || (m == 15))
7830 return false;
7831
7832 break;
7833
7834 default:
7835 return false;
7836 }
7837
7838 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7839 if (!success)
7840 return false;
7841
7842 // rotated = ROR(R[m], rotation);
7843 uint64_t rotated = ROR (Rm, rotation);
7844
7845 // R[d] = ZeroExtend(rotated<7:0>, 32);
7846 Register source_reg;
7847 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7848
7849 EmulateInstruction::Context context;
7850 context.type = eContextRegisterLoad;
7851 context.SetRegister (source_reg);
7852
7853 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7854 return false;
7855 }
7856 return true;
7857}
7858
Caroline Tice11555f22011-03-03 18:48:58 +00007859// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7860// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7861bool
7862EmulateInstructionARM::EmulateUXTH (ARMEncoding encoding)
7863{
7864#if 0
7865 if ConditionPassed() then
7866 EncodingSpecificOperations();
7867 rotated = ROR(R[m], rotation);
7868 R[d] = ZeroExtend(rotated<15:0>, 32);
7869#endif
7870
7871 bool success = false;
7872 const uint32_t opcode = OpcodeAsUnsigned (&success);
7873 if (!success)
7874 return false;
7875
7876 if (ConditionPassed ())
7877 {
7878 uint32_t d;
7879 uint32_t m;
7880 uint32_t rotation;
7881
7882 switch (encoding)
7883 {
7884 case eEncodingT1:
7885 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7886 d = Bits32 (opcode, 2, 0);
7887 m = Bits32 (opcode, 5, 3);
7888 rotation = 0;
7889
7890 break;
7891
7892 case eEncodingT2:
7893 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7894 d = Bits32 (opcode, 11, 8);
7895 m = Bits32 (opcode, 3, 0);
7896 rotation = Bits32 (opcode, 5, 4) << 3;
7897
7898 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7899 if (BadReg (d) || BadReg (m))
7900 return false;
7901
7902 break;
7903
7904 case eEncodingA1:
7905 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7906 d = Bits32 (opcode, 15, 12);
7907 m = Bits32 (opcode, 3, 0);
7908 rotation = Bits32 (opcode, 11, 10) << 3;
7909
7910 // if d == 15 || m == 15 then UNPREDICTABLE;
7911 if ((d == 15) || (m == 15))
7912 return false;
7913
7914 break;
7915
7916 default:
7917 return false;
7918 }
7919
7920 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7921 if (!success)
7922 return false;
7923
7924 // rotated = ROR(R[m], rotation);
7925 uint64_t rotated = ROR (Rm, rotation);
7926
7927 // R[d] = ZeroExtend(rotated<15:0>, 32);
7928 Register source_reg;
7929 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7930
7931 EmulateInstruction::Context context;
7932 context.type = eContextRegisterLoad;
7933 context.SetRegister (source_reg);
7934
7935 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7936 return false;
7937 }
7938 return true;
7939}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007940
7941// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7942// word respectively.
7943bool
7944EmulateInstructionARM::EmulateRFE (ARMEncoding encoding)
7945{
7946#if 0
7947 if ConditionPassed() then
7948 EncodingSpecificOperations();
7949 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7950 UNPREDICTABLE;
7951 else
7952 address = if increment then R[n] else R[n]-8;
7953 if wordhigher then address = address+4;
7954 CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
7955 BranchWritePC(MemA[address,4]);
7956 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7957#endif
7958
7959 bool success = false;
7960 const uint32_t opcode = OpcodeAsUnsigned (&success);
7961 if (!success)
7962 return false;
7963
7964 if (ConditionPassed())
7965 {
7966 uint32_t n;
7967 bool wback;
7968 bool increment;
7969 bool wordhigher;
7970
7971 // EncodingSpecificOperations();
7972 switch (encoding)
7973 {
7974 case eEncodingT1:
7975 // n = UInt(Rn); wback = (W == ’1’); increment = FALSE; wordhigher = FALSE;
7976 n = Bits32 (opcode, 19, 16);
7977 wback = BitIsSet (opcode, 21);
7978 increment = false;
7979 wordhigher = false;
7980
7981 // if n == 15 then UNPREDICTABLE;
7982 if (n == 15)
7983 return false;
7984
7985 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7986 if (InITBlock() && !LastInITBlock())
7987 return false;
7988
7989 break;
7990
7991 case eEncodingT2:
7992 // n = UInt(Rn); wback = (W == ’1’); increment = TRUE; wordhigher = FALSE;
7993 n = Bits32 (opcode, 19, 16);
7994 wback = BitIsSet (opcode, 21);
7995 increment = true;
7996 wordhigher = false;
7997
7998 // if n == 15 then UNPREDICTABLE;
7999 if (n == 15)
8000 return false;
8001
8002 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8003 if (InITBlock() && !LastInITBlock())
8004 return false;
8005
8006 break;
8007
8008 case eEncodingA1:
8009 // n = UInt(Rn);
8010 n = Bits32 (opcode, 19, 16);
8011
8012 // wback = (W == ’1’); inc = (U == ’1’); wordhigher = (P == U);
8013 wback = BitIsSet (opcode, 21);
8014 increment = BitIsSet (opcode, 23);
8015 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8016
8017 // if n == 15 then UNPREDICTABLE;
8018 if (n == 15)
8019 return false;
8020
8021 break;
8022
8023 default:
8024 return false;
8025 }
8026
8027 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8028 if (!CurrentModeIsPrivileged ())
8029 // UNPREDICTABLE;
8030 return false;
8031 else
8032 {
8033 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8034 if (!success)
8035 return false;
8036
8037 addr_t address;
8038 // address = if increment then R[n] else R[n]-8;
8039 if (increment)
8040 address = Rn;
8041 else
8042 address = Rn - 8;
8043
8044 // if wordhigher then address = address+4;
8045 if (wordhigher)
8046 address = address + 4;
8047
8048 // CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
8049 Register base_reg;
8050 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8051
8052 EmulateInstruction::Context context;
8053 context.type = eContextReturnFromException;
8054 context.SetRegisterPlusOffset (base_reg, address - Rn);
8055
8056 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8057 if (!success)
8058 return false;
8059
8060 CPSRWriteByInstr (data, 15, true);
8061
8062 // BranchWritePC(MemA[address,4]);
8063 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8064 if (!success)
8065 return false;
8066
8067 BranchWritePC (context, data2);
8068
8069 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8070 if (wback)
8071 {
8072 context.type = eContextAdjustBaseRegister;
8073 if (increment)
8074 {
8075 context.SetOffset (8);
8076 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8077 return false;
8078 }
8079 else
8080 {
8081 context.SetOffset (-8);
8082 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8083 return false;
8084 }
8085 } // if wback
8086 }
8087 } // if ConditionPassed()
8088 return true;
8089}
Caroline Tice11555f22011-03-03 18:48:58 +00008090
Johnny Chen2115b412011-02-21 23:42:44 +00008091// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8092// and writes the result to the destination register. It can optionally update the condition flags based on
8093// the result.
8094bool
8095EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
8096{
8097#if 0
8098 // ARM pseudo code...
8099 if ConditionPassed() then
8100 EncodingSpecificOperations();
8101 result = R[n] EOR imm32;
8102 if d == 15 then // Can only occur for ARM encoding
8103 ALUWritePC(result); // setflags is always FALSE here
8104 else
8105 R[d] = result;
8106 if setflags then
8107 APSR.N = result<31>;
8108 APSR.Z = IsZeroBit(result);
8109 APSR.C = carry;
8110 // APSR.V unchanged
8111#endif
8112
8113 bool success = false;
8114 const uint32_t opcode = OpcodeAsUnsigned (&success);
8115 if (!success)
8116 return false;
8117
8118 if (ConditionPassed())
8119 {
8120 uint32_t Rd, Rn;
8121 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8122 bool setflags;
8123 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8124 switch (encoding)
8125 {
8126 case eEncodingT1:
8127 Rd = Bits32(opcode, 11, 8);
8128 Rn = Bits32(opcode, 19, 16);
8129 setflags = BitIsSet(opcode, 20);
8130 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8131 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8132 if (Rd == 15 && setflags)
8133 return EmulateTEQImm(eEncodingT1);
8134 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8135 return false;
8136 break;
8137 case eEncodingA1:
8138 Rd = Bits32(opcode, 15, 12);
8139 Rn = Bits32(opcode, 19, 16);
8140 setflags = BitIsSet(opcode, 20);
8141 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8142 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8143 // TODO: Emulate SUBS PC, LR and related instructions.
8144 if (Rd == 15 && setflags)
8145 return false;
8146 break;
8147 default:
8148 return false;
8149 }
8150
8151 // Read the first operand.
8152 uint32_t val1 = ReadCoreReg(Rn, &success);
8153 if (!success)
8154 return false;
8155
8156 uint32_t result = val1 ^ imm32;
8157
8158 EmulateInstruction::Context context;
8159 context.type = EmulateInstruction::eContextImmediate;
8160 context.SetNoArgs ();
8161
8162 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8163 return false;
8164 }
8165 return true;
8166}
8167
8168// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8169// optionally-shifted register value, and writes the result to the destination register.
8170// It can optionally update the condition flags based on the result.
8171bool
8172EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
8173{
8174#if 0
8175 // ARM pseudo code...
8176 if ConditionPassed() then
8177 EncodingSpecificOperations();
8178 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8179 result = R[n] EOR shifted;
8180 if d == 15 then // Can only occur for ARM encoding
8181 ALUWritePC(result); // setflags is always FALSE here
8182 else
8183 R[d] = result;
8184 if setflags then
8185 APSR.N = result<31>;
8186 APSR.Z = IsZeroBit(result);
8187 APSR.C = carry;
8188 // APSR.V unchanged
8189#endif
8190
8191 bool success = false;
8192 const uint32_t opcode = OpcodeAsUnsigned (&success);
8193 if (!success)
8194 return false;
8195
8196 if (ConditionPassed())
8197 {
8198 uint32_t Rd, Rn, Rm;
8199 ARM_ShifterType shift_t;
8200 uint32_t shift_n; // the shift applied to the value read from Rm
8201 bool setflags;
8202 uint32_t carry;
8203 switch (encoding)
8204 {
8205 case eEncodingT1:
8206 Rd = Rn = Bits32(opcode, 2, 0);
8207 Rm = Bits32(opcode, 5, 3);
8208 setflags = !InITBlock();
8209 shift_t = SRType_LSL;
8210 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008211 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008212 case eEncodingT2:
8213 Rd = Bits32(opcode, 11, 8);
8214 Rn = Bits32(opcode, 19, 16);
8215 Rm = Bits32(opcode, 3, 0);
8216 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008217 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8218 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008219 if (Rd == 15 && setflags)
8220 return EmulateTEQReg(eEncodingT1);
8221 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8222 return false;
8223 break;
8224 case eEncodingA1:
8225 Rd = Bits32(opcode, 15, 12);
8226 Rn = Bits32(opcode, 19, 16);
8227 Rm = Bits32(opcode, 3, 0);
8228 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008229 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008230 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8231 // TODO: Emulate SUBS PC, LR and related instructions.
8232 if (Rd == 15 && setflags)
8233 return false;
8234 break;
8235 default:
8236 return false;
8237 }
8238
8239 // Read the first operand.
8240 uint32_t val1 = ReadCoreReg(Rn, &success);
8241 if (!success)
8242 return false;
8243
8244 // Read the second operand.
8245 uint32_t val2 = ReadCoreReg(Rm, &success);
8246 if (!success)
8247 return false;
8248
8249 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8250 uint32_t result = val1 ^ shifted;
8251
8252 EmulateInstruction::Context context;
8253 context.type = EmulateInstruction::eContextImmediate;
8254 context.SetNoArgs ();
8255
8256 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8257 return false;
8258 }
8259 return true;
8260}
8261
Johnny Chen7c5234d2011-02-18 23:41:11 +00008262// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8263// writes the result to the destination register. It can optionally update the condition flags based
8264// on the result.
8265bool
8266EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
8267{
8268#if 0
8269 // ARM pseudo code...
8270 if ConditionPassed() then
8271 EncodingSpecificOperations();
8272 result = R[n] OR imm32;
8273 if d == 15 then // Can only occur for ARM encoding
8274 ALUWritePC(result); // setflags is always FALSE here
8275 else
8276 R[d] = result;
8277 if setflags then
8278 APSR.N = result<31>;
8279 APSR.Z = IsZeroBit(result);
8280 APSR.C = carry;
8281 // APSR.V unchanged
8282#endif
8283
8284 bool success = false;
8285 const uint32_t opcode = OpcodeAsUnsigned (&success);
8286 if (!success)
8287 return false;
8288
8289 if (ConditionPassed())
8290 {
8291 uint32_t Rd, Rn;
8292 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8293 bool setflags;
8294 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8295 switch (encoding)
8296 {
8297 case eEncodingT1:
8298 Rd = Bits32(opcode, 11, 8);
8299 Rn = Bits32(opcode, 19, 16);
8300 setflags = BitIsSet(opcode, 20);
8301 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8302 // if Rn == ‘1111’ then SEE MOV (immediate);
8303 if (Rn == 15)
8304 return EmulateMOVRdImm(eEncodingT2);
8305 if (BadReg(Rd) || Rn == 13)
8306 return false;
8307 break;
8308 case eEncodingA1:
8309 Rd = Bits32(opcode, 15, 12);
8310 Rn = Bits32(opcode, 19, 16);
8311 setflags = BitIsSet(opcode, 20);
8312 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8313 // TODO: Emulate SUBS PC, LR and related instructions.
8314 if (Rd == 15 && setflags)
8315 return false;
8316 break;
8317 default:
8318 return false;
8319 }
8320
8321 // Read the first operand.
8322 uint32_t val1 = ReadCoreReg(Rn, &success);
8323 if (!success)
8324 return false;
8325
8326 uint32_t result = val1 | imm32;
8327
8328 EmulateInstruction::Context context;
8329 context.type = EmulateInstruction::eContextImmediate;
8330 context.SetNoArgs ();
8331
8332 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8333 return false;
8334 }
8335 return true;
8336}
8337
8338// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8339// value, and writes the result to the destination register. It can optionally update the condition flags based
8340// on the result.
8341bool
8342EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
8343{
8344#if 0
8345 // ARM pseudo code...
8346 if ConditionPassed() then
8347 EncodingSpecificOperations();
8348 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8349 result = R[n] OR shifted;
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 unchanged
8359#endif
8360
8361 bool success = false;
8362 const uint32_t opcode = OpcodeAsUnsigned (&success);
8363 if (!success)
8364 return false;
8365
8366 if (ConditionPassed())
8367 {
8368 uint32_t Rd, Rn, Rm;
8369 ARM_ShifterType shift_t;
8370 uint32_t shift_n; // the shift applied to the value read from Rm
8371 bool setflags;
8372 uint32_t carry;
8373 switch (encoding)
8374 {
8375 case eEncodingT1:
8376 Rd = Rn = Bits32(opcode, 2, 0);
8377 Rm = Bits32(opcode, 5, 3);
8378 setflags = !InITBlock();
8379 shift_t = SRType_LSL;
8380 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008381 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008382 case eEncodingT2:
8383 Rd = Bits32(opcode, 11, 8);
8384 Rn = Bits32(opcode, 19, 16);
8385 Rm = Bits32(opcode, 3, 0);
8386 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008387 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8388 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008389 if (Rn == 15)
8390 return EmulateMOVRdRm(eEncodingT3);
8391 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8392 return false;
8393 break;
8394 case eEncodingA1:
8395 Rd = Bits32(opcode, 15, 12);
8396 Rn = Bits32(opcode, 19, 16);
8397 Rm = Bits32(opcode, 3, 0);
8398 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008399 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008400 // TODO: Emulate SUBS PC, LR and related instructions.
8401 if (Rd == 15 && setflags)
8402 return false;
8403 break;
8404 default:
8405 return false;
8406 }
8407
8408 // Read the first operand.
8409 uint32_t val1 = ReadCoreReg(Rn, &success);
8410 if (!success)
8411 return false;
8412
8413 // Read the second operand.
8414 uint32_t val2 = ReadCoreReg(Rm, &success);
8415 if (!success)
8416 return false;
8417
8418 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008419 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008420
8421 EmulateInstruction::Context context;
8422 context.type = EmulateInstruction::eContextImmediate;
8423 context.SetNoArgs ();
8424
8425 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8426 return false;
8427 }
8428 return true;
8429}
8430
Johnny Chened32e7c2011-02-22 23:42:58 +00008431// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8432// the destination register. It can optionally update the condition flags based on the result.
8433bool
8434EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
8435{
8436#if 0
8437 // ARM pseudo code...
8438 if ConditionPassed() then
8439 EncodingSpecificOperations();
8440 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8441 if d == 15 then // Can only occur for ARM encoding
8442 ALUWritePC(result); // setflags is always FALSE here
8443 else
8444 R[d] = result;
8445 if setflags then
8446 APSR.N = result<31>;
8447 APSR.Z = IsZeroBit(result);
8448 APSR.C = carry;
8449 APSR.V = overflow;
8450#endif
8451
8452 bool success = false;
8453 const uint32_t opcode = OpcodeAsUnsigned (&success);
8454 if (!success)
8455 return false;
8456
8457 uint32_t Rd; // the destination register
8458 uint32_t Rn; // the first operand
8459 bool setflags;
8460 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8461 switch (encoding) {
8462 case eEncodingT1:
8463 Rd = Bits32(opcode, 2, 0);
8464 Rn = Bits32(opcode, 5, 3);
8465 setflags = !InITBlock();
8466 imm32 = 0;
8467 break;
8468 case eEncodingT2:
8469 Rd = Bits32(opcode, 11, 8);
8470 Rn = Bits32(opcode, 19, 16);
8471 setflags = BitIsSet(opcode, 20);
8472 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8473 if (BadReg(Rd) || BadReg(Rn))
8474 return false;
8475 break;
8476 case eEncodingA1:
8477 Rd = Bits32(opcode, 15, 12);
8478 Rn = Bits32(opcode, 19, 16);
8479 setflags = BitIsSet(opcode, 20);
8480 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8481 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8482 // TODO: Emulate SUBS PC, LR and related instructions.
8483 if (Rd == 15 && setflags)
8484 return false;
8485 break;
8486 default:
8487 return false;
8488 }
8489 // Read the register value from the operand register Rn.
8490 uint32_t reg_val = ReadCoreReg(Rn, &success);
8491 if (!success)
8492 return false;
8493
8494 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8495
8496 EmulateInstruction::Context context;
8497 context.type = EmulateInstruction::eContextImmediate;
8498 context.SetNoArgs ();
8499
8500 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8501 return false;
8502
8503 return true;
8504}
8505
8506// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8507// result to the destination register. It can optionally update the condition flags based on the result.
8508bool
8509EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
8510{
8511#if 0
8512 // ARM pseudo code...
8513 if ConditionPassed() then
8514 EncodingSpecificOperations();
8515 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8516 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8517 if d == 15 then // Can only occur for ARM encoding
8518 ALUWritePC(result); // setflags is always FALSE here
8519 else
8520 R[d] = result;
8521 if setflags then
8522 APSR.N = result<31>;
8523 APSR.Z = IsZeroBit(result);
8524 APSR.C = carry;
8525 APSR.V = overflow;
8526#endif
8527
8528 bool success = false;
8529 const uint32_t opcode = OpcodeAsUnsigned (&success);
8530 if (!success)
8531 return false;
8532
8533 uint32_t Rd; // the destination register
8534 uint32_t Rn; // the first operand
8535 uint32_t Rm; // the second operand
8536 bool setflags;
8537 ARM_ShifterType shift_t;
8538 uint32_t shift_n; // the shift applied to the value read from Rm
8539 switch (encoding) {
8540 case eEncodingT1:
8541 Rd = Bits32(opcode, 11, 8);
8542 Rn = Bits32(opcode, 19, 16);
8543 Rm = Bits32(opcode, 3, 0);
8544 setflags = BitIsSet(opcode, 20);
8545 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8546 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8547 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8548 return false;
8549 break;
8550 case eEncodingA1:
8551 Rd = Bits32(opcode, 15, 12);
8552 Rn = Bits32(opcode, 19, 16);
8553 Rm = Bits32(opcode, 3, 0);
8554 setflags = BitIsSet(opcode, 20);
8555 shift_n = DecodeImmShiftARM(opcode, shift_t);
8556 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8557 // TODO: Emulate SUBS PC, LR and related instructions.
8558 if (Rd == 15 && setflags)
8559 return false;
8560 break;
8561 default:
8562 return false;
8563 }
8564 // Read the register value from register Rn.
8565 uint32_t val1 = ReadCoreReg(Rn, &success);
8566 if (!success)
8567 return false;
8568
8569 // Read the register value from register Rm.
8570 uint32_t val2 = ReadCoreReg(Rm, &success);
8571 if (!success)
8572 return false;
8573
8574 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8575 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8576
8577 EmulateInstruction::Context context;
8578 context.type = EmulateInstruction::eContextImmediate;
8579 context.SetNoArgs();
8580 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8581 return false;
8582
8583 return true;
8584}
8585
Johnny Chen90e607b2011-02-23 00:07:09 +00008586// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8587// an immediate value, and writes the result to the destination register. It can optionally update the condition
8588// flags based on the result.
8589bool
8590EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
8591{
8592#if 0
8593 // ARM pseudo code...
8594 if ConditionPassed() then
8595 EncodingSpecificOperations();
8596 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8597 if d == 15 then
8598 ALUWritePC(result); // setflags is always FALSE here
8599 else
8600 R[d] = result;
8601 if setflags then
8602 APSR.N = result<31>;
8603 APSR.Z = IsZeroBit(result);
8604 APSR.C = carry;
8605 APSR.V = overflow;
8606#endif
8607
8608 bool success = false;
8609 const uint32_t opcode = OpcodeAsUnsigned (&success);
8610 if (!success)
8611 return false;
8612
8613 uint32_t Rd; // the destination register
8614 uint32_t Rn; // the first operand
8615 bool setflags;
8616 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8617 switch (encoding) {
8618 case eEncodingA1:
8619 Rd = Bits32(opcode, 15, 12);
8620 Rn = Bits32(opcode, 19, 16);
8621 setflags = BitIsSet(opcode, 20);
8622 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8623 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8624 // TODO: Emulate SUBS PC, LR and related instructions.
8625 if (Rd == 15 && setflags)
8626 return false;
8627 break;
8628 default:
8629 return false;
8630 }
8631 // Read the register value from the operand register Rn.
8632 uint32_t reg_val = ReadCoreReg(Rn, &success);
8633 if (!success)
8634 return false;
8635
8636 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8637
8638 EmulateInstruction::Context context;
8639 context.type = EmulateInstruction::eContextImmediate;
8640 context.SetNoArgs ();
8641
8642 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8643 return false;
8644
8645 return true;
8646}
8647
8648// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8649// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8650// condition flags based on the result.
8651bool
8652EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
8653{
8654#if 0
8655 // ARM pseudo code...
8656 if ConditionPassed() then
8657 EncodingSpecificOperations();
8658 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8659 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8660 if d == 15 then
8661 ALUWritePC(result); // setflags is always FALSE here
8662 else
8663 R[d] = result;
8664 if setflags then
8665 APSR.N = result<31>;
8666 APSR.Z = IsZeroBit(result);
8667 APSR.C = carry;
8668 APSR.V = overflow;
8669#endif
8670
8671 bool success = false;
8672 const uint32_t opcode = OpcodeAsUnsigned (&success);
8673 if (!success)
8674 return false;
8675
8676 uint32_t Rd; // the destination register
8677 uint32_t Rn; // the first operand
8678 uint32_t Rm; // the second operand
8679 bool setflags;
8680 ARM_ShifterType shift_t;
8681 uint32_t shift_n; // the shift applied to the value read from Rm
8682 switch (encoding) {
8683 case eEncodingA1:
8684 Rd = Bits32(opcode, 15, 12);
8685 Rn = Bits32(opcode, 19, 16);
8686 Rm = Bits32(opcode, 3, 0);
8687 setflags = BitIsSet(opcode, 20);
8688 shift_n = DecodeImmShiftARM(opcode, shift_t);
8689 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8690 // TODO: Emulate SUBS PC, LR and related instructions.
8691 if (Rd == 15 && setflags)
8692 return false;
8693 break;
8694 default:
8695 return false;
8696 }
8697 // Read the register value from register Rn.
8698 uint32_t val1 = ReadCoreReg(Rn, &success);
8699 if (!success)
8700 return false;
8701
8702 // Read the register value from register Rm.
8703 uint32_t val2 = ReadCoreReg(Rm, &success);
8704 if (!success)
8705 return false;
8706
8707 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8708 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8709
8710 EmulateInstruction::Context context;
8711 context.type = EmulateInstruction::eContextImmediate;
8712 context.SetNoArgs();
8713 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8714 return false;
8715
8716 return true;
8717}
8718
Johnny Chen9b381772011-02-23 01:01:21 +00008719// Subtract with Carry (immediate) subtracts an immediate value and the value of
8720// NOT (Carry flag) from a register value, and writes the result to the destination register.
8721// It can optionally update the condition flags based on the result.
8722bool
8723EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
8724{
8725#if 0
8726 // ARM pseudo code...
8727 if ConditionPassed() then
8728 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008729 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008730 if d == 15 then // Can only occur for ARM encoding
8731 ALUWritePC(result); // setflags is always FALSE here
8732 else
8733 R[d] = result;
8734 if setflags then
8735 APSR.N = result<31>;
8736 APSR.Z = IsZeroBit(result);
8737 APSR.C = carry;
8738 APSR.V = overflow;
8739#endif
8740
8741 bool success = false;
8742 const uint32_t opcode = OpcodeAsUnsigned (&success);
8743 if (!success)
8744 return false;
8745
8746 uint32_t Rd; // the destination register
8747 uint32_t Rn; // the first operand
8748 bool setflags;
8749 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8750 switch (encoding) {
8751 case eEncodingT1:
8752 Rd = Bits32(opcode, 11, 8);
8753 Rn = Bits32(opcode, 19, 16);
8754 setflags = BitIsSet(opcode, 20);
8755 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8756 if (BadReg(Rd) || BadReg(Rn))
8757 return false;
8758 break;
8759 case eEncodingA1:
8760 Rd = Bits32(opcode, 15, 12);
8761 Rn = Bits32(opcode, 19, 16);
8762 setflags = BitIsSet(opcode, 20);
8763 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8764 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8765 // TODO: Emulate SUBS PC, LR and related instructions.
8766 if (Rd == 15 && setflags)
8767 return false;
8768 break;
8769 default:
8770 return false;
8771 }
8772 // Read the register value from the operand register Rn.
8773 uint32_t reg_val = ReadCoreReg(Rn, &success);
8774 if (!success)
8775 return false;
8776
8777 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8778
8779 EmulateInstruction::Context context;
8780 context.type = EmulateInstruction::eContextImmediate;
8781 context.SetNoArgs ();
8782
8783 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8784 return false;
8785
8786 return true;
8787}
8788
8789// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8790// NOT (Carry flag) from a register value, and writes the result to the destination register.
8791// It can optionally update the condition flags based on the result.
8792bool
8793EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8794{
8795#if 0
8796 // ARM pseudo code...
8797 if ConditionPassed() then
8798 EncodingSpecificOperations();
8799 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8800 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8801 if d == 15 then // Can only occur for ARM encoding
8802 ALUWritePC(result); // setflags is always FALSE here
8803 else
8804 R[d] = result;
8805 if setflags then
8806 APSR.N = result<31>;
8807 APSR.Z = IsZeroBit(result);
8808 APSR.C = carry;
8809 APSR.V = overflow;
8810#endif
8811
8812 bool success = false;
8813 const uint32_t opcode = OpcodeAsUnsigned (&success);
8814 if (!success)
8815 return false;
8816
8817 uint32_t Rd; // the destination register
8818 uint32_t Rn; // the first operand
8819 uint32_t Rm; // the second operand
8820 bool setflags;
8821 ARM_ShifterType shift_t;
8822 uint32_t shift_n; // the shift applied to the value read from Rm
8823 switch (encoding) {
8824 case eEncodingT1:
8825 Rd = Rn = Bits32(opcode, 2, 0);
8826 Rm = Bits32(opcode, 5, 3);
8827 setflags = !InITBlock();
8828 shift_t = SRType_LSL;
8829 shift_n = 0;
8830 break;
8831 case eEncodingT2:
8832 Rd = Bits32(opcode, 11, 8);
8833 Rn = Bits32(opcode, 19, 16);
8834 Rm = Bits32(opcode, 3, 0);
8835 setflags = BitIsSet(opcode, 20);
8836 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8837 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8838 return false;
8839 break;
8840 case eEncodingA1:
8841 Rd = Bits32(opcode, 15, 12);
8842 Rn = Bits32(opcode, 19, 16);
8843 Rm = Bits32(opcode, 3, 0);
8844 setflags = BitIsSet(opcode, 20);
8845 shift_n = DecodeImmShiftARM(opcode, shift_t);
8846 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8847 // TODO: Emulate SUBS PC, LR and related instructions.
8848 if (Rd == 15 && setflags)
8849 return false;
8850 break;
8851 default:
8852 return false;
8853 }
8854 // Read the register value from register Rn.
8855 uint32_t val1 = ReadCoreReg(Rn, &success);
8856 if (!success)
8857 return false;
8858
8859 // Read the register value from register Rm.
8860 uint32_t val2 = ReadCoreReg(Rm, &success);
8861 if (!success)
8862 return false;
8863
8864 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8865 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8866
8867 EmulateInstruction::Context context;
8868 context.type = EmulateInstruction::eContextImmediate;
8869 context.SetNoArgs();
8870 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8871 return false;
8872
8873 return true;
8874}
8875
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008876// This instruction subtracts an immediate value from a register value, and writes the result
8877// to the destination register. It can optionally update the condition flags based on the result.
8878bool
8879EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8880{
8881#if 0
8882 // ARM pseudo code...
8883 if ConditionPassed() then
8884 EncodingSpecificOperations();
8885 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8886 R[d] = result;
8887 if setflags then
8888 APSR.N = result<31>;
8889 APSR.Z = IsZeroBit(result);
8890 APSR.C = carry;
8891 APSR.V = overflow;
8892#endif
8893
8894 bool success = false;
8895 const uint32_t opcode = OpcodeAsUnsigned (&success);
8896 if (!success)
8897 return false;
8898
8899 uint32_t Rd; // the destination register
8900 uint32_t Rn; // the first operand
8901 bool setflags;
8902 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8903 switch (encoding) {
8904 case eEncodingT1:
8905 Rd = Bits32(opcode, 2, 0);
8906 Rn = Bits32(opcode, 5, 3);
8907 setflags = !InITBlock();
8908 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8909 break;
8910 case eEncodingT2:
8911 Rd = Rn = Bits32(opcode, 10, 8);
8912 setflags = !InITBlock();
8913 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8914 break;
8915 case eEncodingT3:
8916 Rd = Bits32(opcode, 11, 8);
8917 Rn = Bits32(opcode, 19, 16);
8918 setflags = BitIsSet(opcode, 20);
8919 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8920
8921 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8922 if (Rd == 15 && setflags)
8923 return EmulateCMPImm(eEncodingT2);
8924
8925 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8926 if (Rn == 13)
8927 return EmulateSUBSPImm(eEncodingT2);
8928
8929 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8930 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8931 return false;
8932 break;
8933 case eEncodingT4:
8934 Rd = Bits32(opcode, 11, 8);
8935 Rn = Bits32(opcode, 19, 16);
8936 setflags = BitIsSet(opcode, 20);
8937 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8938
8939 // if Rn == '1111' then SEE ADR;
8940 if (Rn == 15)
8941 return EmulateADR(eEncodingT2);
8942
8943 // if Rn == '1101' then SEE SUB (SP minus immediate);
8944 if (Rn == 13)
8945 return EmulateSUBSPImm(eEncodingT3);
8946
8947 if (BadReg(Rd))
8948 return false;
8949 break;
8950 default:
8951 return false;
8952 }
8953 // Read the register value from the operand register Rn.
8954 uint32_t reg_val = ReadCoreReg(Rn, &success);
8955 if (!success)
8956 return false;
8957
8958 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8959
8960 EmulateInstruction::Context context;
8961 context.type = EmulateInstruction::eContextImmediate;
8962 context.SetNoArgs ();
8963
8964 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8965 return false;
8966
8967 return true;
8968}
8969
8970// This instruction subtracts an immediate value from a register value, and writes the result
8971// to the destination register. It can optionally update the condition flags based on the result.
8972bool
8973EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
8974{
8975#if 0
8976 // ARM pseudo code...
8977 if ConditionPassed() then
8978 EncodingSpecificOperations();
8979 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8980 if d == 15 then
8981 ALUWritePC(result); // setflags is always FALSE here
8982 else
8983 R[d] = result;
8984 if setflags then
8985 APSR.N = result<31>;
8986 APSR.Z = IsZeroBit(result);
8987 APSR.C = carry;
8988 APSR.V = overflow;
8989#endif
8990
8991 bool success = false;
8992 const uint32_t opcode = OpcodeAsUnsigned (&success);
8993 if (!success)
8994 return false;
8995
8996 uint32_t Rd; // the destination register
8997 uint32_t Rn; // the first operand
8998 bool setflags;
8999 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9000 switch (encoding) {
9001 case eEncodingA1:
9002 Rd = Bits32(opcode, 15, 12);
9003 Rn = Bits32(opcode, 19, 16);
9004 setflags = BitIsSet(opcode, 20);
9005 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9006
9007 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
9008 if (Rn == 15 && !setflags)
9009 return EmulateADR(eEncodingA2);
9010
9011 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
9012 if (Rn == 13)
9013 return EmulateSUBSPImm(eEncodingA1);
9014
9015 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
9016 // TODO: Emulate SUBS PC, LR and related instructions.
9017 if (Rd == 15 && setflags)
9018 return false;
9019 break;
9020 default:
9021 return false;
9022 }
9023 // Read the register value from the operand register Rn.
9024 uint32_t reg_val = ReadCoreReg(Rn, &success);
9025 if (!success)
9026 return false;
9027
9028 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9029
9030 EmulateInstruction::Context context;
9031 context.type = EmulateInstruction::eContextImmediate;
9032 context.SetNoArgs ();
9033
9034 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9035 return false;
9036
9037 return true;
9038}
9039
Johnny Chen2115b412011-02-21 23:42:44 +00009040// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9041// immediate value. It updates the condition flags based on the result, and discards the result.
9042bool
9043EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
9044{
9045#if 0
9046 // ARM pseudo code...
9047 if ConditionPassed() then
9048 EncodingSpecificOperations();
9049 result = R[n] EOR imm32;
9050 APSR.N = result<31>;
9051 APSR.Z = IsZeroBit(result);
9052 APSR.C = carry;
9053 // APSR.V unchanged
9054#endif
9055
9056 bool success = false;
9057 const uint32_t opcode = OpcodeAsUnsigned (&success);
9058 if (!success)
9059 return false;
9060
9061 if (ConditionPassed())
9062 {
9063 uint32_t Rn;
9064 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9065 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9066 switch (encoding)
9067 {
9068 case eEncodingT1:
9069 Rn = Bits32(opcode, 19, 16);
9070 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9071 if (BadReg(Rn))
9072 return false;
9073 break;
9074 case eEncodingA1:
9075 Rn = Bits32(opcode, 19, 16);
9076 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9077 break;
9078 default:
9079 return false;
9080 }
9081
9082 // Read the first operand.
9083 uint32_t val1 = ReadCoreReg(Rn, &success);
9084 if (!success)
9085 return false;
9086
9087 uint32_t result = val1 ^ imm32;
9088
9089 EmulateInstruction::Context context;
9090 context.type = EmulateInstruction::eContextImmediate;
9091 context.SetNoArgs ();
9092
9093 if (!WriteFlags(context, result, carry))
9094 return false;
9095 }
9096 return true;
9097}
9098
9099// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9100// optionally-shifted register value. It updates the condition flags based on the result, and discards
9101// the result.
9102bool
9103EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
9104{
9105#if 0
9106 // ARM pseudo code...
9107 if ConditionPassed() then
9108 EncodingSpecificOperations();
9109 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9110 result = R[n] EOR shifted;
9111 APSR.N = result<31>;
9112 APSR.Z = IsZeroBit(result);
9113 APSR.C = carry;
9114 // APSR.V unchanged
9115#endif
9116
9117 bool success = false;
9118 const uint32_t opcode = OpcodeAsUnsigned (&success);
9119 if (!success)
9120 return false;
9121
9122 if (ConditionPassed())
9123 {
9124 uint32_t Rn, Rm;
9125 ARM_ShifterType shift_t;
9126 uint32_t shift_n; // the shift applied to the value read from Rm
9127 uint32_t carry;
9128 switch (encoding)
9129 {
9130 case eEncodingT1:
9131 Rn = Bits32(opcode, 19, 16);
9132 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009133 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009134 if (BadReg(Rn) || BadReg(Rm))
9135 return false;
9136 break;
9137 case eEncodingA1:
9138 Rn = Bits32(opcode, 19, 16);
9139 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009140 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009141 break;
9142 default:
9143 return false;
9144 }
9145
9146 // Read the first operand.
9147 uint32_t val1 = ReadCoreReg(Rn, &success);
9148 if (!success)
9149 return false;
9150
9151 // Read the second operand.
9152 uint32_t val2 = ReadCoreReg(Rm, &success);
9153 if (!success)
9154 return false;
9155
9156 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9157 uint32_t result = val1 ^ shifted;
9158
9159 EmulateInstruction::Context context;
9160 context.type = EmulateInstruction::eContextImmediate;
9161 context.SetNoArgs ();
9162
9163 if (!WriteFlags(context, result, carry))
9164 return false;
9165 }
9166 return true;
9167}
9168
Johnny Chende3cce32011-02-21 21:24:49 +00009169// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9170// It updates the condition flags based on the result, and discards the result.
9171bool
9172EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
9173{
9174#if 0
9175 // ARM pseudo code...
9176 if ConditionPassed() then
9177 EncodingSpecificOperations();
9178 result = R[n] AND imm32;
9179 APSR.N = result<31>;
9180 APSR.Z = IsZeroBit(result);
9181 APSR.C = carry;
9182 // APSR.V unchanged
9183#endif
9184
9185 bool success = false;
9186 const uint32_t opcode = OpcodeAsUnsigned (&success);
9187 if (!success)
9188 return false;
9189
9190 if (ConditionPassed())
9191 {
9192 uint32_t Rn;
9193 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9194 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9195 switch (encoding)
9196 {
9197 case eEncodingT1:
9198 Rn = Bits32(opcode, 19, 16);
9199 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9200 if (BadReg(Rn))
9201 return false;
9202 break;
9203 case eEncodingA1:
9204 Rn = Bits32(opcode, 19, 16);
9205 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9206 break;
9207 default:
9208 return false;
9209 }
9210
9211 // Read the first operand.
9212 uint32_t val1 = ReadCoreReg(Rn, &success);
9213 if (!success)
9214 return false;
9215
9216 uint32_t result = val1 & imm32;
9217
9218 EmulateInstruction::Context context;
9219 context.type = EmulateInstruction::eContextImmediate;
9220 context.SetNoArgs ();
9221
9222 if (!WriteFlags(context, result, carry))
9223 return false;
9224 }
9225 return true;
9226}
9227
9228// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9229// It updates the condition flags based on the result, and discards the result.
9230bool
9231EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
9232{
9233#if 0
9234 // ARM pseudo code...
9235 if ConditionPassed() then
9236 EncodingSpecificOperations();
9237 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9238 result = R[n] AND shifted;
9239 APSR.N = result<31>;
9240 APSR.Z = IsZeroBit(result);
9241 APSR.C = carry;
9242 // APSR.V unchanged
9243#endif
9244
9245 bool success = false;
9246 const uint32_t opcode = OpcodeAsUnsigned (&success);
9247 if (!success)
9248 return false;
9249
9250 if (ConditionPassed())
9251 {
9252 uint32_t Rn, Rm;
9253 ARM_ShifterType shift_t;
9254 uint32_t shift_n; // the shift applied to the value read from Rm
9255 uint32_t carry;
9256 switch (encoding)
9257 {
9258 case eEncodingT1:
9259 Rn = Bits32(opcode, 2, 0);
9260 Rm = Bits32(opcode, 5, 3);
9261 shift_t = SRType_LSL;
9262 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009263 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009264 case eEncodingT2:
9265 Rn = Bits32(opcode, 19, 16);
9266 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009267 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009268 if (BadReg(Rn) || BadReg(Rm))
9269 return false;
9270 break;
9271 case eEncodingA1:
9272 Rn = Bits32(opcode, 19, 16);
9273 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009274 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009275 break;
9276 default:
9277 return false;
9278 }
9279
9280 // Read the first operand.
9281 uint32_t val1 = ReadCoreReg(Rn, &success);
9282 if (!success)
9283 return false;
9284
9285 // Read the second operand.
9286 uint32_t val2 = ReadCoreReg(Rm, &success);
9287 if (!success)
9288 return false;
9289
9290 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9291 uint32_t result = val1 & shifted;
9292
9293 EmulateInstruction::Context context;
9294 context.type = EmulateInstruction::eContextImmediate;
9295 context.SetNoArgs ();
9296
9297 if (!WriteFlags(context, result, carry))
9298 return false;
9299 }
9300 return true;
9301}
9302
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009303EmulateInstructionARM::ARMOpcode*
9304EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009305{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009306 static ARMOpcode
9307 g_arm_opcodes[] =
9308 {
9309 //----------------------------------------------------------------------
9310 // Prologue instructions
9311 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009312
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009313 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009314 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9315 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009316
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009317 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009318 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009319 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009320 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009321 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9322 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009323 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009324
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009325 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009326 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009327
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009328 // push one register
9329 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Caroline Tice8d681f52011-03-17 23:50:16 +00009330 { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009331
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009332 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009333 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9334 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009335
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009336 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009337 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009338 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009339
Johnny Chen9f687722011-02-18 00:02:28 +00009340 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9341 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009342 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009343 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9344
9345 //----------------------------------------------------------------------
9346 // Supervisor Call (previously Software Interrupt)
9347 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009348 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9349
9350 //----------------------------------------------------------------------
9351 // Branch instructions
9352 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009353 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009354 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9355 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9356 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9357 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009358 // for example, "bx lr"
9359 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009360 // bxj
9361 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009362
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009363 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009364 // Data-processing instructions
9365 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009366 // adc (immediate)
9367 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9368 // adc (register)
9369 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009370 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009371 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009372 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009373 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009374 // adr
9375 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9376 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009377 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009378 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009379 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009380 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009381 // bic (immediate)
9382 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9383 // bic (register)
9384 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009385 // eor (immediate)
9386 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9387 // eor (register)
9388 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009389 // orr (immediate)
9390 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9391 // orr (register)
9392 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009393 // rsb (immediate)
9394 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9395 // rsb (register)
9396 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009397 // rsc (immediate)
9398 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9399 // rsc (register)
9400 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009401 // sbc (immediate)
9402 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9403 // sbc (register)
9404 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009405 // sub (immediate, ARM)
9406 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009407 // sub (sp minus immediate)
9408 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009409 // teq (immediate)
9410 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9411 // teq (register)
9412 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009413 // tst (immediate)
9414 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9415 // tst (register)
9416 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9417
9418
Johnny Chen01d61572011-02-25 00:23:25 +00009419 // mov (register)
9420 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009421 // mvn (immediate)
9422 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9423 // mvn (register)
9424 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009425 // cmn (immediate)
9426 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9427 // cmn (register)
9428 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009429 // cmp (immediate)
9430 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9431 // cmp (register)
9432 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009433 // asr (immediate)
9434 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009435 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009436 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009437 // lsl (immediate)
9438 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9439 // lsl (register)
9440 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9441 // lsr (immediate)
9442 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9443 // lsr (register)
9444 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009445 // rrx is a special case encoding of ror (immediate)
9446 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9447 // ror (immediate)
9448 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9449 // ror (register)
9450 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009451 // mul
9452 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009453
9454 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009455 // Load instructions
9456 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009457 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009458 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009459 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009460 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009461 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009462 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009463 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009464 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009465 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009466 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009467 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009468 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009469 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009470 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009471 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9472 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009473
9474 //----------------------------------------------------------------------
9475 // Store instructions
9476 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009477 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009478 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009479 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009480 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009481 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009482 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009483
Caroline Tice6bf65162011-03-03 17:42:58 +00009484 //----------------------------------------------------------------------
9485 // Other instructions
9486 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009487 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009488 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009489 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009490 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9491 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009492
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009493 };
9494 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9495
9496 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9497 {
9498 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9499 return &g_arm_opcodes[i];
9500 }
9501 return NULL;
9502}
Greg Clayton64c84432011-01-21 22:02:52 +00009503
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009504
9505EmulateInstructionARM::ARMOpcode*
9506EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009507{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009508
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009509 static ARMOpcode
9510 g_thumb_opcodes[] =
9511 {
9512 //----------------------------------------------------------------------
9513 // Prologue instructions
9514 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009515
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009516 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009517 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9518 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9519 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009520
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009521 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009522 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009523 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009524 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009525 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009526 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009527
Johnny Chen864a8e82011-02-18 00:07:39 +00009528 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009529 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009530
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009531 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009532 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009533 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009534 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9535 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009536
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009537 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009538 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9539 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009540
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009541 //----------------------------------------------------------------------
9542 // Epilogue instructions
9543 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009544
Johnny Chen864a8e82011-02-18 00:07:39 +00009545 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009546 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9547 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9548 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009549 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9550 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009551
9552 //----------------------------------------------------------------------
9553 // Supervisor Call (previously Software Interrupt)
9554 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009555 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9556
9557 //----------------------------------------------------------------------
9558 // If Then makes up to four following instructions conditional.
9559 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009560 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9561
9562 //----------------------------------------------------------------------
9563 // Branch instructions
9564 //----------------------------------------------------------------------
9565 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9566 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009567 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009568 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009569 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009570 // J1 == J2 == 1
9571 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9572 // J1 == J2 == 1
9573 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9574 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009575 // for example, "bx lr"
9576 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009577 // bxj
9578 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009579 // compare and branch
9580 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009581 // table branch byte
9582 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9583 // table branch halfword
9584 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009585
9586 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009587 // Data-processing instructions
9588 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009589 // adc (immediate)
9590 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9591 // adc (register)
9592 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9593 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9594 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009595 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009596 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009597 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009598 // adr
9599 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9600 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9601 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009602 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009603 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009604 // and (register)
9605 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9606 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009607 // bic (immediate)
9608 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9609 // bic (register)
9610 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9611 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009612 // eor (immediate)
9613 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9614 // eor (register)
9615 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9616 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009617 // orr (immediate)
9618 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9619 // orr (register)
9620 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9621 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009622 // rsb (immediate)
9623 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9624 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9625 // rsb (register)
9626 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009627 // sbc (immediate)
9628 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9629 // sbc (register)
9630 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9631 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009632 // add (immediate, Thumb)
9633 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9634 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9635 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9636 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009637 // sub (immediate, Thumb)
9638 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9639 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9640 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9641 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009642 // sub (sp minus immediate)
9643 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9644 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009645 // teq (immediate)
9646 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9647 // teq (register)
9648 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009649 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009650 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009651 // tst (register)
9652 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9653 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9654
Johnny Chen7c5234d2011-02-18 23:41:11 +00009655
Johnny Chen338bf542011-02-10 19:29:03 +00009656 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009657 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009658 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009659 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009660 // mov{s}<c>.w <Rd>, <Rm>
9661 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009662 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009663 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9664 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009665 // mvn (immediate)
9666 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9667 // mvn (register)
9668 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9669 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009670 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009671 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009672 // cmn (register)
9673 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009674 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009675 // cmp (immediate)
9676 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009677 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009678 // cmp (register) (Rn and Rm both from r0-r7)
9679 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9680 // cmp (register) (Rn and Rm not both from r0-r7)
9681 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009682 // asr (immediate)
9683 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009684 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009685 // asr (register)
9686 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9687 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009688 // lsl (immediate)
9689 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9690 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9691 // lsl (register)
9692 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9693 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9694 // lsr (immediate)
9695 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9696 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9697 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009698 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009699 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009700 // rrx is a special case encoding of ror (immediate)
9701 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9702 // ror (immediate)
9703 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9704 // ror (register)
9705 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9706 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009707 // mul
9708 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9709 // mul
9710 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009711
Johnny Chen26863dc2011-02-09 23:43:29 +00009712 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009713 // Load instructions
9714 //----------------------------------------------------------------------
9715 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009716 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009717 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00009718 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9719 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009720 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009721 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9722 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009723 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9724 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9725 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009726 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009727 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9728 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009729 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9730 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9731 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009732 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009733 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9734 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009735 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9736 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009737 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009738 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9739 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009740 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9741 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009742 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009743 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9744 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009745
9746 //----------------------------------------------------------------------
9747 // Store instructions
9748 //----------------------------------------------------------------------
9749 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009750 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009751 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009752 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9753 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9754 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9755 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9756 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9757 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9758 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9759 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009760 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009761 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
9762 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009763
9764 //----------------------------------------------------------------------
9765 // Other instructions
9766 //----------------------------------------------------------------------
9767 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009768 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9769 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009770 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9771 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009772 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9773 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009774 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9775 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9776 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009777
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009778 };
9779
9780 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9781 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9782 {
9783 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9784 return &g_thumb_opcodes[i];
9785 }
9786 return NULL;
9787}
Greg Clayton64c84432011-01-21 22:02:52 +00009788
Greg Clayton31e2a382011-01-30 20:03:56 +00009789bool
Greg Clayton395fc332011-02-15 21:59:32 +00009790EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009791{
9792 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009793 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009794 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009795 {
Greg Clayton395fc332011-02-15 21:59:32 +00009796 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9797 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9798 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9799 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9800 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9801 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9802 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9803 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9804 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9805 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009806 }
9807 return m_arm_isa != 0;
9808}
9809
9810
Greg Clayton64c84432011-01-21 22:02:52 +00009811bool
9812EmulateInstructionARM::ReadInstruction ()
9813{
9814 bool success = false;
9815 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
9816 if (success)
9817 {
9818 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9819 if (success)
9820 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009821 Context read_inst_context;
9822 read_inst_context.type = eContextReadOpcode;
9823 read_inst_context.SetNoArgs ();
9824
Greg Clayton64c84432011-01-21 22:02:52 +00009825 if (m_inst_cpsr & MASK_CPSR_T)
9826 {
9827 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009828 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009829
9830 if (success)
9831 {
9832 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9833 {
9834 m_inst.opcode_type = eOpcode16;
9835 m_inst.opcode.inst16 = thumb_opcode;
9836 }
9837 else
9838 {
9839 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009840 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009841 }
9842 }
9843 }
9844 else
9845 {
9846 m_inst_mode = eModeARM;
9847 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009848 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009849 }
9850 }
9851 }
9852 if (!success)
9853 {
9854 m_inst_mode = eModeInvalid;
9855 m_inst_pc = LLDB_INVALID_ADDRESS;
9856 }
9857 return success;
9858}
9859
Johnny Chenee9b1f72011-02-09 01:00:31 +00009860uint32_t
9861EmulateInstructionARM::ArchVersion ()
9862{
9863 return m_arm_isa;
9864}
9865
Greg Clayton64c84432011-01-21 22:02:52 +00009866bool
9867EmulateInstructionARM::ConditionPassed ()
9868{
9869 if (m_inst_cpsr == 0)
9870 return false;
9871
9872 const uint32_t cond = CurrentCond ();
9873
9874 if (cond == UINT32_MAX)
9875 return false;
9876
9877 bool result = false;
9878 switch (UnsignedBits(cond, 3, 1))
9879 {
9880 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9881 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9882 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9883 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9884 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9885 case 5:
9886 {
9887 bool n = (m_inst_cpsr & MASK_CPSR_N);
9888 bool v = (m_inst_cpsr & MASK_CPSR_V);
9889 result = n == v;
9890 }
9891 break;
9892 case 6:
9893 {
9894 bool n = (m_inst_cpsr & MASK_CPSR_N);
9895 bool v = (m_inst_cpsr & MASK_CPSR_V);
9896 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
9897 }
9898 break;
9899 case 7:
9900 result = true;
9901 break;
9902 }
9903
9904 if (cond & 1)
9905 result = !result;
9906 return result;
9907}
9908
Johnny Chen9ee056b2011-02-08 00:06:35 +00009909uint32_t
9910EmulateInstructionARM::CurrentCond ()
9911{
9912 switch (m_inst_mode)
9913 {
9914 default:
9915 case eModeInvalid:
9916 break;
9917
9918 case eModeARM:
9919 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
9920
9921 case eModeThumb:
9922 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9923 // 'cond' field of the encoding.
9924 if (m_inst.opcode_type == eOpcode16 &&
9925 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
9926 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
9927 {
9928 return Bits32(m_inst.opcode.inst16, 11, 7);
9929 }
9930 else if (m_inst.opcode_type == eOpcode32 &&
9931 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
9932 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
9933 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
9934 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
9935 {
9936 return Bits32(m_inst.opcode.inst32, 25, 22);
9937 }
9938
9939 return m_it_session.GetCond();
9940 }
9941 return UINT32_MAX; // Return invalid value
9942}
9943
Johnny Chen9ee056b2011-02-08 00:06:35 +00009944bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009945EmulateInstructionARM::InITBlock()
9946{
9947 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9948}
9949
9950bool
9951EmulateInstructionARM::LastInITBlock()
9952{
9953 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9954}
9955
Caroline Ticeb27771d2011-03-03 22:37:46 +00009956bool
9957EmulateInstructionARM::BadMode (uint32_t mode)
9958{
9959
9960 switch (mode)
9961 {
9962 case 16: return false; // '10000'
9963 case 17: return false; // '10001'
9964 case 18: return false; // '10010'
9965 case 19: return false; // '10011'
9966 case 22: return false; // '10110'
9967 case 23: return false; // '10111'
9968 case 27: return false; // '11011'
9969 case 31: return false; // '11111'
9970 default: return true;
9971 }
9972 return true;
9973}
9974
9975bool
9976EmulateInstructionARM::CurrentModeIsPrivileged ()
9977{
9978 uint32_t mode = Bits32 (m_inst_cpsr, 4, 0);
9979
9980 if (BadMode (mode))
9981 return false;
9982
9983 if (mode == 16)
9984 return false;
9985
9986 return true;
9987}
9988
9989void
9990EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
9991{
9992 bool privileged = CurrentModeIsPrivileged();
9993
9994 uint32_t tmp_cpsr = 0;
9995
9996 tmp_cpsr = tmp_cpsr | (Bits32 (m_inst_cpsr, 23, 20) << 20);
9997
9998 if (BitIsSet (bytemask, 3))
9999 {
10000 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
10001 if (affect_execstate)
10002 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
10003 }
10004
10005 if (BitIsSet (bytemask, 2))
10006 {
10007 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
10008 }
10009
10010 if (BitIsSet (bytemask, 1))
10011 {
10012 if (affect_execstate)
10013 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
10014 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
10015 if (privileged)
10016 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
10017 }
10018
10019 if (BitIsSet (bytemask, 0))
10020 {
10021 if (privileged)
10022 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
10023 if (affect_execstate)
10024 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
10025 if (privileged)
10026 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
10027 }
10028
10029 m_inst_cpsr = tmp_cpsr;
10030}
10031
10032
Johnny Chen098ae2d2011-02-12 00:50:05 +000010033bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000010034EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
10035{
10036 addr_t target;
10037
Johnny Chenee9b1f72011-02-09 01:00:31 +000010038 // Check the current instruction set.
10039 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010040 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010041 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000010042 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010043
Johnny Chen9ee056b2011-02-08 00:06:35 +000010044 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010045 return false;
10046
10047 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010048}
10049
10050// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
10051bool
Johnny Chen668b4512011-02-15 21:08:58 +000010052EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010053{
10054 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000010055 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
10056 // we want to record it and issue a WriteRegister callback so the clients
10057 // can track the mode changes accordingly.
10058 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010059
10060 if (BitIsSet(addr, 0))
10061 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010062 if (CurrentInstrSet() != eModeThumb)
10063 {
10064 SelectInstrSet(eModeThumb);
10065 cpsr_changed = true;
10066 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010067 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000010068 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010069 }
10070 else if (BitIsClear(addr, 1))
10071 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010072 if (CurrentInstrSet() != eModeARM)
10073 {
10074 SelectInstrSet(eModeARM);
10075 cpsr_changed = true;
10076 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010077 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000010078 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010079 }
10080 else
10081 return false; // address<1:0> == '10' => UNPREDICTABLE
10082
Johnny Chen0f309db2011-02-09 19:11:32 +000010083 if (cpsr_changed)
10084 {
Johnny Chen558133b2011-02-09 23:59:17 +000010085 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000010086 return false;
10087 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010088 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010089 return false;
10090
10091 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010092}
Greg Clayton64c84432011-01-21 22:02:52 +000010093
Johnny Chenee9b1f72011-02-09 01:00:31 +000010094// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
10095bool
Johnny Chen668b4512011-02-15 21:08:58 +000010096EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000010097{
10098 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000010099 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000010100 else
10101 return BranchWritePC((const Context)context, addr);
10102}
10103
Johnny Chen26863dc2011-02-09 23:43:29 +000010104// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
10105bool
Johnny Chen668b4512011-02-15 21:08:58 +000010106EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000010107{
10108 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000010109 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000010110 else
10111 return BranchWritePC((const Context)context, addr);
10112}
10113
Johnny Chenee9b1f72011-02-09 01:00:31 +000010114EmulateInstructionARM::Mode
10115EmulateInstructionARM::CurrentInstrSet ()
10116{
10117 return m_inst_mode;
10118}
10119
10120// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000010121// ReadInstruction() is performed. This function has a side effect of updating
10122// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000010123bool
10124EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
10125{
Johnny Chen558133b2011-02-09 23:59:17 +000010126 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010127 switch (arm_or_thumb)
10128 {
10129 default:
10130 return false;
10131 eModeARM:
10132 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010133 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010134 break;
10135 eModeThumb:
10136 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010137 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010138 break;
10139 }
10140 return true;
10141}
10142
Johnny Chenef21b592011-02-10 01:52:38 +000010143// This function returns TRUE if the processor currently provides support for
10144// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
10145// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
10146bool
10147EmulateInstructionARM::UnalignedSupport()
10148{
10149 return (ArchVersion() >= ARMv7);
10150}
10151
Johnny Chenbf6ad172011-02-11 01:29:53 +000010152// The main addition and subtraction instructions can produce status information
10153// about both unsigned carry and signed overflow conditions. This status
10154// information can be used to synthesize multi-word additions and subtractions.
10155EmulateInstructionARM::AddWithCarryResult
10156EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
10157{
10158 uint32_t result;
10159 uint8_t carry_out;
10160 uint8_t overflow;
10161
10162 uint64_t unsigned_sum = x + y + carry_in;
10163 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
10164
10165 result = UnsignedBits(unsigned_sum, 31, 0);
10166 carry_out = (result == unsigned_sum ? 0 : 1);
10167 overflow = ((int32_t)result == signed_sum ? 0 : 1);
10168
10169 AddWithCarryResult res = { result, carry_out, overflow };
10170 return res;
10171}
10172
Johnny Chen157b9592011-02-18 21:13:05 +000010173uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000010174EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000010175{
Johnny Chene39f22d2011-02-19 01:36:13 +000010176 uint32_t reg_kind, reg_num;
10177 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000010178 {
Johnny Chene39f22d2011-02-19 01:36:13 +000010179 case SP_REG:
10180 reg_kind = eRegisterKindGeneric;
10181 reg_num = LLDB_REGNUM_GENERIC_SP;
10182 break;
10183 case LR_REG:
10184 reg_kind = eRegisterKindGeneric;
10185 reg_num = LLDB_REGNUM_GENERIC_RA;
10186 break;
10187 case PC_REG:
10188 reg_kind = eRegisterKindGeneric;
10189 reg_num = LLDB_REGNUM_GENERIC_PC;
10190 break;
10191 default:
10192 if (0 <= num && num < SP_REG)
10193 {
10194 reg_kind = eRegisterKindDWARF;
10195 reg_num = dwarf_r0 + num;
10196 }
Johnny Chen157b9592011-02-18 21:13:05 +000010197 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010198 {
10199 assert(0 && "Invalid register number");
10200 *success = false;
10201 return ~0u;
10202 }
10203 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010204 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010205
10206 // Read our register.
10207 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10208
10209 // When executing an ARM instruction , PC reads as the address of the current
10210 // instruction plus 8.
10211 // When executing a Thumb instruction , PC reads as the address of the current
10212 // instruction plus 4.
10213 if (num == 15)
10214 {
10215 if (CurrentInstrSet() == eModeARM)
10216 val += 8;
10217 else
10218 val += 4;
10219 }
Johnny Chen157b9592011-02-18 21:13:05 +000010220
10221 return val;
10222}
10223
Johnny Chenca67d1c2011-02-17 01:35:27 +000010224// Write the result to the ARM core register Rd, and optionally update the
10225// condition flags based on the result.
10226//
10227// This helper method tries to encapsulate the following pseudocode from the
10228// ARM Architecture Reference Manual:
10229//
10230// if d == 15 then // Can only occur for encoding A1
10231// ALUWritePC(result); // setflags is always FALSE here
10232// else
10233// R[d] = result;
10234// if setflags then
10235// APSR.N = result<31>;
10236// APSR.Z = IsZeroBit(result);
10237// APSR.C = carry;
10238// // APSR.V unchanged
10239//
10240// In the above case, the API client does not pass in the overflow arg, which
10241// defaults to ~0u.
10242bool
Johnny Chen10530c22011-02-17 22:37:12 +000010243EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10244 const uint32_t result,
10245 const uint32_t Rd,
10246 bool setflags,
10247 const uint32_t carry,
10248 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010249{
10250 if (Rd == 15)
10251 {
10252 if (!ALUWritePC (context, result))
10253 return false;
10254 }
10255 else
10256 {
Johnny Chena695f952011-02-23 21:24:25 +000010257 uint32_t reg_kind, reg_num;
10258 switch (Rd)
10259 {
10260 case SP_REG:
10261 reg_kind = eRegisterKindGeneric;
10262 reg_num = LLDB_REGNUM_GENERIC_SP;
10263 break;
10264 case LR_REG:
10265 reg_kind = eRegisterKindGeneric;
10266 reg_num = LLDB_REGNUM_GENERIC_RA;
10267 break;
10268 default:
10269 reg_kind = eRegisterKindDWARF;
10270 reg_num = dwarf_r0 + Rd;
10271 }
10272 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010273 return false;
10274 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010275 return WriteFlags (context, result, carry, overflow);
10276 }
10277 return true;
10278}
10279
10280// This helper method tries to encapsulate the following pseudocode from the
10281// ARM Architecture Reference Manual:
10282//
10283// APSR.N = result<31>;
10284// APSR.Z = IsZeroBit(result);
10285// APSR.C = carry;
10286// APSR.V = overflow
10287//
10288// Default arguments can be specified for carry and overflow parameters, which means
10289// not to update the respective flags.
10290bool
10291EmulateInstructionARM::WriteFlags (Context &context,
10292 const uint32_t result,
10293 const uint32_t carry,
10294 const uint32_t overflow)
10295{
10296 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010297 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10298 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010299 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010300 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010301 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010302 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +000010303 if (m_new_inst_cpsr != m_inst_cpsr)
10304 {
10305 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10306 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010307 }
10308 return true;
10309}
10310
Greg Clayton64c84432011-01-21 22:02:52 +000010311bool
10312EmulateInstructionARM::EvaluateInstruction ()
10313{
Johnny Chenc315f862011-02-05 00:46:10 +000010314 // Advance the ITSTATE bits to their values for the next instruction.
10315 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
10316 m_it_session.ITAdvance();
10317
Greg Clayton64c84432011-01-21 22:02:52 +000010318 return false;
10319}