blob: d68184f3bd4feb64e7a0f7b3fd19dc7421dcffdd [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 Ticecc96eb52011-02-17 19:20:40 +00001776 if (!MemUWrite (context, addr, pc + 8, 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 Ticefa172202011-02-11 22:49:54 +00003917 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3918 if (!success)
3919 return false;
3920
Caroline Ticecc96eb52011-02-17 19:20:40 +00003921 if (!MemAWrite (context, address + offset, pc + 8, 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);
4045 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4046 if (!success)
4047 return false;
4048
Caroline Ticecc96eb52011-02-17 19:20:40 +00004049 if (!MemAWrite (context, address + offset, pc + 8, 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);
4199 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4200 if (!success)
4201 return false;
4202
Caroline Ticecc96eb52011-02-17 19:20:40 +00004203 if (!MemAWrite (context, address + offset, pc + 8, 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);
4328 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4329 if (!success)
4330 return false;
4331
Caroline Ticecc96eb52011-02-17 19:20:40 +00004332 if (!MemAWrite (context, address + offset, pc + 8, 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();
4660 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4661 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;
5649 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5650 if (!success)
5651 return false;
5652
5653 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5654 if (add)
5655 offset_addr = base_address + imm32;
5656 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);
6129 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
6130 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);
6533 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
6534 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);
6966 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS,
6967 &success);
6968 if (!success)
6969 return false;
6970 uint64_t base = AlignPC (pc_value);
6971
6972 // address = if add then (base + imm32) else (base - imm32);
6973 addr_t address;
6974 if (add)
6975 address = base + imm32;
6976 else
6977 address = base - imm32;
6978
6979 // R[t] = SignExtend(MemU[address,1], 32);
6980 Register base_reg;
6981 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6982
6983 EmulateInstruction::Context context;
6984 context.type = eContextRegisterLoad;
6985 context.SetRegisterPlusOffset (base_reg, address - base);
6986
6987 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6988 if (!success)
6989 return false;
6990
6991 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6992 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6993 return false;
6994 }
6995 return true;
6996}
6997
Caroline Tice672f3112011-03-01 23:55:59 +00006998// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6999// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7000// shifted left by 0, 1, 2, or 3 bits.
7001bool
7002EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
7003{
7004#if 0
7005 if ConditionPassed() then
7006 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7007 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7008 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7009 address = if index then offset_addr else R[n];
7010 R[t] = SignExtend(MemU[address,1], 32);
7011 if wback then R[n] = offset_addr;
7012#endif
7013
7014 bool success = false;
7015 const uint32_t opcode = OpcodeAsUnsigned (&success);
7016 if (!success)
7017 return false;
7018
7019 if (ConditionPassed ())
7020 {
7021 uint32_t t;
7022 uint32_t n;
7023 uint32_t m;
7024 bool index;
7025 bool add;
7026 bool wback;
7027 ARM_ShifterType shift_t;
7028 uint32_t shift_n;
7029
7030 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7031 switch (encoding)
7032 {
7033 case eEncodingT1:
7034 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7035 t = Bits32 (opcode, 2, 0);
7036 n = Bits32 (opcode, 5, 3);
7037 m = Bits32 (opcode, 8, 6);
7038
7039 // index = TRUE; add = TRUE; wback = FALSE;
7040 index = true;
7041 add = true;
7042 wback = false;
7043
7044 // (shift_t, shift_n) = (SRType_LSL, 0);
7045 shift_t = SRType_LSL;
7046 shift_n = 0;
7047
7048 break;
7049
7050 case eEncodingT2:
7051 // if Rt == ’1111’ then SEE PLI;
7052 // if Rn == ’1111’ then SEE LDRSB (literal);
7053 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7054 t = Bits32 (opcode, 15, 12);
7055 n = Bits32 (opcode, 19, 16);
7056 m = Bits32 (opcode, 3, 0);
7057
7058 // index = TRUE; add = TRUE; wback = FALSE;
7059 index = true;
7060 add = true;
7061 wback = false;
7062
7063 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7064 shift_t = SRType_LSL;
7065 shift_n = Bits32 (opcode, 5, 4);
7066
7067 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7068 if ((t == 13) || BadReg (m))
7069 return false;
7070 break;
7071
7072 case eEncodingA1:
7073 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
7074 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7075 t = Bits32 (opcode, 15, 12);
7076 n = Bits32 (opcode, 19, 16);
7077 m = Bits32 (opcode, 3, 0);
7078
7079 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7080 index = BitIsSet (opcode, 24);
7081 add = BitIsSet (opcode, 23);
7082 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7083
7084 // (shift_t, shift_n) = (SRType_LSL, 0);
7085 shift_t = SRType_LSL;
7086 shift_n = 0;
7087
7088 // if t == 15 || m == 15 then UNPREDICTABLE;
7089 if ((t == 15) || (m == 15))
7090 return false;
7091
7092 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7093 if (wback && ((n == 15) || (n == t)))
7094 return false;
7095 break;
7096
7097 default:
7098 return false;
7099 }
7100
7101 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7102 if (!success)
7103 return false;
7104
7105 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7106 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7107
7108 addr_t offset_addr;
7109 addr_t address;
7110
7111 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7112 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7113 if (!success)
7114 return false;
7115
7116 if (add)
7117 offset_addr = Rn + offset;
7118 else
7119 offset_addr = Rn - offset;
7120
7121 // address = if index then offset_addr else R[n];
7122 if (index)
7123 address = offset_addr;
7124 else
7125 address = Rn;
7126
7127 // R[t] = SignExtend(MemU[address,1], 32);
7128 Register base_reg;
7129 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7130 Register offset_reg;
7131 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7132
7133 EmulateInstruction::Context context;
7134 context.type = eContextRegisterLoad;
7135 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7136
7137 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
7138 if (!success)
7139 return false;
7140
7141 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7142 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7143 return false;
7144
7145 // if wback then R[n] = offset_addr;
7146 if (wback)
7147 {
7148 context.type = eContextAdjustBaseRegister;
7149 context.SetAddress (offset_addr);
7150 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7151 return false;
7152 }
7153 }
7154 return true;
7155}
7156
Caroline Tice78fb5632011-03-02 00:39:42 +00007157// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
7158// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
7159// pre-indexed addressing.
7160bool
7161EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
7162{
7163#if 0
7164 if ConditionPassed() then
7165 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7166 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7167 address = if index then offset_addr else R[n];
7168 data = MemU[address,2];
7169 if wback then R[n] = offset_addr;
7170 if UnalignedSupport() || address<0> = ’0’ then
7171 R[t] = SignExtend(data, 32);
7172 else // Can only apply before ARMv7
7173 R[t] = bits(32) UNKNOWN;
7174#endif
7175
7176 bool success = false;
7177 const uint32_t opcode = OpcodeAsUnsigned (&success);
7178 if (!success)
7179 return false;
7180
7181 if (ConditionPassed())
7182 {
7183 uint32_t t;
7184 uint32_t n;
7185 uint32_t imm32;
7186 bool index;
7187 bool add;
7188 bool wback;
7189
7190 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7191 switch (encoding)
7192 {
7193 case eEncodingT1:
7194 // if Rn == ’1111’ then SEE LDRSH (literal);
7195 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7196 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7197 t = Bits32 (opcode, 15, 12);
7198 n = Bits32 (opcode, 19, 16);
7199 imm32 = Bits32 (opcode, 11, 0);
7200
7201 // index = TRUE; add = TRUE; wback = FALSE;
7202 index = true;
7203 add = true;
7204 wback = false;
7205
7206 // if t == 13 then UNPREDICTABLE;
7207 if (t == 13)
7208 return false;
7209
7210 break;
7211
7212 case eEncodingT2:
7213 // if Rn == ’1111’ then SEE LDRSH (literal);
7214 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
7215 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
7216 // if P == ’0’ && W == ’0’ then UNDEFINED;
7217 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7218 return false;
7219
7220 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7221 t = Bits32 (opcode, 15, 12);
7222 n = Bits32 (opcode, 19, 16);
7223 imm32 = Bits32 (opcode, 7, 0);
7224
7225 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
7226 index = BitIsSet (opcode, 10);
7227 add = BitIsSet (opcode, 9);
7228 wback = BitIsSet (opcode, 8);
7229
7230 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7231 if (BadReg (t) || (wback && (n == t)))
7232 return false;
7233
7234 break;
7235
7236 case eEncodingA1:
7237 {
7238 // if Rn == ’1111’ then SEE LDRSH (literal);
7239 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7240 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7241 t = Bits32 (opcode, 15, 12);
7242 n = Bits32 (opcode, 19, 16);
7243 uint32_t imm4H = Bits32 (opcode, 11,8);
7244 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007245 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007246
7247 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7248 index = BitIsSet (opcode, 24);
7249 add = BitIsSet (opcode, 23);
7250 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7251
7252 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7253 if ((t == 15) || (wback && (n == t)))
7254 return false;
7255
7256 break;
7257 }
7258
7259 default:
7260 return false;
7261 }
7262
7263 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7264 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7265 if (!success)
7266 return false;
7267
7268 addr_t offset_addr;
7269 if (add)
7270 offset_addr = Rn + imm32;
7271 else
7272 offset_addr = Rn - imm32;
7273
7274 // address = if index then offset_addr else R[n];
7275 addr_t address;
7276 if (index)
7277 address = offset_addr;
7278 else
7279 address = Rn;
7280
7281 // data = MemU[address,2];
7282 Register base_reg;
7283 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7284
7285 EmulateInstruction::Context context;
7286 context.type = eContextRegisterLoad;
7287 context.SetRegisterPlusOffset (base_reg, address - Rn);
7288
7289 uint64_t data = MemURead (context, address, 2, 0, &success);
7290 if (!success)
7291 return false;
7292
7293 // if wback then R[n] = offset_addr;
7294 if (wback)
7295 {
7296 context.type = eContextAdjustBaseRegister;
7297 context.SetAddress (offset_addr);
7298 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7299 return false;
7300 }
7301
7302 // if UnalignedSupport() || address<0> = ’0’ then
7303 if (UnalignedSupport() || BitIsClear (address, 0))
7304 {
7305 // R[t] = SignExtend(data, 32);
7306 int64_t signed_data = llvm::SignExtend64<16>(data);
7307 context.type = eContextRegisterLoad;
7308 context.SetRegisterPlusOffset (base_reg, address - Rn);
7309 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7310 return false;
7311 }
7312 else // Can only apply before ARMv7
7313 {
7314 // R[t] = bits(32) UNKNOWN;
7315 WriteBits32Unknown (t);
7316 }
7317 }
7318 return true;
7319}
7320
Caroline Ticed2fac092011-03-02 19:45:34 +00007321// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7322// sign-extends it to from a 32-bit word, and writes it to a register.
7323bool
7324EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
7325{
7326#if 0
7327 if ConditionPassed() then
7328 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7329 base = Align(PC,4);
7330 address = if add then (base + imm32) else (base - imm32);
7331 data = MemU[address,2];
7332 if UnalignedSupport() || address<0> = ’0’ then
7333 R[t] = SignExtend(data, 32);
7334 else // Can only apply before ARMv7
7335 R[t] = bits(32) UNKNOWN;
7336#endif
7337
7338 bool success = false;
7339 const uint32_t opcode = OpcodeAsUnsigned (&success);
7340 if (!success)
7341 return false;
7342
7343 if (ConditionPassed())
7344 {
7345 uint32_t t;
7346 uint32_t imm32;
7347 bool add;
7348
7349 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7350 switch (encoding)
7351 {
7352 case eEncodingT1:
7353 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7354 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7355 t = Bits32 (opcode, 15, 12);
7356 imm32 = Bits32 (opcode, 11, 0);
7357 add = BitIsSet (opcode, 23);
7358
7359 // if t == 13 then UNPREDICTABLE;
7360 if (t == 13)
7361 return false;
7362
7363 break;
7364
7365 case eEncodingA1:
7366 {
7367 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7368 t = Bits32 (opcode, 15, 12);
7369 uint32_t imm4H = Bits32 (opcode, 11, 8);
7370 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007371 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007372 add = BitIsSet (opcode, 23);
7373
7374 // if t == 15 then UNPREDICTABLE;
7375 if (t == 15)
7376 return false;
7377
7378 break;
7379 }
7380 default:
7381 return false;
7382 }
7383
7384 // base = Align(PC,4);
7385 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
7386 if (!success)
7387 return false;
7388
7389 uint64_t base = AlignPC (pc_value);
7390
7391 addr_t address;
7392 // address = if add then (base + imm32) else (base - imm32);
7393 if (add)
7394 address = base + imm32;
7395 else
7396 address = base - imm32;
7397
7398 // data = MemU[address,2];
7399 Register base_reg;
7400 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7401
7402 EmulateInstruction::Context context;
7403 context.type = eContextRegisterLoad;
7404 context.SetRegisterPlusOffset (base_reg, imm32);
7405
7406 uint64_t data = MemURead (context, address, 2, 0, &success);
7407 if (!success)
7408 return false;
7409
7410 // if UnalignedSupport() || address<0> = ’0’ then
7411 if (UnalignedSupport() || BitIsClear (address, 0))
7412 {
7413 // R[t] = SignExtend(data, 32);
7414 int64_t signed_data = llvm::SignExtend64<16>(data);
7415 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7416 return false;
7417 }
7418 else // Can only apply before ARMv7
7419 {
7420 // R[t] = bits(32) UNKNOWN;
7421 WriteBits32Unknown (t);
7422 }
7423 }
7424 return true;
7425}
7426
Caroline Tice291a3e92011-03-02 21:13:44 +00007427// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7428// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7429// shifted left by 0, 1, 2, or 3 bits.
7430bool
7431EmulateInstructionARM::EmulateLDRSHRegister (ARMEncoding encoding)
7432{
7433#if 0
7434 if ConditionPassed() then
7435 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7436 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7437 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7438 address = if index then offset_addr else R[n];
7439 data = MemU[address,2];
7440 if wback then R[n] = offset_addr;
7441 if UnalignedSupport() || address<0> = ’0’ then
7442 R[t] = SignExtend(data, 32);
7443 else // Can only apply before ARMv7
7444 R[t] = bits(32) UNKNOWN;
7445#endif
7446
7447 bool success = false;
7448 const uint32_t opcode = OpcodeAsUnsigned (&success);
7449 if (!success)
7450 return false;
7451
7452 if (ConditionPassed())
7453 {
7454 uint32_t t;
7455 uint32_t n;
7456 uint32_t m;
7457 bool index;
7458 bool add;
7459 bool wback;
7460 ARM_ShifterType shift_t;
7461 uint32_t shift_n;
7462
7463 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7464 switch (encoding)
7465 {
7466 case eEncodingT1:
7467 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7468 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7469 t = Bits32 (opcode, 2, 0);
7470 n = Bits32 (opcode, 5, 3);
7471 m = Bits32 (opcode, 8, 6);
7472
7473 // index = TRUE; add = TRUE; wback = FALSE;
7474 index = true;
7475 add = true;
7476 wback = false;
7477
7478 // (shift_t, shift_n) = (SRType_LSL, 0);
7479 shift_t = SRType_LSL;
7480 shift_n = 0;
7481
7482 break;
7483
7484 case eEncodingT2:
7485 // if Rn == ’1111’ then SEE LDRSH (literal);
7486 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7487 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7488 t = Bits32 (opcode, 15, 12);
7489 n = Bits32 (opcode, 19, 16);
7490 m = Bits32 (opcode, 3, 0);
7491
7492 // index = TRUE; add = TRUE; wback = FALSE;
7493 index = true;
7494 add = true;
7495 wback = false;
7496
7497 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7498 shift_t = SRType_LSL;
7499 shift_n = Bits32 (opcode, 5, 4);
7500
7501 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7502 if ((t == 13) || BadReg (m))
7503 return false;
7504
7505 break;
7506
7507 case eEncodingA1:
7508 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7509 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7510 t = Bits32 (opcode, 15, 12);
7511 n = Bits32 (opcode, 19, 16);
7512 m = Bits32 (opcode, 3, 0);
7513
7514 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7515 index = BitIsSet (opcode, 24);
7516 add = BitIsSet (opcode, 23);
7517 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7518
7519 // (shift_t, shift_n) = (SRType_LSL, 0);
7520 shift_t = SRType_LSL;
7521 shift_n = 0;
7522
7523 // if t == 15 || m == 15 then UNPREDICTABLE;
7524 if ((t == 15) || (m == 15))
7525 return false;
7526
7527 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7528 if (wback && ((n == 15) || (n == t)))
7529 return false;
7530
7531 break;
7532
7533 default:
7534 break;
7535 }
7536
7537 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7538 if (!success)
7539 return false;
7540
7541 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7542 if (!success)
7543 return false;
7544
7545 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7546 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7547
7548 addr_t offset_addr;
7549 addr_t address;
7550
7551 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7552 if (add)
7553 offset_addr = Rn + offset;
7554 else
7555 offset_addr = Rn - offset;
7556
7557 // address = if index then offset_addr else R[n];
7558 if (index)
7559 address = offset_addr;
7560 else
7561 address = Rn;
7562
7563 // data = MemU[address,2];
7564 Register base_reg;
7565 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7566
7567 Register offset_reg;
7568 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7569
7570 EmulateInstruction::Context context;
7571 context.type = eContextRegisterLoad;
7572 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7573
7574 uint64_t data = MemURead (context, address, 2, 0, &success);
7575 if (!success)
7576 return false;
7577
7578 // if wback then R[n] = offset_addr;
7579 if (wback)
7580 {
7581 context.type = eContextAdjustBaseRegister;
7582 context.SetAddress (offset_addr);
7583 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7584 return false;
7585 }
7586
7587 // if UnalignedSupport() || address<0> = ’0’ then
7588 if (UnalignedSupport() || BitIsClear (address, 0))
7589 {
7590 // R[t] = SignExtend(data, 32);
7591 context.type = eContextRegisterLoad;
7592 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7593
7594 int64_t signed_data = llvm::SignExtend64<16>(data);
7595 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7596 return false;
7597 }
7598 else // Can only apply before ARMv7
7599 {
7600 // R[t] = bits(32) UNKNOWN;
7601 WriteBits32Unknown (t);
7602 }
7603 }
7604 return true;
7605}
Caroline Tice6bf65162011-03-03 17:42:58 +00007606
7607// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7608// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7609bool
7610EmulateInstructionARM::EmulateSXTB (ARMEncoding encoding)
7611{
7612#if 0
7613 if ConditionPassed() then
7614 EncodingSpecificOperations();
7615 rotated = ROR(R[m], rotation);
7616 R[d] = SignExtend(rotated<7:0>, 32);
7617#endif
7618
7619 bool success = false;
7620 const uint32_t opcode = OpcodeAsUnsigned (&success);
7621 if (!success)
7622 return false;
7623
7624 if (ConditionPassed())
7625 {
7626 uint32_t d;
7627 uint32_t m;
7628 uint32_t rotation;
7629
7630 // EncodingSpecificOperations();
7631 switch (encoding)
7632 {
7633 case eEncodingT1:
7634 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7635 d = Bits32 (opcode, 2, 0);
7636 m = Bits32 (opcode, 5, 3);
7637 rotation = 0;
7638
7639 break;
7640
7641 case eEncodingT2:
7642 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7643 d = Bits32 (opcode, 11, 8);
7644 m = Bits32 (opcode, 3, 0);
7645 rotation = Bits32 (opcode, 5, 4) << 3;
7646
7647 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7648 if (BadReg (d) || BadReg (m))
7649 return false;
7650
7651 break;
7652
7653 case eEncodingA1:
7654 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7655 d = Bits32 (opcode, 15, 12);
7656 m = Bits32 (opcode, 3, 0);
7657 rotation = Bits32 (opcode, 11, 10) << 3;
7658
7659 // if d == 15 || m == 15 then UNPREDICTABLE;
7660 if ((d == 15) || (m == 15))
7661 return false;
7662
7663 break;
7664
7665 default:
7666 return false;
7667 }
7668
Caroline Tice868198b2011-03-03 18:04:49 +00007669 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7670 if (!success)
7671 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007672
7673 // rotated = ROR(R[m], rotation);
7674 uint64_t rotated = ROR (Rm, rotation);
7675
7676 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007677 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007678
7679 Register source_reg;
7680 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7681
7682 EmulateInstruction::Context context;
7683 context.type = eContextRegisterLoad;
7684 context.SetRegister (source_reg);
7685
Caroline Tice8ce96d92011-03-03 18:27:17 +00007686 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007687 return false;
7688 }
7689 return true;
7690}
Caroline Tice291a3e92011-03-02 21:13:44 +00007691
Caroline Tice868198b2011-03-03 18:04:49 +00007692// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7693// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7694bool
7695EmulateInstructionARM::EmulateSXTH (ARMEncoding encoding)
7696{
7697#if 0
7698 if ConditionPassed() then
7699 EncodingSpecificOperations();
7700 rotated = ROR(R[m], rotation);
7701 R[d] = SignExtend(rotated<15:0>, 32);
7702#endif
7703
7704 bool success = false;
7705 const uint32_t opcode = OpcodeAsUnsigned (&success);
7706 if (!success)
7707 return false;
7708
7709 if (ConditionPassed())
7710 {
7711 uint32_t d;
7712 uint32_t m;
7713 uint32_t rotation;
7714
7715 // EncodingSpecificOperations();
7716 switch (encoding)
7717 {
7718 case eEncodingT1:
7719 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7720 d = Bits32 (opcode, 2, 0);
7721 m = Bits32 (opcode, 5, 3);
7722 rotation = 0;
7723
7724 break;
7725
7726 case eEncodingT2:
7727 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7728 d = Bits32 (opcode, 11, 8);
7729 m = Bits32 (opcode, 3, 0);
7730 rotation = Bits32 (opcode, 5, 4) << 3;
7731
7732 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7733 if (BadReg (d) || BadReg (m))
7734 return false;
7735
7736 break;
7737
7738 case eEncodingA1:
7739 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7740 d = Bits32 (opcode, 15, 12);
7741 m = Bits32 (opcode, 3, 0);
7742 rotation = Bits32 (opcode, 11, 10) << 3;
7743
7744 // if d == 15 || m == 15 then UNPREDICTABLE;
7745 if ((d == 15) || (m == 15))
7746 return false;
7747
7748 break;
7749
7750 default:
7751 return false;
7752 }
7753
7754 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7755 if (!success)
7756 return false;
7757
7758 // rotated = ROR(R[m], rotation);
7759 uint64_t rotated = ROR (Rm, rotation);
7760
7761 // R[d] = SignExtend(rotated<15:0>, 32);
7762 Register source_reg;
7763 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7764
7765 EmulateInstruction::Context context;
7766 context.type = eContextRegisterLoad;
7767 context.SetRegister (source_reg);
7768
Caroline Tice8ce96d92011-03-03 18:27:17 +00007769 int64_t data = llvm::SignExtend64<16> (rotated);
7770 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007771 return false;
7772 }
7773
7774 return true;
7775}
7776
Caroline Tice8ce96d92011-03-03 18:27:17 +00007777// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7778// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7779bool
7780EmulateInstructionARM::EmulateUXTB (ARMEncoding encoding)
7781{
7782#if 0
7783 if ConditionPassed() then
7784 EncodingSpecificOperations();
7785 rotated = ROR(R[m], rotation);
7786 R[d] = ZeroExtend(rotated<7:0>, 32);
7787#endif
7788
7789 bool success = false;
7790 const uint32_t opcode = OpcodeAsUnsigned (&success);
7791 if (!success)
7792 return false;
7793
7794 if (ConditionPassed())
7795 {
7796 uint32_t d;
7797 uint32_t m;
7798 uint32_t rotation;
7799
7800 // EncodingSpecificOperations();
7801 switch (encoding)
7802 {
7803 case eEncodingT1:
7804 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7805 d = Bits32 (opcode, 2, 0);
7806 m = Bits32 (opcode, 5, 3);
7807 rotation = 0;
7808
7809 break;
7810
7811 case eEncodingT2:
7812 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7813 d = Bits32 (opcode, 11, 8);
7814 m = Bits32 (opcode, 3, 0);
7815 rotation = Bits32 (opcode, 5, 4) << 3;
7816
7817 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7818 if (BadReg (d) || BadReg (m))
7819 return false;
7820
7821 break;
7822
7823 case eEncodingA1:
7824 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7825 d = Bits32 (opcode, 15, 12);
7826 m = Bits32 (opcode, 3, 0);
7827 rotation = Bits32 (opcode, 11, 10) << 3;
7828
7829 // if d == 15 || m == 15 then UNPREDICTABLE;
7830 if ((d == 15) || (m == 15))
7831 return false;
7832
7833 break;
7834
7835 default:
7836 return false;
7837 }
7838
7839 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7840 if (!success)
7841 return false;
7842
7843 // rotated = ROR(R[m], rotation);
7844 uint64_t rotated = ROR (Rm, rotation);
7845
7846 // R[d] = ZeroExtend(rotated<7:0>, 32);
7847 Register source_reg;
7848 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7849
7850 EmulateInstruction::Context context;
7851 context.type = eContextRegisterLoad;
7852 context.SetRegister (source_reg);
7853
7854 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7855 return false;
7856 }
7857 return true;
7858}
7859
Caroline Tice11555f22011-03-03 18:48:58 +00007860// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7861// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7862bool
7863EmulateInstructionARM::EmulateUXTH (ARMEncoding encoding)
7864{
7865#if 0
7866 if ConditionPassed() then
7867 EncodingSpecificOperations();
7868 rotated = ROR(R[m], rotation);
7869 R[d] = ZeroExtend(rotated<15:0>, 32);
7870#endif
7871
7872 bool success = false;
7873 const uint32_t opcode = OpcodeAsUnsigned (&success);
7874 if (!success)
7875 return false;
7876
7877 if (ConditionPassed ())
7878 {
7879 uint32_t d;
7880 uint32_t m;
7881 uint32_t rotation;
7882
7883 switch (encoding)
7884 {
7885 case eEncodingT1:
7886 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7887 d = Bits32 (opcode, 2, 0);
7888 m = Bits32 (opcode, 5, 3);
7889 rotation = 0;
7890
7891 break;
7892
7893 case eEncodingT2:
7894 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7895 d = Bits32 (opcode, 11, 8);
7896 m = Bits32 (opcode, 3, 0);
7897 rotation = Bits32 (opcode, 5, 4) << 3;
7898
7899 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7900 if (BadReg (d) || BadReg (m))
7901 return false;
7902
7903 break;
7904
7905 case eEncodingA1:
7906 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7907 d = Bits32 (opcode, 15, 12);
7908 m = Bits32 (opcode, 3, 0);
7909 rotation = Bits32 (opcode, 11, 10) << 3;
7910
7911 // if d == 15 || m == 15 then UNPREDICTABLE;
7912 if ((d == 15) || (m == 15))
7913 return false;
7914
7915 break;
7916
7917 default:
7918 return false;
7919 }
7920
7921 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7922 if (!success)
7923 return false;
7924
7925 // rotated = ROR(R[m], rotation);
7926 uint64_t rotated = ROR (Rm, rotation);
7927
7928 // R[d] = ZeroExtend(rotated<15:0>, 32);
7929 Register source_reg;
7930 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7931
7932 EmulateInstruction::Context context;
7933 context.type = eContextRegisterLoad;
7934 context.SetRegister (source_reg);
7935
7936 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7937 return false;
7938 }
7939 return true;
7940}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007941
7942// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7943// word respectively.
7944bool
7945EmulateInstructionARM::EmulateRFE (ARMEncoding encoding)
7946{
7947#if 0
7948 if ConditionPassed() then
7949 EncodingSpecificOperations();
7950 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7951 UNPREDICTABLE;
7952 else
7953 address = if increment then R[n] else R[n]-8;
7954 if wordhigher then address = address+4;
7955 CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
7956 BranchWritePC(MemA[address,4]);
7957 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7958#endif
7959
7960 bool success = false;
7961 const uint32_t opcode = OpcodeAsUnsigned (&success);
7962 if (!success)
7963 return false;
7964
7965 if (ConditionPassed())
7966 {
7967 uint32_t n;
7968 bool wback;
7969 bool increment;
7970 bool wordhigher;
7971
7972 // EncodingSpecificOperations();
7973 switch (encoding)
7974 {
7975 case eEncodingT1:
7976 // n = UInt(Rn); wback = (W == ’1’); increment = FALSE; wordhigher = FALSE;
7977 n = Bits32 (opcode, 19, 16);
7978 wback = BitIsSet (opcode, 21);
7979 increment = false;
7980 wordhigher = false;
7981
7982 // if n == 15 then UNPREDICTABLE;
7983 if (n == 15)
7984 return false;
7985
7986 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7987 if (InITBlock() && !LastInITBlock())
7988 return false;
7989
7990 break;
7991
7992 case eEncodingT2:
7993 // n = UInt(Rn); wback = (W == ’1’); increment = TRUE; wordhigher = FALSE;
7994 n = Bits32 (opcode, 19, 16);
7995 wback = BitIsSet (opcode, 21);
7996 increment = true;
7997 wordhigher = false;
7998
7999 // if n == 15 then UNPREDICTABLE;
8000 if (n == 15)
8001 return false;
8002
8003 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8004 if (InITBlock() && !LastInITBlock())
8005 return false;
8006
8007 break;
8008
8009 case eEncodingA1:
8010 // n = UInt(Rn);
8011 n = Bits32 (opcode, 19, 16);
8012
8013 // wback = (W == ’1’); inc = (U == ’1’); wordhigher = (P == U);
8014 wback = BitIsSet (opcode, 21);
8015 increment = BitIsSet (opcode, 23);
8016 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
8017
8018 // if n == 15 then UNPREDICTABLE;
8019 if (n == 15)
8020 return false;
8021
8022 break;
8023
8024 default:
8025 return false;
8026 }
8027
8028 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8029 if (!CurrentModeIsPrivileged ())
8030 // UNPREDICTABLE;
8031 return false;
8032 else
8033 {
8034 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8035 if (!success)
8036 return false;
8037
8038 addr_t address;
8039 // address = if increment then R[n] else R[n]-8;
8040 if (increment)
8041 address = Rn;
8042 else
8043 address = Rn - 8;
8044
8045 // if wordhigher then address = address+4;
8046 if (wordhigher)
8047 address = address + 4;
8048
8049 // CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
8050 Register base_reg;
8051 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
8052
8053 EmulateInstruction::Context context;
8054 context.type = eContextReturnFromException;
8055 context.SetRegisterPlusOffset (base_reg, address - Rn);
8056
8057 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
8058 if (!success)
8059 return false;
8060
8061 CPSRWriteByInstr (data, 15, true);
8062
8063 // BranchWritePC(MemA[address,4]);
8064 uint64_t data2 = MemARead (context, address, 4, 0, &success);
8065 if (!success)
8066 return false;
8067
8068 BranchWritePC (context, data2);
8069
8070 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8071 if (wback)
8072 {
8073 context.type = eContextAdjustBaseRegister;
8074 if (increment)
8075 {
8076 context.SetOffset (8);
8077 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
8078 return false;
8079 }
8080 else
8081 {
8082 context.SetOffset (-8);
8083 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
8084 return false;
8085 }
8086 } // if wback
8087 }
8088 } // if ConditionPassed()
8089 return true;
8090}
Caroline Tice11555f22011-03-03 18:48:58 +00008091
Johnny Chen2115b412011-02-21 23:42:44 +00008092// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
8093// and writes the result to the destination register. It can optionally update the condition flags based on
8094// the result.
8095bool
8096EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
8097{
8098#if 0
8099 // ARM pseudo code...
8100 if ConditionPassed() then
8101 EncodingSpecificOperations();
8102 result = R[n] EOR imm32;
8103 if d == 15 then // Can only occur for ARM encoding
8104 ALUWritePC(result); // setflags is always FALSE here
8105 else
8106 R[d] = result;
8107 if setflags then
8108 APSR.N = result<31>;
8109 APSR.Z = IsZeroBit(result);
8110 APSR.C = carry;
8111 // APSR.V unchanged
8112#endif
8113
8114 bool success = false;
8115 const uint32_t opcode = OpcodeAsUnsigned (&success);
8116 if (!success)
8117 return false;
8118
8119 if (ConditionPassed())
8120 {
8121 uint32_t Rd, Rn;
8122 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8123 bool setflags;
8124 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8125 switch (encoding)
8126 {
8127 case eEncodingT1:
8128 Rd = Bits32(opcode, 11, 8);
8129 Rn = Bits32(opcode, 19, 16);
8130 setflags = BitIsSet(opcode, 20);
8131 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8132 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8133 if (Rd == 15 && setflags)
8134 return EmulateTEQImm(eEncodingT1);
8135 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8136 return false;
8137 break;
8138 case eEncodingA1:
8139 Rd = Bits32(opcode, 15, 12);
8140 Rn = Bits32(opcode, 19, 16);
8141 setflags = BitIsSet(opcode, 20);
8142 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8143 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8144 // TODO: Emulate SUBS PC, LR and related instructions.
8145 if (Rd == 15 && setflags)
8146 return false;
8147 break;
8148 default:
8149 return false;
8150 }
8151
8152 // Read the first operand.
8153 uint32_t val1 = ReadCoreReg(Rn, &success);
8154 if (!success)
8155 return false;
8156
8157 uint32_t result = val1 ^ imm32;
8158
8159 EmulateInstruction::Context context;
8160 context.type = EmulateInstruction::eContextImmediate;
8161 context.SetNoArgs ();
8162
8163 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8164 return false;
8165 }
8166 return true;
8167}
8168
8169// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
8170// optionally-shifted register value, and writes the result to the destination register.
8171// It can optionally update the condition flags based on the result.
8172bool
8173EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
8174{
8175#if 0
8176 // ARM pseudo code...
8177 if ConditionPassed() then
8178 EncodingSpecificOperations();
8179 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8180 result = R[n] EOR shifted;
8181 if d == 15 then // Can only occur for ARM encoding
8182 ALUWritePC(result); // setflags is always FALSE here
8183 else
8184 R[d] = result;
8185 if setflags then
8186 APSR.N = result<31>;
8187 APSR.Z = IsZeroBit(result);
8188 APSR.C = carry;
8189 // APSR.V unchanged
8190#endif
8191
8192 bool success = false;
8193 const uint32_t opcode = OpcodeAsUnsigned (&success);
8194 if (!success)
8195 return false;
8196
8197 if (ConditionPassed())
8198 {
8199 uint32_t Rd, Rn, Rm;
8200 ARM_ShifterType shift_t;
8201 uint32_t shift_n; // the shift applied to the value read from Rm
8202 bool setflags;
8203 uint32_t carry;
8204 switch (encoding)
8205 {
8206 case eEncodingT1:
8207 Rd = Rn = Bits32(opcode, 2, 0);
8208 Rm = Bits32(opcode, 5, 3);
8209 setflags = !InITBlock();
8210 shift_t = SRType_LSL;
8211 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008212 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008213 case eEncodingT2:
8214 Rd = Bits32(opcode, 11, 8);
8215 Rn = Bits32(opcode, 19, 16);
8216 Rm = Bits32(opcode, 3, 0);
8217 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008218 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8219 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008220 if (Rd == 15 && setflags)
8221 return EmulateTEQReg(eEncodingT1);
8222 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8223 return false;
8224 break;
8225 case eEncodingA1:
8226 Rd = Bits32(opcode, 15, 12);
8227 Rn = Bits32(opcode, 19, 16);
8228 Rm = Bits32(opcode, 3, 0);
8229 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008230 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008231 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8232 // TODO: Emulate SUBS PC, LR and related instructions.
8233 if (Rd == 15 && setflags)
8234 return false;
8235 break;
8236 default:
8237 return false;
8238 }
8239
8240 // Read the first operand.
8241 uint32_t val1 = ReadCoreReg(Rn, &success);
8242 if (!success)
8243 return false;
8244
8245 // Read the second operand.
8246 uint32_t val2 = ReadCoreReg(Rm, &success);
8247 if (!success)
8248 return false;
8249
8250 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8251 uint32_t result = val1 ^ shifted;
8252
8253 EmulateInstruction::Context context;
8254 context.type = EmulateInstruction::eContextImmediate;
8255 context.SetNoArgs ();
8256
8257 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8258 return false;
8259 }
8260 return true;
8261}
8262
Johnny Chen7c5234d2011-02-18 23:41:11 +00008263// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8264// writes the result to the destination register. It can optionally update the condition flags based
8265// on the result.
8266bool
8267EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
8268{
8269#if 0
8270 // ARM pseudo code...
8271 if ConditionPassed() then
8272 EncodingSpecificOperations();
8273 result = R[n] OR imm32;
8274 if d == 15 then // Can only occur for ARM encoding
8275 ALUWritePC(result); // setflags is always FALSE here
8276 else
8277 R[d] = result;
8278 if setflags then
8279 APSR.N = result<31>;
8280 APSR.Z = IsZeroBit(result);
8281 APSR.C = carry;
8282 // APSR.V unchanged
8283#endif
8284
8285 bool success = false;
8286 const uint32_t opcode = OpcodeAsUnsigned (&success);
8287 if (!success)
8288 return false;
8289
8290 if (ConditionPassed())
8291 {
8292 uint32_t Rd, Rn;
8293 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8294 bool setflags;
8295 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8296 switch (encoding)
8297 {
8298 case eEncodingT1:
8299 Rd = Bits32(opcode, 11, 8);
8300 Rn = Bits32(opcode, 19, 16);
8301 setflags = BitIsSet(opcode, 20);
8302 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8303 // if Rn == ‘1111’ then SEE MOV (immediate);
8304 if (Rn == 15)
8305 return EmulateMOVRdImm(eEncodingT2);
8306 if (BadReg(Rd) || Rn == 13)
8307 return false;
8308 break;
8309 case eEncodingA1:
8310 Rd = Bits32(opcode, 15, 12);
8311 Rn = Bits32(opcode, 19, 16);
8312 setflags = BitIsSet(opcode, 20);
8313 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8314 // TODO: Emulate SUBS PC, LR and related instructions.
8315 if (Rd == 15 && setflags)
8316 return false;
8317 break;
8318 default:
8319 return false;
8320 }
8321
8322 // Read the first operand.
8323 uint32_t val1 = ReadCoreReg(Rn, &success);
8324 if (!success)
8325 return false;
8326
8327 uint32_t result = val1 | imm32;
8328
8329 EmulateInstruction::Context context;
8330 context.type = EmulateInstruction::eContextImmediate;
8331 context.SetNoArgs ();
8332
8333 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8334 return false;
8335 }
8336 return true;
8337}
8338
8339// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8340// value, and writes the result to the destination register. It can optionally update the condition flags based
8341// on the result.
8342bool
8343EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
8344{
8345#if 0
8346 // ARM pseudo code...
8347 if ConditionPassed() then
8348 EncodingSpecificOperations();
8349 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8350 result = R[n] OR shifted;
8351 if d == 15 then // Can only occur for ARM encoding
8352 ALUWritePC(result); // setflags is always FALSE here
8353 else
8354 R[d] = result;
8355 if setflags then
8356 APSR.N = result<31>;
8357 APSR.Z = IsZeroBit(result);
8358 APSR.C = carry;
8359 // APSR.V unchanged
8360#endif
8361
8362 bool success = false;
8363 const uint32_t opcode = OpcodeAsUnsigned (&success);
8364 if (!success)
8365 return false;
8366
8367 if (ConditionPassed())
8368 {
8369 uint32_t Rd, Rn, Rm;
8370 ARM_ShifterType shift_t;
8371 uint32_t shift_n; // the shift applied to the value read from Rm
8372 bool setflags;
8373 uint32_t carry;
8374 switch (encoding)
8375 {
8376 case eEncodingT1:
8377 Rd = Rn = Bits32(opcode, 2, 0);
8378 Rm = Bits32(opcode, 5, 3);
8379 setflags = !InITBlock();
8380 shift_t = SRType_LSL;
8381 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008382 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008383 case eEncodingT2:
8384 Rd = Bits32(opcode, 11, 8);
8385 Rn = Bits32(opcode, 19, 16);
8386 Rm = Bits32(opcode, 3, 0);
8387 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008388 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8389 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008390 if (Rn == 15)
8391 return EmulateMOVRdRm(eEncodingT3);
8392 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8393 return false;
8394 break;
8395 case eEncodingA1:
8396 Rd = Bits32(opcode, 15, 12);
8397 Rn = Bits32(opcode, 19, 16);
8398 Rm = Bits32(opcode, 3, 0);
8399 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008400 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008401 // TODO: Emulate SUBS PC, LR and related instructions.
8402 if (Rd == 15 && setflags)
8403 return false;
8404 break;
8405 default:
8406 return false;
8407 }
8408
8409 // Read the first operand.
8410 uint32_t val1 = ReadCoreReg(Rn, &success);
8411 if (!success)
8412 return false;
8413
8414 // Read the second operand.
8415 uint32_t val2 = ReadCoreReg(Rm, &success);
8416 if (!success)
8417 return false;
8418
8419 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008420 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008421
8422 EmulateInstruction::Context context;
8423 context.type = EmulateInstruction::eContextImmediate;
8424 context.SetNoArgs ();
8425
8426 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8427 return false;
8428 }
8429 return true;
8430}
8431
Johnny Chened32e7c2011-02-22 23:42:58 +00008432// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8433// the destination register. It can optionally update the condition flags based on the result.
8434bool
8435EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
8436{
8437#if 0
8438 // ARM pseudo code...
8439 if ConditionPassed() then
8440 EncodingSpecificOperations();
8441 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8442 if d == 15 then // Can only occur for ARM encoding
8443 ALUWritePC(result); // setflags is always FALSE here
8444 else
8445 R[d] = result;
8446 if setflags then
8447 APSR.N = result<31>;
8448 APSR.Z = IsZeroBit(result);
8449 APSR.C = carry;
8450 APSR.V = overflow;
8451#endif
8452
8453 bool success = false;
8454 const uint32_t opcode = OpcodeAsUnsigned (&success);
8455 if (!success)
8456 return false;
8457
8458 uint32_t Rd; // the destination register
8459 uint32_t Rn; // the first operand
8460 bool setflags;
8461 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8462 switch (encoding) {
8463 case eEncodingT1:
8464 Rd = Bits32(opcode, 2, 0);
8465 Rn = Bits32(opcode, 5, 3);
8466 setflags = !InITBlock();
8467 imm32 = 0;
8468 break;
8469 case eEncodingT2:
8470 Rd = Bits32(opcode, 11, 8);
8471 Rn = Bits32(opcode, 19, 16);
8472 setflags = BitIsSet(opcode, 20);
8473 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8474 if (BadReg(Rd) || BadReg(Rn))
8475 return false;
8476 break;
8477 case eEncodingA1:
8478 Rd = Bits32(opcode, 15, 12);
8479 Rn = Bits32(opcode, 19, 16);
8480 setflags = BitIsSet(opcode, 20);
8481 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8482 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8483 // TODO: Emulate SUBS PC, LR and related instructions.
8484 if (Rd == 15 && setflags)
8485 return false;
8486 break;
8487 default:
8488 return false;
8489 }
8490 // Read the register value from the operand register Rn.
8491 uint32_t reg_val = ReadCoreReg(Rn, &success);
8492 if (!success)
8493 return false;
8494
8495 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8496
8497 EmulateInstruction::Context context;
8498 context.type = EmulateInstruction::eContextImmediate;
8499 context.SetNoArgs ();
8500
8501 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8502 return false;
8503
8504 return true;
8505}
8506
8507// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8508// result to the destination register. It can optionally update the condition flags based on the result.
8509bool
8510EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
8511{
8512#if 0
8513 // ARM pseudo code...
8514 if ConditionPassed() then
8515 EncodingSpecificOperations();
8516 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8517 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8518 if d == 15 then // Can only occur for ARM encoding
8519 ALUWritePC(result); // setflags is always FALSE here
8520 else
8521 R[d] = result;
8522 if setflags then
8523 APSR.N = result<31>;
8524 APSR.Z = IsZeroBit(result);
8525 APSR.C = carry;
8526 APSR.V = overflow;
8527#endif
8528
8529 bool success = false;
8530 const uint32_t opcode = OpcodeAsUnsigned (&success);
8531 if (!success)
8532 return false;
8533
8534 uint32_t Rd; // the destination register
8535 uint32_t Rn; // the first operand
8536 uint32_t Rm; // the second operand
8537 bool setflags;
8538 ARM_ShifterType shift_t;
8539 uint32_t shift_n; // the shift applied to the value read from Rm
8540 switch (encoding) {
8541 case eEncodingT1:
8542 Rd = Bits32(opcode, 11, 8);
8543 Rn = Bits32(opcode, 19, 16);
8544 Rm = Bits32(opcode, 3, 0);
8545 setflags = BitIsSet(opcode, 20);
8546 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8547 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8548 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8549 return false;
8550 break;
8551 case eEncodingA1:
8552 Rd = Bits32(opcode, 15, 12);
8553 Rn = Bits32(opcode, 19, 16);
8554 Rm = Bits32(opcode, 3, 0);
8555 setflags = BitIsSet(opcode, 20);
8556 shift_n = DecodeImmShiftARM(opcode, shift_t);
8557 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8558 // TODO: Emulate SUBS PC, LR and related instructions.
8559 if (Rd == 15 && setflags)
8560 return false;
8561 break;
8562 default:
8563 return false;
8564 }
8565 // Read the register value from register Rn.
8566 uint32_t val1 = ReadCoreReg(Rn, &success);
8567 if (!success)
8568 return false;
8569
8570 // Read the register value from register Rm.
8571 uint32_t val2 = ReadCoreReg(Rm, &success);
8572 if (!success)
8573 return false;
8574
8575 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8576 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8577
8578 EmulateInstruction::Context context;
8579 context.type = EmulateInstruction::eContextImmediate;
8580 context.SetNoArgs();
8581 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8582 return false;
8583
8584 return true;
8585}
8586
Johnny Chen90e607b2011-02-23 00:07:09 +00008587// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8588// an immediate value, and writes the result to the destination register. It can optionally update the condition
8589// flags based on the result.
8590bool
8591EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
8592{
8593#if 0
8594 // ARM pseudo code...
8595 if ConditionPassed() then
8596 EncodingSpecificOperations();
8597 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8598 if d == 15 then
8599 ALUWritePC(result); // setflags is always FALSE here
8600 else
8601 R[d] = result;
8602 if setflags then
8603 APSR.N = result<31>;
8604 APSR.Z = IsZeroBit(result);
8605 APSR.C = carry;
8606 APSR.V = overflow;
8607#endif
8608
8609 bool success = false;
8610 const uint32_t opcode = OpcodeAsUnsigned (&success);
8611 if (!success)
8612 return false;
8613
8614 uint32_t Rd; // the destination register
8615 uint32_t Rn; // the first operand
8616 bool setflags;
8617 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8618 switch (encoding) {
8619 case eEncodingA1:
8620 Rd = Bits32(opcode, 15, 12);
8621 Rn = Bits32(opcode, 19, 16);
8622 setflags = BitIsSet(opcode, 20);
8623 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8624 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8625 // TODO: Emulate SUBS PC, LR and related instructions.
8626 if (Rd == 15 && setflags)
8627 return false;
8628 break;
8629 default:
8630 return false;
8631 }
8632 // Read the register value from the operand register Rn.
8633 uint32_t reg_val = ReadCoreReg(Rn, &success);
8634 if (!success)
8635 return false;
8636
8637 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8638
8639 EmulateInstruction::Context context;
8640 context.type = EmulateInstruction::eContextImmediate;
8641 context.SetNoArgs ();
8642
8643 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8644 return false;
8645
8646 return true;
8647}
8648
8649// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8650// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8651// condition flags based on the result.
8652bool
8653EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
8654{
8655#if 0
8656 // ARM pseudo code...
8657 if ConditionPassed() then
8658 EncodingSpecificOperations();
8659 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8660 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8661 if d == 15 then
8662 ALUWritePC(result); // setflags is always FALSE here
8663 else
8664 R[d] = result;
8665 if setflags then
8666 APSR.N = result<31>;
8667 APSR.Z = IsZeroBit(result);
8668 APSR.C = carry;
8669 APSR.V = overflow;
8670#endif
8671
8672 bool success = false;
8673 const uint32_t opcode = OpcodeAsUnsigned (&success);
8674 if (!success)
8675 return false;
8676
8677 uint32_t Rd; // the destination register
8678 uint32_t Rn; // the first operand
8679 uint32_t Rm; // the second operand
8680 bool setflags;
8681 ARM_ShifterType shift_t;
8682 uint32_t shift_n; // the shift applied to the value read from Rm
8683 switch (encoding) {
8684 case eEncodingA1:
8685 Rd = Bits32(opcode, 15, 12);
8686 Rn = Bits32(opcode, 19, 16);
8687 Rm = Bits32(opcode, 3, 0);
8688 setflags = BitIsSet(opcode, 20);
8689 shift_n = DecodeImmShiftARM(opcode, shift_t);
8690 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8691 // TODO: Emulate SUBS PC, LR and related instructions.
8692 if (Rd == 15 && setflags)
8693 return false;
8694 break;
8695 default:
8696 return false;
8697 }
8698 // Read the register value from register Rn.
8699 uint32_t val1 = ReadCoreReg(Rn, &success);
8700 if (!success)
8701 return false;
8702
8703 // Read the register value from register Rm.
8704 uint32_t val2 = ReadCoreReg(Rm, &success);
8705 if (!success)
8706 return false;
8707
8708 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8709 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8710
8711 EmulateInstruction::Context context;
8712 context.type = EmulateInstruction::eContextImmediate;
8713 context.SetNoArgs();
8714 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8715 return false;
8716
8717 return true;
8718}
8719
Johnny Chen9b381772011-02-23 01:01:21 +00008720// Subtract with Carry (immediate) subtracts an immediate value and the value of
8721// NOT (Carry flag) from a register value, and writes the result to the destination register.
8722// It can optionally update the condition flags based on the result.
8723bool
8724EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
8725{
8726#if 0
8727 // ARM pseudo code...
8728 if ConditionPassed() then
8729 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008730 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008731 if d == 15 then // Can only occur for ARM encoding
8732 ALUWritePC(result); // setflags is always FALSE here
8733 else
8734 R[d] = result;
8735 if setflags then
8736 APSR.N = result<31>;
8737 APSR.Z = IsZeroBit(result);
8738 APSR.C = carry;
8739 APSR.V = overflow;
8740#endif
8741
8742 bool success = false;
8743 const uint32_t opcode = OpcodeAsUnsigned (&success);
8744 if (!success)
8745 return false;
8746
8747 uint32_t Rd; // the destination register
8748 uint32_t Rn; // the first operand
8749 bool setflags;
8750 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8751 switch (encoding) {
8752 case eEncodingT1:
8753 Rd = Bits32(opcode, 11, 8);
8754 Rn = Bits32(opcode, 19, 16);
8755 setflags = BitIsSet(opcode, 20);
8756 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8757 if (BadReg(Rd) || BadReg(Rn))
8758 return false;
8759 break;
8760 case eEncodingA1:
8761 Rd = Bits32(opcode, 15, 12);
8762 Rn = Bits32(opcode, 19, 16);
8763 setflags = BitIsSet(opcode, 20);
8764 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8765 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8766 // TODO: Emulate SUBS PC, LR and related instructions.
8767 if (Rd == 15 && setflags)
8768 return false;
8769 break;
8770 default:
8771 return false;
8772 }
8773 // Read the register value from the operand register Rn.
8774 uint32_t reg_val = ReadCoreReg(Rn, &success);
8775 if (!success)
8776 return false;
8777
8778 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8779
8780 EmulateInstruction::Context context;
8781 context.type = EmulateInstruction::eContextImmediate;
8782 context.SetNoArgs ();
8783
8784 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8785 return false;
8786
8787 return true;
8788}
8789
8790// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8791// NOT (Carry flag) from a register value, and writes the result to the destination register.
8792// It can optionally update the condition flags based on the result.
8793bool
8794EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8795{
8796#if 0
8797 // ARM pseudo code...
8798 if ConditionPassed() then
8799 EncodingSpecificOperations();
8800 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8801 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8802 if d == 15 then // Can only occur for ARM encoding
8803 ALUWritePC(result); // setflags is always FALSE here
8804 else
8805 R[d] = result;
8806 if setflags then
8807 APSR.N = result<31>;
8808 APSR.Z = IsZeroBit(result);
8809 APSR.C = carry;
8810 APSR.V = overflow;
8811#endif
8812
8813 bool success = false;
8814 const uint32_t opcode = OpcodeAsUnsigned (&success);
8815 if (!success)
8816 return false;
8817
8818 uint32_t Rd; // the destination register
8819 uint32_t Rn; // the first operand
8820 uint32_t Rm; // the second operand
8821 bool setflags;
8822 ARM_ShifterType shift_t;
8823 uint32_t shift_n; // the shift applied to the value read from Rm
8824 switch (encoding) {
8825 case eEncodingT1:
8826 Rd = Rn = Bits32(opcode, 2, 0);
8827 Rm = Bits32(opcode, 5, 3);
8828 setflags = !InITBlock();
8829 shift_t = SRType_LSL;
8830 shift_n = 0;
8831 break;
8832 case eEncodingT2:
8833 Rd = Bits32(opcode, 11, 8);
8834 Rn = Bits32(opcode, 19, 16);
8835 Rm = Bits32(opcode, 3, 0);
8836 setflags = BitIsSet(opcode, 20);
8837 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8838 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8839 return false;
8840 break;
8841 case eEncodingA1:
8842 Rd = Bits32(opcode, 15, 12);
8843 Rn = Bits32(opcode, 19, 16);
8844 Rm = Bits32(opcode, 3, 0);
8845 setflags = BitIsSet(opcode, 20);
8846 shift_n = DecodeImmShiftARM(opcode, shift_t);
8847 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8848 // TODO: Emulate SUBS PC, LR and related instructions.
8849 if (Rd == 15 && setflags)
8850 return false;
8851 break;
8852 default:
8853 return false;
8854 }
8855 // Read the register value from register Rn.
8856 uint32_t val1 = ReadCoreReg(Rn, &success);
8857 if (!success)
8858 return false;
8859
8860 // Read the register value from register Rm.
8861 uint32_t val2 = ReadCoreReg(Rm, &success);
8862 if (!success)
8863 return false;
8864
8865 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8866 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8867
8868 EmulateInstruction::Context context;
8869 context.type = EmulateInstruction::eContextImmediate;
8870 context.SetNoArgs();
8871 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8872 return false;
8873
8874 return true;
8875}
8876
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008877// This instruction subtracts an immediate value from a register value, and writes the result
8878// to the destination register. It can optionally update the condition flags based on the result.
8879bool
8880EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8881{
8882#if 0
8883 // ARM pseudo code...
8884 if ConditionPassed() then
8885 EncodingSpecificOperations();
8886 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8887 R[d] = result;
8888 if setflags then
8889 APSR.N = result<31>;
8890 APSR.Z = IsZeroBit(result);
8891 APSR.C = carry;
8892 APSR.V = overflow;
8893#endif
8894
8895 bool success = false;
8896 const uint32_t opcode = OpcodeAsUnsigned (&success);
8897 if (!success)
8898 return false;
8899
8900 uint32_t Rd; // the destination register
8901 uint32_t Rn; // the first operand
8902 bool setflags;
8903 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8904 switch (encoding) {
8905 case eEncodingT1:
8906 Rd = Bits32(opcode, 2, 0);
8907 Rn = Bits32(opcode, 5, 3);
8908 setflags = !InITBlock();
8909 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8910 break;
8911 case eEncodingT2:
8912 Rd = Rn = Bits32(opcode, 10, 8);
8913 setflags = !InITBlock();
8914 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8915 break;
8916 case eEncodingT3:
8917 Rd = Bits32(opcode, 11, 8);
8918 Rn = Bits32(opcode, 19, 16);
8919 setflags = BitIsSet(opcode, 20);
8920 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8921
8922 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8923 if (Rd == 15 && setflags)
8924 return EmulateCMPImm(eEncodingT2);
8925
8926 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8927 if (Rn == 13)
8928 return EmulateSUBSPImm(eEncodingT2);
8929
8930 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8931 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8932 return false;
8933 break;
8934 case eEncodingT4:
8935 Rd = Bits32(opcode, 11, 8);
8936 Rn = Bits32(opcode, 19, 16);
8937 setflags = BitIsSet(opcode, 20);
8938 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8939
8940 // if Rn == '1111' then SEE ADR;
8941 if (Rn == 15)
8942 return EmulateADR(eEncodingT2);
8943
8944 // if Rn == '1101' then SEE SUB (SP minus immediate);
8945 if (Rn == 13)
8946 return EmulateSUBSPImm(eEncodingT3);
8947
8948 if (BadReg(Rd))
8949 return false;
8950 break;
8951 default:
8952 return false;
8953 }
8954 // Read the register value from the operand register Rn.
8955 uint32_t reg_val = ReadCoreReg(Rn, &success);
8956 if (!success)
8957 return false;
8958
8959 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8960
8961 EmulateInstruction::Context context;
8962 context.type = EmulateInstruction::eContextImmediate;
8963 context.SetNoArgs ();
8964
8965 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8966 return false;
8967
8968 return true;
8969}
8970
8971// This instruction subtracts an immediate value from a register value, and writes the result
8972// to the destination register. It can optionally update the condition flags based on the result.
8973bool
8974EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
8975{
8976#if 0
8977 // ARM pseudo code...
8978 if ConditionPassed() then
8979 EncodingSpecificOperations();
8980 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8981 if d == 15 then
8982 ALUWritePC(result); // setflags is always FALSE here
8983 else
8984 R[d] = result;
8985 if setflags then
8986 APSR.N = result<31>;
8987 APSR.Z = IsZeroBit(result);
8988 APSR.C = carry;
8989 APSR.V = overflow;
8990#endif
8991
8992 bool success = false;
8993 const uint32_t opcode = OpcodeAsUnsigned (&success);
8994 if (!success)
8995 return false;
8996
8997 uint32_t Rd; // the destination register
8998 uint32_t Rn; // the first operand
8999 bool setflags;
9000 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
9001 switch (encoding) {
9002 case eEncodingA1:
9003 Rd = Bits32(opcode, 15, 12);
9004 Rn = Bits32(opcode, 19, 16);
9005 setflags = BitIsSet(opcode, 20);
9006 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9007
9008 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
9009 if (Rn == 15 && !setflags)
9010 return EmulateADR(eEncodingA2);
9011
9012 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
9013 if (Rn == 13)
9014 return EmulateSUBSPImm(eEncodingA1);
9015
9016 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
9017 // TODO: Emulate SUBS PC, LR and related instructions.
9018 if (Rd == 15 && setflags)
9019 return false;
9020 break;
9021 default:
9022 return false;
9023 }
9024 // Read the register value from the operand register Rn.
9025 uint32_t reg_val = ReadCoreReg(Rn, &success);
9026 if (!success)
9027 return false;
9028
9029 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9030
9031 EmulateInstruction::Context context;
9032 context.type = EmulateInstruction::eContextImmediate;
9033 context.SetNoArgs ();
9034
9035 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
9036 return false;
9037
9038 return true;
9039}
9040
Johnny Chen2115b412011-02-21 23:42:44 +00009041// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
9042// immediate value. It updates the condition flags based on the result, and discards the result.
9043bool
9044EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
9045{
9046#if 0
9047 // ARM pseudo code...
9048 if ConditionPassed() then
9049 EncodingSpecificOperations();
9050 result = R[n] EOR imm32;
9051 APSR.N = result<31>;
9052 APSR.Z = IsZeroBit(result);
9053 APSR.C = carry;
9054 // APSR.V unchanged
9055#endif
9056
9057 bool success = false;
9058 const uint32_t opcode = OpcodeAsUnsigned (&success);
9059 if (!success)
9060 return false;
9061
9062 if (ConditionPassed())
9063 {
9064 uint32_t Rn;
9065 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9066 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9067 switch (encoding)
9068 {
9069 case eEncodingT1:
9070 Rn = Bits32(opcode, 19, 16);
9071 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9072 if (BadReg(Rn))
9073 return false;
9074 break;
9075 case eEncodingA1:
9076 Rn = Bits32(opcode, 19, 16);
9077 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9078 break;
9079 default:
9080 return false;
9081 }
9082
9083 // Read the first operand.
9084 uint32_t val1 = ReadCoreReg(Rn, &success);
9085 if (!success)
9086 return false;
9087
9088 uint32_t result = val1 ^ imm32;
9089
9090 EmulateInstruction::Context context;
9091 context.type = EmulateInstruction::eContextImmediate;
9092 context.SetNoArgs ();
9093
9094 if (!WriteFlags(context, result, carry))
9095 return false;
9096 }
9097 return true;
9098}
9099
9100// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
9101// optionally-shifted register value. It updates the condition flags based on the result, and discards
9102// the result.
9103bool
9104EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
9105{
9106#if 0
9107 // ARM pseudo code...
9108 if ConditionPassed() then
9109 EncodingSpecificOperations();
9110 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9111 result = R[n] EOR shifted;
9112 APSR.N = result<31>;
9113 APSR.Z = IsZeroBit(result);
9114 APSR.C = carry;
9115 // APSR.V unchanged
9116#endif
9117
9118 bool success = false;
9119 const uint32_t opcode = OpcodeAsUnsigned (&success);
9120 if (!success)
9121 return false;
9122
9123 if (ConditionPassed())
9124 {
9125 uint32_t Rn, Rm;
9126 ARM_ShifterType shift_t;
9127 uint32_t shift_n; // the shift applied to the value read from Rm
9128 uint32_t carry;
9129 switch (encoding)
9130 {
9131 case eEncodingT1:
9132 Rn = Bits32(opcode, 19, 16);
9133 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009134 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009135 if (BadReg(Rn) || BadReg(Rm))
9136 return false;
9137 break;
9138 case eEncodingA1:
9139 Rn = Bits32(opcode, 19, 16);
9140 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009141 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00009142 break;
9143 default:
9144 return false;
9145 }
9146
9147 // Read the first operand.
9148 uint32_t val1 = ReadCoreReg(Rn, &success);
9149 if (!success)
9150 return false;
9151
9152 // Read the second operand.
9153 uint32_t val2 = ReadCoreReg(Rm, &success);
9154 if (!success)
9155 return false;
9156
9157 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9158 uint32_t result = val1 ^ shifted;
9159
9160 EmulateInstruction::Context context;
9161 context.type = EmulateInstruction::eContextImmediate;
9162 context.SetNoArgs ();
9163
9164 if (!WriteFlags(context, result, carry))
9165 return false;
9166 }
9167 return true;
9168}
9169
Johnny Chende3cce32011-02-21 21:24:49 +00009170// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
9171// It updates the condition flags based on the result, and discards the result.
9172bool
9173EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
9174{
9175#if 0
9176 // ARM pseudo code...
9177 if ConditionPassed() then
9178 EncodingSpecificOperations();
9179 result = R[n] AND imm32;
9180 APSR.N = result<31>;
9181 APSR.Z = IsZeroBit(result);
9182 APSR.C = carry;
9183 // APSR.V unchanged
9184#endif
9185
9186 bool success = false;
9187 const uint32_t opcode = OpcodeAsUnsigned (&success);
9188 if (!success)
9189 return false;
9190
9191 if (ConditionPassed())
9192 {
9193 uint32_t Rn;
9194 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9195 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9196 switch (encoding)
9197 {
9198 case eEncodingT1:
9199 Rn = Bits32(opcode, 19, 16);
9200 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9201 if (BadReg(Rn))
9202 return false;
9203 break;
9204 case eEncodingA1:
9205 Rn = Bits32(opcode, 19, 16);
9206 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9207 break;
9208 default:
9209 return false;
9210 }
9211
9212 // Read the first operand.
9213 uint32_t val1 = ReadCoreReg(Rn, &success);
9214 if (!success)
9215 return false;
9216
9217 uint32_t result = val1 & imm32;
9218
9219 EmulateInstruction::Context context;
9220 context.type = EmulateInstruction::eContextImmediate;
9221 context.SetNoArgs ();
9222
9223 if (!WriteFlags(context, result, carry))
9224 return false;
9225 }
9226 return true;
9227}
9228
9229// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9230// It updates the condition flags based on the result, and discards the result.
9231bool
9232EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
9233{
9234#if 0
9235 // ARM pseudo code...
9236 if ConditionPassed() then
9237 EncodingSpecificOperations();
9238 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9239 result = R[n] AND shifted;
9240 APSR.N = result<31>;
9241 APSR.Z = IsZeroBit(result);
9242 APSR.C = carry;
9243 // APSR.V unchanged
9244#endif
9245
9246 bool success = false;
9247 const uint32_t opcode = OpcodeAsUnsigned (&success);
9248 if (!success)
9249 return false;
9250
9251 if (ConditionPassed())
9252 {
9253 uint32_t Rn, Rm;
9254 ARM_ShifterType shift_t;
9255 uint32_t shift_n; // the shift applied to the value read from Rm
9256 uint32_t carry;
9257 switch (encoding)
9258 {
9259 case eEncodingT1:
9260 Rn = Bits32(opcode, 2, 0);
9261 Rm = Bits32(opcode, 5, 3);
9262 shift_t = SRType_LSL;
9263 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009264 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009265 case eEncodingT2:
9266 Rn = Bits32(opcode, 19, 16);
9267 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009268 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009269 if (BadReg(Rn) || BadReg(Rm))
9270 return false;
9271 break;
9272 case eEncodingA1:
9273 Rn = Bits32(opcode, 19, 16);
9274 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009275 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009276 break;
9277 default:
9278 return false;
9279 }
9280
9281 // Read the first operand.
9282 uint32_t val1 = ReadCoreReg(Rn, &success);
9283 if (!success)
9284 return false;
9285
9286 // Read the second operand.
9287 uint32_t val2 = ReadCoreReg(Rm, &success);
9288 if (!success)
9289 return false;
9290
9291 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9292 uint32_t result = val1 & shifted;
9293
9294 EmulateInstruction::Context context;
9295 context.type = EmulateInstruction::eContextImmediate;
9296 context.SetNoArgs ();
9297
9298 if (!WriteFlags(context, result, carry))
9299 return false;
9300 }
9301 return true;
9302}
9303
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009304EmulateInstructionARM::ARMOpcode*
9305EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009306{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009307 static ARMOpcode
9308 g_arm_opcodes[] =
9309 {
9310 //----------------------------------------------------------------------
9311 // Prologue instructions
9312 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009313
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009314 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009315 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9316 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009317
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009318 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009319 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009320 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009321 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009322 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9323 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009324 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009325
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009326 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009327 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009328
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009329 // push one register
9330 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00009331 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009332
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009333 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009334 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9335 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009336
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009337 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009338 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009339 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009340
Johnny Chen9f687722011-02-18 00:02:28 +00009341 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9342 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009343 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009344 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9345
9346 //----------------------------------------------------------------------
9347 // Supervisor Call (previously Software Interrupt)
9348 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009349 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9350
9351 //----------------------------------------------------------------------
9352 // Branch instructions
9353 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009354 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009355 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9356 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9357 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9358 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009359 // for example, "bx lr"
9360 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009361 // bxj
9362 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009363
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009364 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009365 // Data-processing instructions
9366 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009367 // adc (immediate)
9368 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9369 // adc (register)
9370 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009371 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009372 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009373 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009374 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009375 // adr
9376 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9377 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009378 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009379 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009380 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009381 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009382 // bic (immediate)
9383 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9384 // bic (register)
9385 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009386 // eor (immediate)
9387 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9388 // eor (register)
9389 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009390 // orr (immediate)
9391 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9392 // orr (register)
9393 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009394 // rsb (immediate)
9395 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9396 // rsb (register)
9397 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009398 // rsc (immediate)
9399 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9400 // rsc (register)
9401 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009402 // sbc (immediate)
9403 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9404 // sbc (register)
9405 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009406 // sub (immediate, ARM)
9407 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009408 // sub (sp minus immediate)
9409 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009410 // teq (immediate)
9411 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9412 // teq (register)
9413 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009414 // tst (immediate)
9415 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9416 // tst (register)
9417 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9418
9419
Johnny Chen01d61572011-02-25 00:23:25 +00009420 // mov (register)
9421 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009422 // mvn (immediate)
9423 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9424 // mvn (register)
9425 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009426 // cmn (immediate)
9427 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9428 // cmn (register)
9429 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009430 // cmp (immediate)
9431 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9432 // cmp (register)
9433 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009434 // asr (immediate)
9435 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009436 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009437 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009438 // lsl (immediate)
9439 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9440 // lsl (register)
9441 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9442 // lsr (immediate)
9443 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9444 // lsr (register)
9445 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009446 // rrx is a special case encoding of ror (immediate)
9447 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9448 // ror (immediate)
9449 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9450 // ror (register)
9451 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009452 // mul
9453 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009454
9455 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009456 // Load instructions
9457 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009458 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009459 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009460 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009461 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009462 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009463 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009464 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009465 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009466 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009467 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009468 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009469 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009470 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009471 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009472 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9473 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009474
9475 //----------------------------------------------------------------------
9476 // Store instructions
9477 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009478 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009479 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009480 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009481 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009482 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009483 { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009484
Caroline Tice6bf65162011-03-03 17:42:58 +00009485 //----------------------------------------------------------------------
9486 // Other instructions
9487 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009488 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009489 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009490 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009491 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9492 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009493
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009494 };
9495 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9496
9497 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9498 {
9499 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9500 return &g_arm_opcodes[i];
9501 }
9502 return NULL;
9503}
Greg Clayton64c84432011-01-21 22:02:52 +00009504
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009505
9506EmulateInstructionARM::ARMOpcode*
9507EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009508{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009509
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009510 static ARMOpcode
9511 g_thumb_opcodes[] =
9512 {
9513 //----------------------------------------------------------------------
9514 // Prologue instructions
9515 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009516
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009517 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009518 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9519 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9520 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009521
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009522 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009523 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009524 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009525 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009526 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009527 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009528
Johnny Chen864a8e82011-02-18 00:07:39 +00009529 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009530 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009531
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009532 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009533 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009534 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009535 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9536 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009537
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009538 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009539 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9540 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009541
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009542 //----------------------------------------------------------------------
9543 // Epilogue instructions
9544 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009545
Johnny Chen864a8e82011-02-18 00:07:39 +00009546 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009547 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9548 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9549 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009550 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9551 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009552
9553 //----------------------------------------------------------------------
9554 // Supervisor Call (previously Software Interrupt)
9555 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009556 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9557
9558 //----------------------------------------------------------------------
9559 // If Then makes up to four following instructions conditional.
9560 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009561 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9562
9563 //----------------------------------------------------------------------
9564 // Branch instructions
9565 //----------------------------------------------------------------------
9566 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9567 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009568 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009569 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009570 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009571 // J1 == J2 == 1
9572 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9573 // J1 == J2 == 1
9574 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9575 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009576 // for example, "bx lr"
9577 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009578 // bxj
9579 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009580 // compare and branch
9581 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009582 // table branch byte
9583 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9584 // table branch halfword
9585 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009586
9587 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009588 // Data-processing instructions
9589 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009590 // adc (immediate)
9591 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9592 // adc (register)
9593 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9594 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9595 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009596 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009597 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009598 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009599 // adr
9600 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9601 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9602 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009603 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009604 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009605 // and (register)
9606 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9607 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009608 // bic (immediate)
9609 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9610 // bic (register)
9611 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9612 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009613 // eor (immediate)
9614 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9615 // eor (register)
9616 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9617 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009618 // orr (immediate)
9619 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9620 // orr (register)
9621 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9622 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009623 // rsb (immediate)
9624 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9625 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9626 // rsb (register)
9627 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009628 // sbc (immediate)
9629 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9630 // sbc (register)
9631 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9632 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009633 // add (immediate, Thumb)
9634 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9635 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9636 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9637 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009638 // sub (immediate, Thumb)
9639 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9640 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9641 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9642 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009643 // sub (sp minus immediate)
9644 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9645 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009646 // teq (immediate)
9647 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9648 // teq (register)
9649 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009650 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009651 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009652 // tst (register)
9653 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9654 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9655
Johnny Chen7c5234d2011-02-18 23:41:11 +00009656
Johnny Chen338bf542011-02-10 19:29:03 +00009657 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009658 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009659 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009660 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009661 // mov{s}<c>.w <Rd>, <Rm>
9662 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009663 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009664 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9665 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009666 // mvn (immediate)
9667 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9668 // mvn (register)
9669 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9670 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009671 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009672 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009673 // cmn (register)
9674 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009675 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009676 // cmp (immediate)
9677 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009678 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009679 // cmp (register) (Rn and Rm both from r0-r7)
9680 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9681 // cmp (register) (Rn and Rm not both from r0-r7)
9682 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009683 // asr (immediate)
9684 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009685 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009686 // asr (register)
9687 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9688 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009689 // lsl (immediate)
9690 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9691 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9692 // lsl (register)
9693 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9694 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9695 // lsr (immediate)
9696 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9697 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9698 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009699 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009700 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009701 // rrx is a special case encoding of ror (immediate)
9702 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9703 // ror (immediate)
9704 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9705 // ror (register)
9706 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9707 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009708 // mul
9709 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9710 // mul
9711 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009712
Johnny Chen26863dc2011-02-09 23:43:29 +00009713 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009714 // Load instructions
9715 //----------------------------------------------------------------------
9716 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009717 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009718 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00009719 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9720 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009721 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009722 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9723 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009724 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9725 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9726 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009727 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009728 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9729 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009730 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9731 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9732 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009733 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009734 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9735 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009736 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9737 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009738 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009739 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9740 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009741 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9742 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009743 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009744 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9745 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009746
9747 //----------------------------------------------------------------------
9748 // Store instructions
9749 //----------------------------------------------------------------------
9750 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009751 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009752 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009753 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9754 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9755 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9756 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9757 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9758 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9759 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9760 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009761 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
Caroline Tice8ce836d2011-03-16 22:46:55 +00009762 { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
9763 { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009764
9765 //----------------------------------------------------------------------
9766 // Other instructions
9767 //----------------------------------------------------------------------
9768 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009769 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9770 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009771 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9772 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009773 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9774 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009775 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9776 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9777 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009778
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009779 };
9780
9781 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9782 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9783 {
9784 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9785 return &g_thumb_opcodes[i];
9786 }
9787 return NULL;
9788}
Greg Clayton64c84432011-01-21 22:02:52 +00009789
Greg Clayton31e2a382011-01-30 20:03:56 +00009790bool
Greg Clayton395fc332011-02-15 21:59:32 +00009791EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009792{
9793 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009794 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009795 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009796 {
Greg Clayton395fc332011-02-15 21:59:32 +00009797 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9798 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9799 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9800 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9801 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9802 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9803 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9804 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9805 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9806 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009807 }
9808 return m_arm_isa != 0;
9809}
9810
9811
Greg Clayton64c84432011-01-21 22:02:52 +00009812bool
9813EmulateInstructionARM::ReadInstruction ()
9814{
9815 bool success = false;
9816 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
9817 if (success)
9818 {
9819 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9820 if (success)
9821 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009822 Context read_inst_context;
9823 read_inst_context.type = eContextReadOpcode;
9824 read_inst_context.SetNoArgs ();
9825
Greg Clayton64c84432011-01-21 22:02:52 +00009826 if (m_inst_cpsr & MASK_CPSR_T)
9827 {
9828 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009829 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009830
9831 if (success)
9832 {
9833 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9834 {
9835 m_inst.opcode_type = eOpcode16;
9836 m_inst.opcode.inst16 = thumb_opcode;
9837 }
9838 else
9839 {
9840 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009841 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009842 }
9843 }
9844 }
9845 else
9846 {
9847 m_inst_mode = eModeARM;
9848 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009849 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009850 }
9851 }
9852 }
9853 if (!success)
9854 {
9855 m_inst_mode = eModeInvalid;
9856 m_inst_pc = LLDB_INVALID_ADDRESS;
9857 }
9858 return success;
9859}
9860
Johnny Chenee9b1f72011-02-09 01:00:31 +00009861uint32_t
9862EmulateInstructionARM::ArchVersion ()
9863{
9864 return m_arm_isa;
9865}
9866
Greg Clayton64c84432011-01-21 22:02:52 +00009867bool
9868EmulateInstructionARM::ConditionPassed ()
9869{
9870 if (m_inst_cpsr == 0)
9871 return false;
9872
9873 const uint32_t cond = CurrentCond ();
9874
9875 if (cond == UINT32_MAX)
9876 return false;
9877
9878 bool result = false;
9879 switch (UnsignedBits(cond, 3, 1))
9880 {
9881 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9882 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9883 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9884 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9885 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9886 case 5:
9887 {
9888 bool n = (m_inst_cpsr & MASK_CPSR_N);
9889 bool v = (m_inst_cpsr & MASK_CPSR_V);
9890 result = n == v;
9891 }
9892 break;
9893 case 6:
9894 {
9895 bool n = (m_inst_cpsr & MASK_CPSR_N);
9896 bool v = (m_inst_cpsr & MASK_CPSR_V);
9897 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
9898 }
9899 break;
9900 case 7:
9901 result = true;
9902 break;
9903 }
9904
9905 if (cond & 1)
9906 result = !result;
9907 return result;
9908}
9909
Johnny Chen9ee056b2011-02-08 00:06:35 +00009910uint32_t
9911EmulateInstructionARM::CurrentCond ()
9912{
9913 switch (m_inst_mode)
9914 {
9915 default:
9916 case eModeInvalid:
9917 break;
9918
9919 case eModeARM:
9920 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
9921
9922 case eModeThumb:
9923 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9924 // 'cond' field of the encoding.
9925 if (m_inst.opcode_type == eOpcode16 &&
9926 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
9927 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
9928 {
9929 return Bits32(m_inst.opcode.inst16, 11, 7);
9930 }
9931 else if (m_inst.opcode_type == eOpcode32 &&
9932 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
9933 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
9934 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
9935 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
9936 {
9937 return Bits32(m_inst.opcode.inst32, 25, 22);
9938 }
9939
9940 return m_it_session.GetCond();
9941 }
9942 return UINT32_MAX; // Return invalid value
9943}
9944
Johnny Chen9ee056b2011-02-08 00:06:35 +00009945bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009946EmulateInstructionARM::InITBlock()
9947{
9948 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9949}
9950
9951bool
9952EmulateInstructionARM::LastInITBlock()
9953{
9954 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9955}
9956
Caroline Ticeb27771d2011-03-03 22:37:46 +00009957bool
9958EmulateInstructionARM::BadMode (uint32_t mode)
9959{
9960
9961 switch (mode)
9962 {
9963 case 16: return false; // '10000'
9964 case 17: return false; // '10001'
9965 case 18: return false; // '10010'
9966 case 19: return false; // '10011'
9967 case 22: return false; // '10110'
9968 case 23: return false; // '10111'
9969 case 27: return false; // '11011'
9970 case 31: return false; // '11111'
9971 default: return true;
9972 }
9973 return true;
9974}
9975
9976bool
9977EmulateInstructionARM::CurrentModeIsPrivileged ()
9978{
9979 uint32_t mode = Bits32 (m_inst_cpsr, 4, 0);
9980
9981 if (BadMode (mode))
9982 return false;
9983
9984 if (mode == 16)
9985 return false;
9986
9987 return true;
9988}
9989
9990void
9991EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
9992{
9993 bool privileged = CurrentModeIsPrivileged();
9994
9995 uint32_t tmp_cpsr = 0;
9996
9997 tmp_cpsr = tmp_cpsr | (Bits32 (m_inst_cpsr, 23, 20) << 20);
9998
9999 if (BitIsSet (bytemask, 3))
10000 {
10001 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
10002 if (affect_execstate)
10003 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
10004 }
10005
10006 if (BitIsSet (bytemask, 2))
10007 {
10008 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
10009 }
10010
10011 if (BitIsSet (bytemask, 1))
10012 {
10013 if (affect_execstate)
10014 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
10015 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
10016 if (privileged)
10017 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
10018 }
10019
10020 if (BitIsSet (bytemask, 0))
10021 {
10022 if (privileged)
10023 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
10024 if (affect_execstate)
10025 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
10026 if (privileged)
10027 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
10028 }
10029
10030 m_inst_cpsr = tmp_cpsr;
10031}
10032
10033
Johnny Chen098ae2d2011-02-12 00:50:05 +000010034bool
Johnny Chen9ee056b2011-02-08 00:06:35 +000010035EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
10036{
10037 addr_t target;
10038
Johnny Chenee9b1f72011-02-09 01:00:31 +000010039 // Check the current instruction set.
10040 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010041 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010042 else
Johnny Chen9ee056b2011-02-08 00:06:35 +000010043 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010044
Johnny Chen9ee056b2011-02-08 00:06:35 +000010045 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010046 return false;
10047
10048 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010049}
10050
10051// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
10052bool
Johnny Chen668b4512011-02-15 21:08:58 +000010053EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +000010054{
10055 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +000010056 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
10057 // we want to record it and issue a WriteRegister callback so the clients
10058 // can track the mode changes accordingly.
10059 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010060
10061 if (BitIsSet(addr, 0))
10062 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010063 if (CurrentInstrSet() != eModeThumb)
10064 {
10065 SelectInstrSet(eModeThumb);
10066 cpsr_changed = true;
10067 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010068 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +000010069 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010070 }
10071 else if (BitIsClear(addr, 1))
10072 {
Johnny Chen0f309db2011-02-09 19:11:32 +000010073 if (CurrentInstrSet() != eModeARM)
10074 {
10075 SelectInstrSet(eModeARM);
10076 cpsr_changed = true;
10077 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010078 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +000010079 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +000010080 }
10081 else
10082 return false; // address<1:0> == '10' => UNPREDICTABLE
10083
Johnny Chen0f309db2011-02-09 19:11:32 +000010084 if (cpsr_changed)
10085 {
Johnny Chen558133b2011-02-09 23:59:17 +000010086 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +000010087 return false;
10088 }
Johnny Chen9ee056b2011-02-08 00:06:35 +000010089 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +000010090 return false;
10091
10092 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +000010093}
Greg Clayton64c84432011-01-21 22:02:52 +000010094
Johnny Chenee9b1f72011-02-09 01:00:31 +000010095// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
10096bool
Johnny Chen668b4512011-02-15 21:08:58 +000010097EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +000010098{
10099 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +000010100 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +000010101 else
10102 return BranchWritePC((const Context)context, addr);
10103}
10104
Johnny Chen26863dc2011-02-09 23:43:29 +000010105// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
10106bool
Johnny Chen668b4512011-02-15 21:08:58 +000010107EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +000010108{
10109 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +000010110 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +000010111 else
10112 return BranchWritePC((const Context)context, addr);
10113}
10114
Johnny Chenee9b1f72011-02-09 01:00:31 +000010115EmulateInstructionARM::Mode
10116EmulateInstructionARM::CurrentInstrSet ()
10117{
10118 return m_inst_mode;
10119}
10120
10121// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +000010122// ReadInstruction() is performed. This function has a side effect of updating
10123// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +000010124bool
10125EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
10126{
Johnny Chen558133b2011-02-09 23:59:17 +000010127 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010128 switch (arm_or_thumb)
10129 {
10130 default:
10131 return false;
10132 eModeARM:
10133 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010134 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010135 break;
10136 eModeThumb:
10137 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +000010138 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +000010139 break;
10140 }
10141 return true;
10142}
10143
Johnny Chenef21b592011-02-10 01:52:38 +000010144// This function returns TRUE if the processor currently provides support for
10145// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
10146// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
10147bool
10148EmulateInstructionARM::UnalignedSupport()
10149{
10150 return (ArchVersion() >= ARMv7);
10151}
10152
Johnny Chenbf6ad172011-02-11 01:29:53 +000010153// The main addition and subtraction instructions can produce status information
10154// about both unsigned carry and signed overflow conditions. This status
10155// information can be used to synthesize multi-word additions and subtractions.
10156EmulateInstructionARM::AddWithCarryResult
10157EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
10158{
10159 uint32_t result;
10160 uint8_t carry_out;
10161 uint8_t overflow;
10162
10163 uint64_t unsigned_sum = x + y + carry_in;
10164 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
10165
10166 result = UnsignedBits(unsigned_sum, 31, 0);
10167 carry_out = (result == unsigned_sum ? 0 : 1);
10168 overflow = ((int32_t)result == signed_sum ? 0 : 1);
10169
10170 AddWithCarryResult res = { result, carry_out, overflow };
10171 return res;
10172}
10173
Johnny Chen157b9592011-02-18 21:13:05 +000010174uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +000010175EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +000010176{
Johnny Chene39f22d2011-02-19 01:36:13 +000010177 uint32_t reg_kind, reg_num;
10178 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +000010179 {
Johnny Chene39f22d2011-02-19 01:36:13 +000010180 case SP_REG:
10181 reg_kind = eRegisterKindGeneric;
10182 reg_num = LLDB_REGNUM_GENERIC_SP;
10183 break;
10184 case LR_REG:
10185 reg_kind = eRegisterKindGeneric;
10186 reg_num = LLDB_REGNUM_GENERIC_RA;
10187 break;
10188 case PC_REG:
10189 reg_kind = eRegisterKindGeneric;
10190 reg_num = LLDB_REGNUM_GENERIC_PC;
10191 break;
10192 default:
10193 if (0 <= num && num < SP_REG)
10194 {
10195 reg_kind = eRegisterKindDWARF;
10196 reg_num = dwarf_r0 + num;
10197 }
Johnny Chen157b9592011-02-18 21:13:05 +000010198 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010199 {
10200 assert(0 && "Invalid register number");
10201 *success = false;
10202 return ~0u;
10203 }
10204 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010205 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010206
10207 // Read our register.
10208 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10209
10210 // When executing an ARM instruction , PC reads as the address of the current
10211 // instruction plus 8.
10212 // When executing a Thumb instruction , PC reads as the address of the current
10213 // instruction plus 4.
10214 if (num == 15)
10215 {
10216 if (CurrentInstrSet() == eModeARM)
10217 val += 8;
10218 else
10219 val += 4;
10220 }
Johnny Chen157b9592011-02-18 21:13:05 +000010221
10222 return val;
10223}
10224
Johnny Chenca67d1c2011-02-17 01:35:27 +000010225// Write the result to the ARM core register Rd, and optionally update the
10226// condition flags based on the result.
10227//
10228// This helper method tries to encapsulate the following pseudocode from the
10229// ARM Architecture Reference Manual:
10230//
10231// if d == 15 then // Can only occur for encoding A1
10232// ALUWritePC(result); // setflags is always FALSE here
10233// else
10234// R[d] = result;
10235// if setflags then
10236// APSR.N = result<31>;
10237// APSR.Z = IsZeroBit(result);
10238// APSR.C = carry;
10239// // APSR.V unchanged
10240//
10241// In the above case, the API client does not pass in the overflow arg, which
10242// defaults to ~0u.
10243bool
Johnny Chen10530c22011-02-17 22:37:12 +000010244EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10245 const uint32_t result,
10246 const uint32_t Rd,
10247 bool setflags,
10248 const uint32_t carry,
10249 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010250{
10251 if (Rd == 15)
10252 {
10253 if (!ALUWritePC (context, result))
10254 return false;
10255 }
10256 else
10257 {
Johnny Chena695f952011-02-23 21:24:25 +000010258 uint32_t reg_kind, reg_num;
10259 switch (Rd)
10260 {
10261 case SP_REG:
10262 reg_kind = eRegisterKindGeneric;
10263 reg_num = LLDB_REGNUM_GENERIC_SP;
10264 break;
10265 case LR_REG:
10266 reg_kind = eRegisterKindGeneric;
10267 reg_num = LLDB_REGNUM_GENERIC_RA;
10268 break;
10269 default:
10270 reg_kind = eRegisterKindDWARF;
10271 reg_num = dwarf_r0 + Rd;
10272 }
10273 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010274 return false;
10275 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010276 return WriteFlags (context, result, carry, overflow);
10277 }
10278 return true;
10279}
10280
10281// This helper method tries to encapsulate the following pseudocode from the
10282// ARM Architecture Reference Manual:
10283//
10284// APSR.N = result<31>;
10285// APSR.Z = IsZeroBit(result);
10286// APSR.C = carry;
10287// APSR.V = overflow
10288//
10289// Default arguments can be specified for carry and overflow parameters, which means
10290// not to update the respective flags.
10291bool
10292EmulateInstructionARM::WriteFlags (Context &context,
10293 const uint32_t result,
10294 const uint32_t carry,
10295 const uint32_t overflow)
10296{
10297 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010298 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10299 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010300 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010301 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010302 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010303 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +000010304 if (m_new_inst_cpsr != m_inst_cpsr)
10305 {
10306 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10307 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010308 }
10309 return true;
10310}
10311
Greg Clayton64c84432011-01-21 22:02:52 +000010312bool
10313EmulateInstructionARM::EvaluateInstruction ()
10314{
Johnny Chenc315f862011-02-05 00:46:10 +000010315 // Advance the ITSTATE bits to their values for the next instruction.
10316 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
10317 m_it_session.ITAdvance();
10318
Greg Clayton64c84432011-01-21 22:02:52 +000010319 return false;
10320}