blob: f45c52fac8cef08031d5c0b9efe6309eb6aea06b [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);
Johnny Chenef85e912011-01-31 23:07:40 +0000415 for (i=0; i<15; ++i)
416 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000417 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000418 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000419 dwarf_reg.num = dwarf_r0 + i;
420 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000421 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000422 if (!success)
423 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000424 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000425 return false;
426 addr += addr_byte_size;
427 }
428 }
429
Johnny Chen7c1bf922011-02-08 23:49:37 +0000430 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000431 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000432 dwarf_reg.num = dwarf_pc;
433 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000434 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000435 if (!success)
436 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000437 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000438 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000439 return false;
440 addr += addr_byte_size;
441 }
442
443 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000444 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000445
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000446 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000447 return false;
448 }
449 return true;
450}
451
Johnny Chen5b442b72011-01-27 19:34:30 +0000452// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000453// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000454bool
Johnny Chen9f687722011-02-18 00:02:28 +0000455EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000456{
457#if 0
458 // ARM pseudo code...
459 if (ConditionPassed())
460 {
461 EncodingSpecificOperations();
462 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
463 if d == 15 then
464 ALUWritePC(result); // setflags is always FALSE here
465 else
466 R[d] = result;
467 if setflags then
468 APSR.N = result<31>;
469 APSR.Z = IsZeroBit(result);
470 APSR.C = carry;
471 APSR.V = overflow;
472 }
473#endif
474
475 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000476 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000477 if (!success)
478 return false;
479
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000480 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000481 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000482 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000483 if (!success)
484 return false;
485 uint32_t Rd; // the destination register
486 uint32_t imm32;
487 switch (encoding) {
488 case eEncodingT1:
489 Rd = 7;
490 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
491 break;
492 case eEncodingA1:
493 Rd = Bits32(opcode, 15, 12);
494 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
495 break;
496 default:
497 return false;
498 }
499 addr_t sp_offset = imm32;
500 addr_t addr = sp + sp_offset; // a pointer to the stack area
501
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000502 EmulateInstruction::Context context;
503 context.type = EmulateInstruction::eContextRegisterPlusOffset;
504 Register sp_reg;
505 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
506 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000507
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000508 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000509 return false;
510 }
511 return true;
512}
513
Johnny Chen2ccad832011-01-28 19:57:25 +0000514// Set r7 or ip to the current stack pointer.
515// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000516bool
Johnny Chen9f687722011-02-18 00:02:28 +0000517EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000518{
519#if 0
520 // ARM pseudo code...
521 if (ConditionPassed())
522 {
523 EncodingSpecificOperations();
524 result = R[m];
525 if d == 15 then
526 ALUWritePC(result); // setflags is always FALSE here
527 else
528 R[d] = result;
529 if setflags then
530 APSR.N = result<31>;
531 APSR.Z = IsZeroBit(result);
532 // APSR.C unchanged
533 // APSR.V unchanged
534 }
535#endif
536
537 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000538 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000539 //if (!success)
540 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000541
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000542 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000543 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000544 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000545 if (!success)
546 return false;
547 uint32_t Rd; // the destination register
548 switch (encoding) {
549 case eEncodingT1:
550 Rd = 7;
551 break;
552 case eEncodingA1:
553 Rd = 12;
554 break;
555 default:
556 return false;
557 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000558
559 EmulateInstruction::Context context;
560 context.type = EmulateInstruction::eContextRegisterPlusOffset;
561 Register sp_reg;
562 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
563 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000564
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000565 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000566 return false;
567 }
568 return true;
569}
570
Johnny Chen1c13b622011-01-29 00:11:15 +0000571// Move from high register (r8-r15) to low register (r0-r7).
572// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000573bool
Johnny Chen9f687722011-02-18 00:02:28 +0000574EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000575{
Johnny Chen9f687722011-02-18 00:02:28 +0000576 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000577}
578
579// Move from register to register.
580// MOV (register)
581bool
Johnny Chen9f687722011-02-18 00:02:28 +0000582EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000583{
Johnny Chen1c13b622011-01-29 00:11:15 +0000584#if 0
585 // ARM pseudo code...
586 if (ConditionPassed())
587 {
588 EncodingSpecificOperations();
589 result = R[m];
590 if d == 15 then
591 ALUWritePC(result); // setflags is always FALSE here
592 else
593 R[d] = result;
594 if setflags then
595 APSR.N = result<31>;
596 APSR.Z = IsZeroBit(result);
597 // APSR.C unchanged
598 // APSR.V unchanged
599 }
600#endif
601
602 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000603 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000604 if (!success)
605 return false;
606
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000607 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000608 {
609 uint32_t Rm; // the source register
610 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000611 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000612 switch (encoding) {
613 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000614 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000615 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000616 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000617 if (Rd == 15 && InITBlock() && !LastInITBlock())
618 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000619 break;
620 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000621 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000622 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000623 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000624 if (InITBlock())
625 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000626 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000627 case eEncodingT3:
628 Rd = Bits32(opcode, 11, 8);
629 Rm = Bits32(opcode, 3, 0);
630 setflags = BitIsSet(opcode, 20);
631 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
632 if (setflags && (BadReg(Rd) || BadReg(Rm)))
633 return false;
634 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
635 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
636 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000637 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000638 case eEncodingA1:
639 Rd = Bits32(opcode, 15, 12);
640 Rm = Bits32(opcode, 3, 0);
641 setflags = BitIsSet(opcode, 20);
642 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
643 // TODO: Emulate SUBS PC, LR and related instructions.
644 if (Rd == 15 && setflags)
645 return false;
646 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000647 default:
648 return false;
649 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000650 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000651 if (!success)
652 return false;
653
654 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000655 EmulateInstruction::Context context;
Caroline Tice2b03ed82011-03-16 00:06:12 +0000656 context.type = EmulateInstruction::eContextRegisterLoad;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000657 Register dwarf_reg;
658 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Caroline Tice2b03ed82011-03-16 00:06:12 +0000659 context.SetRegister (dwarf_reg);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000660
Johnny Chen10530c22011-02-17 22:37:12 +0000661 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000662 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000663 }
664 return true;
665}
666
Johnny Chen357c30f2011-02-14 22:04:25 +0000667// Move (immediate) writes an immediate value to the destination register. It
668// can optionally update the condition flags based on the value.
669// MOV (immediate)
670bool
Johnny Chen9f687722011-02-18 00:02:28 +0000671EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000672{
673#if 0
674 // ARM pseudo code...
675 if (ConditionPassed())
676 {
677 EncodingSpecificOperations();
678 result = imm32;
679 if d == 15 then // Can only occur for ARM encoding
680 ALUWritePC(result); // setflags is always FALSE here
681 else
682 R[d] = result;
683 if setflags then
684 APSR.N = result<31>;
685 APSR.Z = IsZeroBit(result);
686 APSR.C = carry;
687 // APSR.V unchanged
688 }
689#endif
690 bool success = false;
691 const uint32_t opcode = OpcodeAsUnsigned (&success);
692 if (!success)
693 return false;
694
695 if (ConditionPassed())
696 {
697 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000698 uint32_t imm32; // the immediate value to be written to Rd
699 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
700 bool setflags;
701 switch (encoding) {
702 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000703 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000704 setflags = !InITBlock();
705 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000706 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000707 break;
708 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000709 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000710 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000711 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000712 if (BadReg(Rd))
713 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000714 break;
715 default:
716 return false;
717 }
718 uint32_t result = imm32;
719
720 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000721 EmulateInstruction::Context context;
722 context.type = EmulateInstruction::eContextImmediate;
723 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000724
Johnny Chen10530c22011-02-17 22:37:12 +0000725 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000726 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000727 }
728 return true;
729}
730
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000731// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
732// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
733// unsigned values.
734//
735// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
736// limited to only a few forms of the instruction.
737bool
738EmulateInstructionARM::EmulateMUL (ARMEncoding encoding)
739{
740#if 0
741 if ConditionPassed() then
742 EncodingSpecificOperations();
743 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
744 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
745 result = operand1 * operand2;
746 R[d] = result<31:0>;
747 if setflags then
748 APSR.N = result<31>;
749 APSR.Z = IsZeroBit(result);
750 if ArchVersion() == 4 then
751 APSR.C = bit UNKNOWN;
752 // else APSR.C unchanged
753 // APSR.V always unchanged
754#endif
755
756 bool success = false;
757 const uint32_t opcode = OpcodeAsUnsigned (&success);
758 if (!success)
759 return false;
760
761 if (ConditionPassed())
762 {
763 uint32_t d;
764 uint32_t n;
765 uint32_t m;
766 bool setflags;
767
768 // EncodingSpecificOperations();
769 switch (encoding)
770 {
771 case eEncodingT1:
772 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
773 d = Bits32 (opcode, 2, 0);
774 n = Bits32 (opcode, 5, 3);
775 m = Bits32 (opcode, 2, 0);
776 setflags = !InITBlock();
777
778 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
779 if ((ArchVersion() < ARMv6) && (d == n))
780 return false;
781
782 break;
783
784 case eEncodingT2:
785 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
786 d = Bits32 (opcode, 11, 8);
787 n = Bits32 (opcode, 19, 16);
788 m = Bits32 (opcode, 3, 0);
789 setflags = false;
790
791 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
792 if (BadReg (d) || BadReg (n) || BadReg (m))
793 return false;
794
795 break;
796
797 case eEncodingA1:
798 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ’1’);
799 d = Bits32 (opcode, 19, 16);
800 n = Bits32 (opcode, 3, 0);
801 m = Bits32 (opcode, 11, 8);
802 setflags = BitIsSet (opcode, 20);
803
804 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
805 if ((d == 15) || (n == 15) || (m == 15))
806 return false;
807
808 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
809 if ((ArchVersion() < ARMv6) && (d == n))
810 return false;
811
812 break;
813
814 default:
815 return false;
816 }
817
818 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
819 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
820 if (!success)
821 return false;
822
823 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
824 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
825 if (!success)
826 return false;
827
828 // result = operand1 * operand2;
829 uint64_t result = operand1 * operand2;
830
831 // R[d] = result<31:0>;
832 Register op1_reg;
833 Register op2_reg;
834 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
835 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
836
837 EmulateInstruction::Context context;
838 context.type = eContextMultiplication;
839 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
840
841 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
842 return false;
843
844 // if setflags then
845 if (setflags)
846 {
847 // APSR.N = result<31>;
848 // APSR.Z = IsZeroBit(result);
849 m_new_inst_cpsr = m_inst_cpsr;
850 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
851 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
852 if (m_new_inst_cpsr != m_inst_cpsr)
853 {
854 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
855 return false;
856 }
857
858 // if ArchVersion() == 4 then
859 // APSR.C = bit UNKNOWN;
860 }
861 }
862 return true;
863}
864
Johnny Chend642a6a2011-02-22 01:01:03 +0000865// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
866// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000867bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000868EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000869{
870#if 0
871 // ARM pseudo code...
872 if (ConditionPassed())
873 {
874 EncodingSpecificOperations();
875 result = NOT(imm32);
876 if d == 15 then // Can only occur for ARM encoding
877 ALUWritePC(result); // setflags is always FALSE here
878 else
879 R[d] = result;
880 if setflags then
881 APSR.N = result<31>;
882 APSR.Z = IsZeroBit(result);
883 APSR.C = carry;
884 // APSR.V unchanged
885 }
886#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000887 bool success = false;
888 const uint32_t opcode = OpcodeAsUnsigned (&success);
889 if (!success)
890 return false;
891
892 if (ConditionPassed())
893 {
894 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000895 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
896 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000897 bool setflags;
898 switch (encoding) {
899 case eEncodingT1:
900 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000901 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000902 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000903 break;
904 case eEncodingA1:
905 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000906 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000907 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
908 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
909 // TODO: Emulate SUBS PC, LR and related instructions.
910 if (Rd == 15 && setflags)
911 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000912 break;
913 default:
914 return false;
915 }
916 uint32_t result = ~imm32;
917
918 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000919 EmulateInstruction::Context context;
920 context.type = EmulateInstruction::eContextImmediate;
921 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000922
Johnny Chen10530c22011-02-17 22:37:12 +0000923 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000924 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000925 }
926 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000927}
928
Johnny Chend642a6a2011-02-22 01:01:03 +0000929// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
930// It can optionally update the condition flags based on the result.
931bool
932EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
933{
934#if 0
935 // ARM pseudo code...
936 if (ConditionPassed())
937 {
938 EncodingSpecificOperations();
939 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
940 result = NOT(shifted);
941 if d == 15 then // Can only occur for ARM encoding
942 ALUWritePC(result); // setflags is always FALSE here
943 else
944 R[d] = result;
945 if setflags then
946 APSR.N = result<31>;
947 APSR.Z = IsZeroBit(result);
948 APSR.C = carry;
949 // APSR.V unchanged
950 }
951#endif
952
953 bool success = false;
954 const uint32_t opcode = OpcodeAsUnsigned (&success);
955 if (!success)
956 return false;
957
958 if (ConditionPassed())
959 {
960 uint32_t Rm; // the source register
961 uint32_t Rd; // the destination register
962 ARM_ShifterType shift_t;
963 uint32_t shift_n; // the shift applied to the value read from Rm
964 bool setflags;
965 uint32_t carry; // the carry bit after the shift operation
966 switch (encoding) {
967 case eEncodingT1:
968 Rd = Bits32(opcode, 2, 0);
969 Rm = Bits32(opcode, 5, 3);
970 setflags = !InITBlock();
971 shift_t = SRType_LSL;
972 shift_n = 0;
973 if (InITBlock())
974 return false;
975 break;
976 case eEncodingT2:
977 Rd = Bits32(opcode, 11, 8);
978 Rm = Bits32(opcode, 3, 0);
979 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000980 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000981 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000982 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000983 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000984 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000985 case eEncodingA1:
986 Rd = Bits32(opcode, 15, 12);
987 Rm = Bits32(opcode, 3, 0);
988 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000989 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000990 break;
991 default:
992 return false;
993 }
994 uint32_t value = ReadCoreReg(Rm, &success);
995 if (!success)
996 return false;
997
998 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
999 uint32_t result = ~shifted;
1000
1001 // The context specifies that an immediate is to be moved into Rd.
1002 EmulateInstruction::Context context;
1003 context.type = EmulateInstruction::eContextImmediate;
1004 context.SetNoArgs ();
1005
1006 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1007 return false;
1008 }
1009 return true;
1010}
1011
Johnny Chen788e0552011-01-27 22:52:23 +00001012// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1013// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001014bool
Johnny Chenc9de9102011-02-11 19:12:30 +00001015EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001016{
1017#if 0
1018 // ARM pseudo code...
1019 if (ConditionPassed())
1020 {
1021 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1022 base = Align(PC,4);
1023 address = if add then (base + imm32) else (base - imm32);
1024 data = MemU[address,4];
1025 if t == 15 then
1026 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
1027 elsif UnalignedSupport() || address<1:0> = ‘00’ then
1028 R[t] = data;
1029 else // Can only apply before ARMv7
1030 if CurrentInstrSet() == InstrSet_ARM then
1031 R[t] = ROR(data, 8*UInt(address<1:0>));
1032 else
1033 R[t] = bits(32) UNKNOWN;
1034 }
1035#endif
1036
1037 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001038 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +00001039 if (!success)
1040 return false;
1041
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001042 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +00001043 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001044 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001045 if (!success)
1046 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001047
1048 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001049 EmulateInstruction::Context context;
1050 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1051 Register pc_reg;
1052 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1053 context.SetRegisterPlusOffset (pc_reg, 0);
1054
Johnny Chenc9de9102011-02-11 19:12:30 +00001055 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001056 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001057 bool add; // +imm32 or -imm32?
1058 addr_t base; // the base address
1059 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001060 uint32_t data; // the literal data value from the PC relative load
1061 switch (encoding) {
1062 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001063 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001064 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001065 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001066 break;
1067 case eEncodingT2:
1068 Rt = Bits32(opcode, 15, 12);
1069 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1070 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001071 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001072 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001073 break;
1074 default:
1075 return false;
1076 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001077
Johnny Chene39f22d2011-02-19 01:36:13 +00001078 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001079 if (add)
1080 address = base + imm32;
1081 else
1082 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001083
1084 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001085 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001086 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001087 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001088
1089 if (Rt == 15)
1090 {
1091 if (Bits32(address, 1, 0) == 0)
1092 {
1093 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001094 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001095 return false;
1096 }
1097 else
1098 return false;
1099 }
1100 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1101 {
1102 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1103 return false;
1104 }
1105 else // We don't handle ARM for now.
1106 return false;
1107
1108 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +00001109 return false;
1110 }
1111 return true;
1112}
1113
Johnny Chen5b442b72011-01-27 19:34:30 +00001114// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001115// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001116bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001117EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001118{
1119#if 0
1120 // ARM pseudo code...
1121 if (ConditionPassed())
1122 {
1123 EncodingSpecificOperations();
1124 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
1125 if d == 15 then // Can only occur for ARM encoding
1126 ALUWritePC(result); // setflags is always FALSE here
1127 else
1128 R[d] = result;
1129 if setflags then
1130 APSR.N = result<31>;
1131 APSR.Z = IsZeroBit(result);
1132 APSR.C = carry;
1133 APSR.V = overflow;
1134 }
1135#endif
1136
1137 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001138 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001139 if (!success)
1140 return false;
1141
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001142 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +00001143 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001144 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001145 if (!success)
1146 return false;
1147 uint32_t imm32; // the immediate operand
1148 switch (encoding) {
1149 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001150 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001151 break;
1152 default:
1153 return false;
1154 }
1155 addr_t sp_offset = imm32;
1156 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1157
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001158 EmulateInstruction::Context context;
1159 context.type = EmulateInstruction::eContextAdjustStackPointer;
1160 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001161
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001162 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001163 return false;
1164 }
1165 return true;
1166}
1167
1168// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001169// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001170bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001171EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001172{
1173#if 0
1174 // ARM pseudo code...
1175 if (ConditionPassed())
1176 {
1177 EncodingSpecificOperations();
1178 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1179 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1180 if d == 15 then
1181 ALUWritePC(result); // setflags is always FALSE here
1182 else
1183 R[d] = result;
1184 if setflags then
1185 APSR.N = result<31>;
1186 APSR.Z = IsZeroBit(result);
1187 APSR.C = carry;
1188 APSR.V = overflow;
1189 }
1190#endif
1191
1192 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001193 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001194 if (!success)
1195 return false;
1196
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001197 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001198 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001199 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001200 if (!success)
1201 return false;
1202 uint32_t Rm; // the second operand
1203 switch (encoding) {
1204 case eEncodingT2:
1205 Rm = Bits32(opcode, 6, 3);
1206 break;
1207 default:
1208 return false;
1209 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001210 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001211 if (!success)
1212 return false;
1213
1214 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1215
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001216 EmulateInstruction::Context context;
1217 context.type = EmulateInstruction::eContextAdjustStackPointer;
1218 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001219
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001220 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001221 return false;
1222 }
1223 return true;
1224}
1225
Johnny Chen9b8d7832011-02-02 01:13:56 +00001226// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1227// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1228// from Thumb to ARM.
1229// BLX (immediate)
1230bool
1231EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1232{
1233#if 0
1234 // ARM pseudo code...
1235 if (ConditionPassed())
1236 {
1237 EncodingSpecificOperations();
1238 if CurrentInstrSet() == InstrSet_ARM then
1239 LR = PC - 4;
1240 else
1241 LR = PC<31:1> : '1';
1242 if targetInstrSet == InstrSet_ARM then
1243 targetAddress = Align(PC,4) + imm32;
1244 else
1245 targetAddress = PC + imm32;
1246 SelectInstrSet(targetInstrSet);
1247 BranchWritePC(targetAddress);
1248 }
1249#endif
1250
1251 bool success = false;
1252 const uint32_t opcode = OpcodeAsUnsigned (&success);
1253 if (!success)
1254 return false;
1255
1256 if (ConditionPassed())
1257 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001258 EmulateInstruction::Context context;
1259 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001260 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001261 if (!success)
1262 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001263 addr_t lr; // next instruction address
1264 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001265 int32_t imm32; // PC-relative offset
1266 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001267 case eEncodingT1:
1268 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001269 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001270 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001271 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001272 uint32_t J1 = Bit32(opcode, 13);
1273 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001274 uint32_t imm11 = Bits32(opcode, 10, 0);
1275 uint32_t I1 = !(J1 ^ S);
1276 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001277 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001278 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001279 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001280 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001281 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001282 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001283 break;
1284 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001285 case eEncodingT2:
1286 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001287 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001288 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001289 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001290 uint32_t J1 = Bit32(opcode, 13);
1291 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001292 uint32_t imm10L = Bits32(opcode, 10, 1);
1293 uint32_t I1 = !(J1 ^ S);
1294 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001295 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001296 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001297 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001298 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001299 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001300 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001301 break;
1302 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001303 case eEncodingA1:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001304 lr = pc - 4; // return address
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001305 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001306 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001307 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001308 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001309 case eEncodingA2:
Caroline Tice2b03ed82011-03-16 00:06:12 +00001310 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001311 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001312 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001313 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001314 break;
1315 default:
1316 return false;
1317 }
1318 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1319 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001320 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001321 return false;
1322 }
1323 return true;
1324}
1325
1326// Branch with Link and Exchange (register) calls a subroutine at an address and
1327// instruction set specified by a register.
1328// BLX (register)
1329bool
1330EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1331{
1332#if 0
1333 // ARM pseudo code...
1334 if (ConditionPassed())
1335 {
1336 EncodingSpecificOperations();
1337 target = R[m];
1338 if CurrentInstrSet() == InstrSet_ARM then
1339 next_instr_addr = PC - 4;
1340 LR = next_instr_addr;
1341 else
1342 next_instr_addr = PC - 2;
1343 LR = next_instr_addr<31:1> : ‘1’;
1344 BXWritePC(target);
1345 }
1346#endif
1347
1348 bool success = false;
1349 const uint32_t opcode = OpcodeAsUnsigned (&success);
1350 if (!success)
1351 return false;
1352
1353 if (ConditionPassed())
1354 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001355 EmulateInstruction::Context context;
1356 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001357 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001358 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001359 if (!success)
1360 return false;
1361 uint32_t Rm; // the register with the target address
1362 switch (encoding) {
1363 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001364 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001365 Rm = Bits32(opcode, 6, 3);
1366 // if m == 15 then UNPREDICTABLE;
1367 if (Rm == 15)
1368 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001369 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001370 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001371 break;
1372 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001373 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001374 Rm = Bits32(opcode, 3, 0);
1375 // if m == 15 then UNPREDICTABLE;
1376 if (Rm == 15)
1377 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001378 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001379 default:
1380 return false;
1381 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001382 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001383 if (!success)
1384 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001385 Register dwarf_reg;
1386 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1387 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001388 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1389 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001390 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001391 return false;
1392 }
1393 return true;
1394}
1395
Johnny Chenab3b3512011-02-12 00:10:51 +00001396// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001397bool
1398EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1399{
1400#if 0
1401 // ARM pseudo code...
1402 if (ConditionPassed())
1403 {
1404 EncodingSpecificOperations();
1405 BXWritePC(R[m]);
1406 }
1407#endif
1408
1409 bool success = false;
1410 const uint32_t opcode = OpcodeAsUnsigned (&success);
1411 if (!success)
1412 return false;
1413
1414 if (ConditionPassed())
1415 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001416 EmulateInstruction::Context context;
1417 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001418 uint32_t Rm; // the register with the target address
1419 switch (encoding) {
1420 case eEncodingT1:
1421 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001422 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001423 return false;
1424 break;
1425 case eEncodingA1:
1426 Rm = Bits32(opcode, 3, 0);
1427 break;
1428 default:
1429 return false;
1430 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001431 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001432 if (!success)
1433 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001434
1435 Register dwarf_reg;
1436 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001437 context.SetRegister (dwarf_reg);
1438 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001439 return false;
1440 }
1441 return true;
1442}
1443
Johnny Chen59e6ab72011-02-24 21:01:20 +00001444// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1445// address and instruction set specified by a register as though it were a BX instruction.
1446//
1447// TODO: Emulate Jazelle architecture?
1448// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1449bool
1450EmulateInstructionARM::EmulateBXJRm (ARMEncoding encoding)
1451{
1452#if 0
1453 // ARM pseudo code...
1454 if (ConditionPassed())
1455 {
1456 EncodingSpecificOperations();
1457 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1458 BXWritePC(R[m]);
1459 else
1460 if JazelleAcceptsExecution() then
1461 SwitchToJazelleExecution();
1462 else
1463 SUBARCHITECTURE_DEFINED handler call;
1464 }
1465#endif
1466
1467 bool success = false;
1468 const uint32_t opcode = OpcodeAsUnsigned (&success);
1469 if (!success)
1470 return false;
1471
1472 if (ConditionPassed())
1473 {
1474 EmulateInstruction::Context context;
1475 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1476 uint32_t Rm; // the register with the target address
1477 switch (encoding) {
1478 case eEncodingT1:
1479 Rm = Bits32(opcode, 19, 16);
1480 if (BadReg(Rm))
1481 return false;
1482 if (InITBlock() && !LastInITBlock())
1483 return false;
1484 break;
1485 case eEncodingA1:
1486 Rm = Bits32(opcode, 3, 0);
1487 if (Rm == 15)
1488 return false;
1489 break;
1490 default:
1491 return false;
1492 }
1493 addr_t target = ReadCoreReg (Rm, &success);
1494 if (!success)
1495 return false;
1496
1497 Register dwarf_reg;
1498 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1499 context.SetRegister (dwarf_reg);
1500 if (!BXWritePC(context, target))
1501 return false;
1502 }
1503 return true;
1504}
1505
Johnny Chen0d0148e2011-01-28 02:26:08 +00001506// Set r7 to point to some ip offset.
1507// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001508bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001509EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001510{
1511#if 0
1512 // ARM pseudo code...
1513 if (ConditionPassed())
1514 {
1515 EncodingSpecificOperations();
1516 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1517 if d == 15 then // Can only occur for ARM encoding
1518 ALUWritePC(result); // setflags is always FALSE here
1519 else
1520 R[d] = result;
1521 if setflags then
1522 APSR.N = result<31>;
1523 APSR.Z = IsZeroBit(result);
1524 APSR.C = carry;
1525 APSR.V = overflow;
1526 }
1527#endif
1528
1529 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001530 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001531 if (!success)
1532 return false;
1533
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001534 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001535 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001536 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001537 if (!success)
1538 return false;
1539 uint32_t imm32;
1540 switch (encoding) {
1541 case eEncodingA1:
1542 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1543 break;
1544 default:
1545 return false;
1546 }
1547 addr_t ip_offset = imm32;
1548 addr_t addr = ip - ip_offset; // the adjusted ip value
1549
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001550 EmulateInstruction::Context context;
1551 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1552 Register dwarf_reg;
1553 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1554 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001555
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001556 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001557 return false;
1558 }
1559 return true;
1560}
1561
1562// Set ip to point to some stack offset.
1563// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001564bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001565EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001566{
1567#if 0
1568 // ARM pseudo code...
1569 if (ConditionPassed())
1570 {
1571 EncodingSpecificOperations();
1572 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1573 if d == 15 then // Can only occur for ARM encoding
1574 ALUWritePC(result); // setflags is always FALSE here
1575 else
1576 R[d] = result;
1577 if setflags then
1578 APSR.N = result<31>;
1579 APSR.Z = IsZeroBit(result);
1580 APSR.C = carry;
1581 APSR.V = overflow;
1582 }
1583#endif
1584
1585 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001586 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001587 if (!success)
1588 return false;
1589
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001590 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001591 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001592 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001593 if (!success)
1594 return false;
1595 uint32_t imm32;
1596 switch (encoding) {
1597 case eEncodingA1:
1598 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1599 break;
1600 default:
1601 return false;
1602 }
1603 addr_t sp_offset = imm32;
1604 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1605
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001606 EmulateInstruction::Context context;
1607 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1608 Register dwarf_reg;
1609 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1610 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001611
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001612 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001613 return false;
1614 }
1615 return true;
1616}
1617
Johnny Chenc9e747f2011-02-23 01:55:07 +00001618// This instruction subtracts an immediate value from the SP value, and writes
1619// the result to the destination register.
1620//
1621// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001622bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001623EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001624{
1625#if 0
1626 // ARM pseudo code...
1627 if (ConditionPassed())
1628 {
1629 EncodingSpecificOperations();
1630 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001631 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001632 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001633 else
1634 R[d] = result;
1635 if setflags then
1636 APSR.N = result<31>;
1637 APSR.Z = IsZeroBit(result);
1638 APSR.C = carry;
1639 APSR.V = overflow;
1640 }
1641#endif
1642
1643 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001644 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001645 if (!success)
1646 return false;
1647
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001648 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001649 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001650 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001651 if (!success)
1652 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001653
1654 uint32_t Rd;
1655 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001656 uint32_t imm32;
1657 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001658 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001659 Rd = 13;
1660 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001661 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001662 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001663 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001664 Rd = Bits32(opcode, 11, 8);
1665 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001666 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001667 if (Rd == 15 && setflags)
1668 return EmulateCMPImm(eEncodingT2);
1669 if (Rd == 15 && !setflags)
1670 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001671 break;
1672 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001673 Rd = Bits32(opcode, 11, 8);
1674 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001675 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001676 if (Rd == 15)
1677 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001678 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001679 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001680 Rd = Bits32(opcode, 15, 12);
1681 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001682 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001683 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1684 // TODO: Emulate SUBS PC, LR and related instructions.
1685 if (Rd == 15 && setflags)
1686 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001687 break;
1688 default:
1689 return false;
1690 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001691 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1692
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001693 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001694 if (Rd == 13)
1695 {
Caroline Tice2b03ed82011-03-16 00:06:12 +00001696 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong
1697 // value gets passed down to context.SetImmediateSigned.
Johnny Chenc9e747f2011-02-23 01:55:07 +00001698 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice2b03ed82011-03-16 00:06:12 +00001699 context.SetImmediateSigned (-imm64); // the stack pointer offset
Johnny Chenc9e747f2011-02-23 01:55:07 +00001700 }
1701 else
1702 {
1703 context.type = EmulateInstruction::eContextImmediate;
1704 context.SetNoArgs ();
1705 }
1706
1707 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001708 return false;
1709 }
1710 return true;
1711}
1712
Johnny Chen08c25e82011-01-31 18:02:28 +00001713// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001714bool
1715EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001716{
1717#if 0
1718 // ARM pseudo code...
1719 if (ConditionPassed())
1720 {
1721 EncodingSpecificOperations();
1722 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1723 address = if index then offset_addr else R[n];
1724 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1725 if wback then R[n] = offset_addr;
1726 }
1727#endif
1728
1729 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001730 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001731 if (!success)
1732 return false;
1733
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001734 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001735 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001736 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001737 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001738 if (!success)
1739 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001740 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001741 uint32_t imm12;
1742 switch (encoding) {
1743 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001744 Rt = Bits32(opcode, 15, 12);
1745 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001746 break;
1747 default:
1748 return false;
1749 }
1750 addr_t sp_offset = imm12;
1751 addr_t addr = sp - sp_offset;
1752
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001753 EmulateInstruction::Context context;
1754 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1755 Register dwarf_reg;
1756 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001757 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001758 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001759 dwarf_reg.num = dwarf_r0 + Rt;
1760 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001761 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001762 if (!success)
1763 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001764 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001765 return false;
1766 }
1767 else
1768 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001769 dwarf_reg.num = dwarf_pc;
1770 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001771 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001772 if (!success)
1773 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001774 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001775 return false;
1776 }
1777
1778 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001779 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001780
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001781 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001782 return false;
1783 }
1784 return true;
1785}
1786
Johnny Chen08c25e82011-01-31 18:02:28 +00001787// Vector Push stores multiple extension registers to the stack.
1788// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001789bool
1790EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001791{
1792#if 0
1793 // ARM pseudo code...
1794 if (ConditionPassed())
1795 {
1796 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1797 address = SP - imm32;
1798 SP = SP - imm32;
1799 if single_regs then
1800 for r = 0 to regs-1
1801 MemA[address,4] = S[d+r]; address = address+4;
1802 else
1803 for r = 0 to regs-1
1804 // Store as two word-aligned words in the correct order for current endianness.
1805 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1806 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1807 address = address+8;
1808 }
1809#endif
1810
1811 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001812 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001813 if (!success)
1814 return false;
1815
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001816 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001817 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001818 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001819 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001820 if (!success)
1821 return false;
1822 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001823 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001824 uint32_t imm32; // stack offset
1825 uint32_t regs; // number of registers
1826 switch (encoding) {
1827 case eEncodingT1:
1828 case eEncodingA1:
1829 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001830 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001831 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1832 // If UInt(imm8) is odd, see "FSTMX".
1833 regs = Bits32(opcode, 7, 0) / 2;
1834 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1835 if (regs == 0 || regs > 16 || (d + regs) > 32)
1836 return false;
1837 break;
1838 case eEncodingT2:
1839 case eEncodingA2:
1840 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001841 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001842 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1843 regs = Bits32(opcode, 7, 0);
1844 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1845 if (regs == 0 || regs > 16 || (d + regs) > 32)
1846 return false;
1847 break;
1848 default:
1849 return false;
1850 }
1851 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1852 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1853 addr_t sp_offset = imm32;
1854 addr_t addr = sp - sp_offset;
1855 uint32_t i;
1856
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001857 EmulateInstruction::Context context;
1858 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1859 Register dwarf_reg;
1860 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001861 for (i=d; i<regs; ++i)
1862 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001863 dwarf_reg.num = start_reg + i;
1864 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001865 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001866 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001867 if (!success)
1868 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001869 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001870 return false;
1871 addr += reg_byte_size;
1872 }
1873
1874 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001875 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001876
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001877 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001878 return false;
1879 }
1880 return true;
1881}
1882
Johnny Chen587a0a42011-02-01 18:35:28 +00001883// Vector Pop loads multiple extension registers from the stack.
1884// It also updates SP to point just above the loaded data.
1885bool
1886EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1887{
1888#if 0
1889 // ARM pseudo code...
1890 if (ConditionPassed())
1891 {
1892 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1893 address = SP;
1894 SP = SP + imm32;
1895 if single_regs then
1896 for r = 0 to regs-1
1897 S[d+r] = MemA[address,4]; address = address+4;
1898 else
1899 for r = 0 to regs-1
1900 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1901 // Combine the word-aligned words in the correct order for current endianness.
1902 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1903 }
1904#endif
1905
1906 bool success = false;
1907 const uint32_t opcode = OpcodeAsUnsigned (&success);
1908 if (!success)
1909 return false;
1910
1911 if (ConditionPassed())
1912 {
1913 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001914 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001915 if (!success)
1916 return false;
1917 bool single_regs;
1918 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1919 uint32_t imm32; // stack offset
1920 uint32_t regs; // number of registers
1921 switch (encoding) {
1922 case eEncodingT1:
1923 case eEncodingA1:
1924 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001925 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001926 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1927 // If UInt(imm8) is odd, see "FLDMX".
1928 regs = Bits32(opcode, 7, 0) / 2;
1929 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1930 if (regs == 0 || regs > 16 || (d + regs) > 32)
1931 return false;
1932 break;
1933 case eEncodingT2:
1934 case eEncodingA2:
1935 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001936 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001937 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1938 regs = Bits32(opcode, 7, 0);
1939 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1940 if (regs == 0 || regs > 16 || (d + regs) > 32)
1941 return false;
1942 break;
1943 default:
1944 return false;
1945 }
1946 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1947 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1948 addr_t sp_offset = imm32;
1949 addr_t addr = sp;
1950 uint32_t i;
1951 uint64_t data; // uint64_t to accomodate 64-bit registers.
1952
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001953 EmulateInstruction::Context context;
1954 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1955 Register dwarf_reg;
1956 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001957 for (i=d; i<regs; ++i)
1958 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001959 dwarf_reg.num = start_reg + i;
1960 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001961 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001962 if (!success)
1963 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001964 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001965 return false;
1966 addr += reg_byte_size;
1967 }
1968
1969 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001970 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001971
1972 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1973 return false;
1974 }
1975 return true;
1976}
1977
Johnny Chenb77be412011-02-04 00:40:18 +00001978// SVC (previously SWI)
1979bool
1980EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1981{
1982#if 0
1983 // ARM pseudo code...
1984 if (ConditionPassed())
1985 {
1986 EncodingSpecificOperations();
1987 CallSupervisor();
1988 }
1989#endif
1990
1991 bool success = false;
1992 const uint32_t opcode = OpcodeAsUnsigned (&success);
1993 if (!success)
1994 return false;
1995
1996 if (ConditionPassed())
1997 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001998 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001999 addr_t lr; // next instruction address
2000 if (!success)
2001 return false;
2002 uint32_t imm32; // the immediate constant
2003 uint32_t mode; // ARM or Thumb mode
2004 switch (encoding) {
2005 case eEncodingT1:
2006 lr = (pc + 2) | 1u; // return address
2007 imm32 = Bits32(opcode, 7, 0);
2008 mode = eModeThumb;
2009 break;
2010 case eEncodingA1:
2011 lr = pc + 4; // return address
2012 imm32 = Bits32(opcode, 23, 0);
2013 mode = eModeARM;
2014 break;
2015 default:
2016 return false;
2017 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002018
2019 EmulateInstruction::Context context;
2020 context.type = EmulateInstruction::eContextSupervisorCall;
2021 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002022 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2023 return false;
2024 }
2025 return true;
2026}
2027
Johnny Chenc315f862011-02-05 00:46:10 +00002028// If Then makes up to four following instructions (the IT block) conditional.
2029bool
2030EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
2031{
2032#if 0
2033 // ARM pseudo code...
2034 EncodingSpecificOperations();
2035 ITSTATE.IT<7:0> = firstcond:mask;
2036#endif
2037
2038 bool success = false;
2039 const uint32_t opcode = OpcodeAsUnsigned (&success);
2040 if (!success)
2041 return false;
2042
2043 m_it_session.InitIT(Bits32(opcode, 7, 0));
2044 return true;
2045}
2046
Johnny Chen3b620b32011-02-07 20:11:47 +00002047// Branch causes a branch to a target address.
2048bool
2049EmulateInstructionARM::EmulateB (ARMEncoding encoding)
2050{
2051#if 0
2052 // ARM pseudo code...
2053 if (ConditionPassed())
2054 {
2055 EncodingSpecificOperations();
2056 BranchWritePC(PC + imm32);
2057 }
2058#endif
2059
2060 bool success = false;
2061 const uint32_t opcode = OpcodeAsUnsigned (&success);
2062 if (!success)
2063 return false;
2064
Johnny Chen9ee056b2011-02-08 00:06:35 +00002065 if (ConditionPassed())
2066 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002067 EmulateInstruction::Context context;
2068 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002069 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002070 if (!success)
2071 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002072 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002073 int32_t imm32; // PC-relative offset
2074 switch (encoding) {
2075 case eEncodingT1:
2076 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2077 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002078 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002079 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002080 break;
2081 case eEncodingT2:
2082 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002083 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002084 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002085 break;
2086 case eEncodingT3:
2087 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2088 {
Johnny Chenbd599902011-02-10 21:39:01 +00002089 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002090 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002091 uint32_t J1 = Bit32(opcode, 13);
2092 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002093 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002094 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002095 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002096 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002097 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002098 break;
2099 }
2100 case eEncodingT4:
2101 {
Johnny Chenbd599902011-02-10 21:39:01 +00002102 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002103 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002104 uint32_t J1 = Bit32(opcode, 13);
2105 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002106 uint32_t imm11 = Bits32(opcode, 10, 0);
2107 uint32_t I1 = !(J1 ^ S);
2108 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002109 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002110 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002111 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002112 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002113 break;
2114 }
2115 case eEncodingA1:
2116 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002117 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002118 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002119 break;
2120 default:
2121 return false;
2122 }
2123 if (!BranchWritePC(context, target))
2124 return false;
2125 }
2126 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002127}
2128
Johnny Chen53ebab72011-02-08 23:21:57 +00002129// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2130// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2131// CBNZ, CBZ
2132bool
2133EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
2134{
2135#if 0
2136 // ARM pseudo code...
2137 EncodingSpecificOperations();
2138 if nonzero ^ IsZero(R[n]) then
2139 BranchWritePC(PC + imm32);
2140#endif
2141
2142 bool success = false;
2143 const uint32_t opcode = OpcodeAsUnsigned (&success);
2144 if (!success)
2145 return false;
2146
2147 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002148 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002149 if (!success)
2150 return false;
2151
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002152 EmulateInstruction::Context context;
2153 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002154 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002155 if (!success)
2156 return false;
2157
2158 addr_t target; // target address
2159 uint32_t imm32; // PC-relative offset to branch forward
2160 bool nonzero;
2161 switch (encoding) {
2162 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002163 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002164 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002165 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002166 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002167 break;
2168 default:
2169 return false;
2170 }
2171 if (nonzero ^ (reg_val == 0))
2172 if (!BranchWritePC(context, target))
2173 return false;
2174
2175 return true;
2176}
2177
Johnny Chen60299ec2011-02-17 19:34:27 +00002178// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2179// A base register provides a pointer to the table, and a second register supplies an index into the table.
2180// The branch length is twice the value of the byte returned from the table.
2181//
2182// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2183// A base register provides a pointer to the table, and a second register supplies an index into the table.
2184// The branch length is twice the value of the halfword returned from the table.
2185// TBB, TBH
2186bool
2187EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
2188{
2189#if 0
2190 // ARM pseudo code...
2191 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2192 if is_tbh then
2193 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2194 else
2195 halfwords = UInt(MemU[R[n]+R[m], 1]);
2196 BranchWritePC(PC + 2*halfwords);
2197#endif
2198
2199 bool success = false;
2200 const uint32_t opcode = OpcodeAsUnsigned (&success);
2201 if (!success)
2202 return false;
2203
2204 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2205 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2206 bool is_tbh; // true if table branch halfword
2207 switch (encoding) {
2208 case eEncodingT1:
2209 Rn = Bits32(opcode, 19, 16);
2210 Rm = Bits32(opcode, 3, 0);
2211 is_tbh = BitIsSet(opcode, 4);
2212 if (Rn == 13 || BadReg(Rm))
2213 return false;
2214 if (InITBlock() && !LastInITBlock())
2215 return false;
2216 break;
2217 default:
2218 return false;
2219 }
2220
2221 // Read the address of the table from the operand register Rn.
2222 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002223 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002224 if (!success)
2225 return false;
2226
2227 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002228 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002229 if (!success)
2230 return false;
2231
2232 // the offsetted table address
2233 addr_t addr = base + (is_tbh ? index*2 : index);
2234
2235 // PC-relative offset to branch forward
2236 EmulateInstruction::Context context;
2237 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002238 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002239 if (!success)
2240 return false;
2241
Johnny Chene39f22d2011-02-19 01:36:13 +00002242 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002243 if (!success)
2244 return false;
2245
2246 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002247 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002248 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2249 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2250
2251 if (!BranchWritePC(context, target))
2252 return false;
2253
2254 return true;
2255}
2256
Caroline Ticedcc11b32011-03-02 23:57:02 +00002257// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2258// It can optionally update the condition flags based on the result.
2259bool
2260EmulateInstructionARM::EmulateADDImmThumb (ARMEncoding encoding)
2261{
2262#if 0
2263 if ConditionPassed() then
2264 EncodingSpecificOperations();
2265 (result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2266 R[d] = result;
2267 if setflags then
2268 APSR.N = result<31>;
2269 APSR.Z = IsZeroBit(result);
2270 APSR.C = carry;
2271 APSR.V = overflow;
2272#endif
2273
2274 bool success = false;
2275 const uint32_t opcode = OpcodeAsUnsigned (&success);
2276 if (!success)
2277 return false;
2278
2279 if (ConditionPassed())
2280 {
2281 uint32_t d;
2282 uint32_t n;
2283 bool setflags;
2284 uint32_t imm32;
2285 uint32_t carry_out;
2286
2287 //EncodingSpecificOperations();
2288 switch (encoding)
2289 {
2290 case eEncodingT1:
2291 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2292 d = Bits32 (opcode, 2, 0);
2293 n = Bits32 (opcode, 5, 3);
2294 setflags = !InITBlock();
2295 imm32 = Bits32 (opcode, 8,6);
2296
2297 break;
2298
2299 case eEncodingT2:
2300 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2301 d = Bits32 (opcode, 10, 8);
2302 n = Bits32 (opcode, 10, 8);
2303 setflags = !InITBlock();
2304 imm32 = Bits32 (opcode, 7, 0);
2305
2306 break;
2307
2308 case eEncodingT3:
2309 // if Rd == ’1111’ && S == ’1’ then SEE CMN (immediate);
2310 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2311 // d = UInt(Rd); n = UInt(Rn); setflags = (S == ’1’); imm32 = ThumbExpandImm(i:imm3:imm8);
2312 d = Bits32 (opcode, 11, 8);
2313 n = Bits32 (opcode, 19, 16);
2314 setflags = BitIsSet (opcode, 20);
2315 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2316
2317 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2318 if (BadReg (d) || (n == 15))
2319 return false;
2320
2321 break;
2322
2323 case eEncodingT4:
2324 {
2325 // if Rn == ’1111’ then SEE ADR;
2326 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2327 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2328 d = Bits32 (opcode, 11, 8);
2329 n = Bits32 (opcode, 19, 16);
2330 setflags = false;
2331 uint32_t i = Bit32 (opcode, 26);
2332 uint32_t imm3 = Bits32 (opcode, 14, 12);
2333 uint32_t imm8 = Bits32 (opcode, 7, 0);
2334 imm32 = (i << 11) | (imm3 << 8) | imm8;
2335
2336 // if BadReg(d) then UNPREDICTABLE;
2337 if (BadReg (d))
2338 return false;
2339
2340 break;
2341 }
2342 default:
2343 return false;
2344 }
2345
2346 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2347 if (!success)
2348 return false;
2349
2350 //(result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2351 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2352
2353 Register reg_n;
2354 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2355
2356 EmulateInstruction::Context context;
2357 context.type = eContextAddition;
2358 context.SetRegisterPlusOffset (reg_n, imm32);
2359
2360 //R[d] = result;
2361 //if setflags then
2362 //APSR.N = result<31>;
2363 //APSR.Z = IsZeroBit(result);
2364 //APSR.C = carry;
2365 //APSR.V = overflow;
2366 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2367 return false;
2368
2369 }
2370 return true;
2371}
2372
Johnny Chen8fa20592011-02-18 01:22:22 +00002373// This instruction adds an immediate value to a register value, and writes the result to the destination
2374// register. It can optionally update the condition flags based on the result.
2375bool
2376EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2377{
2378#if 0
2379 // ARM pseudo code...
2380 if ConditionPassed() then
2381 EncodingSpecificOperations();
2382 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2383 if d == 15 then
2384 ALUWritePC(result); // setflags is always FALSE here
2385 else
2386 R[d] = result;
2387 if setflags then
2388 APSR.N = result<31>;
2389 APSR.Z = IsZeroBit(result);
2390 APSR.C = carry;
2391 APSR.V = overflow;
2392#endif
2393
2394 bool success = false;
2395 const uint32_t opcode = OpcodeAsUnsigned (&success);
2396 if (!success)
2397 return false;
2398
2399 if (ConditionPassed())
2400 {
2401 uint32_t Rd, Rn;
2402 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2403 bool setflags;
2404 switch (encoding)
2405 {
2406 case eEncodingA1:
2407 Rd = Bits32(opcode, 15, 12);
2408 Rn = Bits32(opcode, 19, 16);
2409 setflags = BitIsSet(opcode, 20);
2410 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2411 break;
2412 default:
2413 return false;
2414 }
2415
Johnny Chen8fa20592011-02-18 01:22:22 +00002416 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002417 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002418 if (!success)
2419 return false;
2420
2421 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2422
2423 EmulateInstruction::Context context;
2424 context.type = EmulateInstruction::eContextImmediate;
2425 context.SetNoArgs ();
2426
2427 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2428 return false;
2429 }
2430 return true;
2431}
2432
Johnny Chend761dcf2011-02-17 22:03:29 +00002433// This instruction adds a register value and an optionally-shifted register value, and writes the result
2434// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002435bool
Johnny Chen9f687722011-02-18 00:02:28 +00002436EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002437{
2438#if 0
2439 // ARM pseudo code...
2440 if ConditionPassed() then
2441 EncodingSpecificOperations();
2442 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2443 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2444 if d == 15 then
2445 ALUWritePC(result); // setflags is always FALSE here
2446 else
2447 R[d] = result;
2448 if setflags then
2449 APSR.N = result<31>;
2450 APSR.Z = IsZeroBit(result);
2451 APSR.C = carry;
2452 APSR.V = overflow;
2453#endif
2454
2455 bool success = false;
2456 const uint32_t opcode = OpcodeAsUnsigned (&success);
2457 if (!success)
2458 return false;
2459
2460 if (ConditionPassed())
2461 {
2462 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002463 ARM_ShifterType shift_t;
2464 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002465 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002466 switch (encoding)
2467 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002468 case eEncodingT1:
2469 Rd = Bits32(opcode, 2, 0);
2470 Rn = Bits32(opcode, 5, 3);
2471 Rm = Bits32(opcode, 8, 6);
2472 setflags = !InITBlock();
2473 shift_t = SRType_LSL;
2474 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002475 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002476 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002477 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002478 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002479 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002480 shift_t = SRType_LSL;
2481 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002482 if (Rn == 15 && Rm == 15)
2483 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002484 if (Rd == 15 && InITBlock() && !LastInITBlock())
2485 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002486 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002487 case eEncodingA1:
2488 Rd = Bits32(opcode, 15, 12);
2489 Rn = Bits32(opcode, 19, 16);
2490 Rm = Bits32(opcode, 3, 0);
2491 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002492 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002493 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002494 default:
2495 return false;
2496 }
2497
Johnny Chen26863dc2011-02-09 23:43:29 +00002498 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002499 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002500 if (!success)
2501 return false;
2502
2503 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002504 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002505 if (!success)
2506 return false;
2507
Johnny Chene97c0d52011-02-18 19:32:20 +00002508 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002509 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002510
2511 EmulateInstruction::Context context;
2512 context.type = EmulateInstruction::eContextImmediate;
2513 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002514
Johnny Chen10530c22011-02-17 22:37:12 +00002515 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002516 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002517 }
2518 return true;
2519}
2520
Johnny Chen34075cb2011-02-22 01:56:31 +00002521// Compare Negative (immediate) adds a register value and an immediate value.
2522// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002523bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002524EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2525{
2526#if 0
2527 // ARM pseudo code...
2528 if ConditionPassed() then
2529 EncodingSpecificOperations();
2530 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2531 APSR.N = result<31>;
2532 APSR.Z = IsZeroBit(result);
2533 APSR.C = carry;
2534 APSR.V = overflow;
2535#endif
2536
2537 bool success = false;
2538 const uint32_t opcode = OpcodeAsUnsigned (&success);
2539 if (!success)
2540 return false;
2541
2542 uint32_t Rn; // the first operand
2543 uint32_t imm32; // the immediate value to be compared with
2544 switch (encoding) {
2545 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002546 Rn = Bits32(opcode, 19, 16);
2547 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2548 if (Rn == 15)
2549 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002550 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002551 case eEncodingA1:
2552 Rn = Bits32(opcode, 19, 16);
2553 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2554 break;
2555 default:
2556 return false;
2557 }
2558 // Read the register value from the operand register Rn.
2559 uint32_t reg_val = ReadCoreReg(Rn, &success);
2560 if (!success)
2561 return false;
2562
Johnny Chen078fbc62011-02-22 19:48:22 +00002563 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002564
2565 EmulateInstruction::Context context;
2566 context.type = EmulateInstruction::eContextImmediate;
2567 context.SetNoArgs ();
2568 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2569 return false;
2570
2571 return true;
2572}
2573
2574// Compare Negative (register) adds a register value and an optionally-shifted register value.
2575// It updates the condition flags based on the result, and discards the result.
2576bool
2577EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2578{
2579#if 0
2580 // ARM pseudo code...
2581 if ConditionPassed() then
2582 EncodingSpecificOperations();
2583 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2584 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2585 APSR.N = result<31>;
2586 APSR.Z = IsZeroBit(result);
2587 APSR.C = carry;
2588 APSR.V = overflow;
2589#endif
2590
2591 bool success = false;
2592 const uint32_t opcode = OpcodeAsUnsigned (&success);
2593 if (!success)
2594 return false;
2595
2596 uint32_t Rn; // the first operand
2597 uint32_t Rm; // the second operand
2598 ARM_ShifterType shift_t;
2599 uint32_t shift_n; // the shift applied to the value read from Rm
2600 switch (encoding) {
2601 case eEncodingT1:
2602 Rn = Bits32(opcode, 2, 0);
2603 Rm = Bits32(opcode, 5, 3);
2604 shift_t = SRType_LSL;
2605 shift_n = 0;
2606 break;
2607 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002608 Rn = Bits32(opcode, 19, 16);
2609 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002610 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002611 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2612 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002613 return false;
2614 break;
2615 case eEncodingA1:
2616 Rn = Bits32(opcode, 19, 16);
2617 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002618 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002619 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002620 default:
2621 return false;
2622 }
2623 // Read the register value from register Rn.
2624 uint32_t val1 = ReadCoreReg(Rn, &success);
2625 if (!success)
2626 return false;
2627
2628 // Read the register value from register Rm.
2629 uint32_t val2 = ReadCoreReg(Rm, &success);
2630 if (!success)
2631 return false;
2632
2633 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002634 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002635
2636 EmulateInstruction::Context context;
2637 context.type = EmulateInstruction::eContextImmediate;
2638 context.SetNoArgs();
2639 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2640 return false;
2641
2642 return true;
2643}
2644
2645// Compare (immediate) subtracts an immediate value from a register value.
2646// It updates the condition flags based on the result, and discards the result.
2647bool
2648EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002649{
2650#if 0
2651 // ARM pseudo code...
2652 if ConditionPassed() then
2653 EncodingSpecificOperations();
2654 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2655 APSR.N = result<31>;
2656 APSR.Z = IsZeroBit(result);
2657 APSR.C = carry;
2658 APSR.V = overflow;
2659#endif
2660
2661 bool success = false;
2662 const uint32_t opcode = OpcodeAsUnsigned (&success);
2663 if (!success)
2664 return false;
2665
2666 uint32_t Rn; // the first operand
2667 uint32_t imm32; // the immediate value to be compared with
2668 switch (encoding) {
2669 case eEncodingT1:
2670 Rn = Bits32(opcode, 10, 8);
2671 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002672 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002673 case eEncodingT2:
2674 Rn = Bits32(opcode, 19, 16);
2675 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2676 if (Rn == 15)
2677 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002678 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002679 case eEncodingA1:
2680 Rn = Bits32(opcode, 19, 16);
2681 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002682 break;
2683 default:
2684 return false;
2685 }
2686 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002687 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002688 if (!success)
2689 return false;
2690
Johnny Chen10530c22011-02-17 22:37:12 +00002691 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2692
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002693 EmulateInstruction::Context context;
2694 context.type = EmulateInstruction::eContextImmediate;
2695 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002696 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2697 return false;
2698
Johnny Chend4dc4442011-02-11 02:02:56 +00002699 return true;
2700}
2701
Johnny Chen34075cb2011-02-22 01:56:31 +00002702// Compare (register) subtracts an optionally-shifted register value from a register value.
2703// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002704bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002705EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002706{
2707#if 0
2708 // ARM pseudo code...
2709 if ConditionPassed() then
2710 EncodingSpecificOperations();
2711 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2712 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2713 APSR.N = result<31>;
2714 APSR.Z = IsZeroBit(result);
2715 APSR.C = carry;
2716 APSR.V = overflow;
2717#endif
2718
2719 bool success = false;
2720 const uint32_t opcode = OpcodeAsUnsigned (&success);
2721 if (!success)
2722 return false;
2723
2724 uint32_t Rn; // the first operand
2725 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002726 ARM_ShifterType shift_t;
2727 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002728 switch (encoding) {
2729 case eEncodingT1:
2730 Rn = Bits32(opcode, 2, 0);
2731 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002732 shift_t = SRType_LSL;
2733 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002734 break;
2735 case eEncodingT2:
2736 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2737 Rm = Bits32(opcode, 6, 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 if (Rn < 8 && Rm < 8)
2741 return false;
2742 if (Rn == 15 || Rm == 15)
2743 return false;
2744 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002745 case eEncodingA1:
2746 Rn = Bits32(opcode, 19, 16);
2747 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002748 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002749 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002750 default:
2751 return false;
2752 }
2753 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002754 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002755 if (!success)
2756 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002757
Johnny Chene4a4d302011-02-11 21:53:58 +00002758 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002759 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002760 if (!success)
2761 return false;
2762
Johnny Chen34075cb2011-02-22 01:56:31 +00002763 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2764 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002765
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002766 EmulateInstruction::Context context;
2767 context.type = EmulateInstruction::eContextImmediate;
2768 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002769 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2770 return false;
2771
Johnny Chene4a4d302011-02-11 21:53:58 +00002772 return true;
2773}
2774
Johnny Chen82f16aa2011-02-15 20:10:55 +00002775// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2776// shifting in copies of its sign bit, and writes the result to the destination register. It can
2777// optionally update the condition flags based on the result.
2778bool
2779EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2780{
2781#if 0
2782 // ARM pseudo code...
2783 if ConditionPassed() then
2784 EncodingSpecificOperations();
2785 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2786 if d == 15 then // Can only occur for ARM encoding
2787 ALUWritePC(result); // setflags is always FALSE here
2788 else
2789 R[d] = result;
2790 if setflags then
2791 APSR.N = result<31>;
2792 APSR.Z = IsZeroBit(result);
2793 APSR.C = carry;
2794 // APSR.V unchanged
2795#endif
2796
Johnny Chen41a0a152011-02-16 01:27:54 +00002797 return EmulateShiftImm(encoding, SRType_ASR);
2798}
2799
2800// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2801// shifting in copies of its sign bit, and writes the result to the destination register.
2802// The variable number of bits is read from the bottom byte of a register. It can optionally update
2803// the condition flags based on the result.
2804bool
2805EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2806{
2807#if 0
2808 // ARM pseudo code...
2809 if ConditionPassed() then
2810 EncodingSpecificOperations();
2811 shift_n = UInt(R[m]<7:0>);
2812 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2813 R[d] = result;
2814 if setflags then
2815 APSR.N = result<31>;
2816 APSR.Z = IsZeroBit(result);
2817 APSR.C = carry;
2818 // APSR.V unchanged
2819#endif
2820
2821 return EmulateShiftReg(encoding, SRType_ASR);
2822}
2823
2824// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2825// shifting in zeros, and writes the result to the destination register. It can optionally
2826// update the condition flags based on the result.
2827bool
2828EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2829{
2830#if 0
2831 // ARM pseudo code...
2832 if ConditionPassed() then
2833 EncodingSpecificOperations();
2834 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2835 if d == 15 then // Can only occur for ARM encoding
2836 ALUWritePC(result); // setflags is always FALSE here
2837 else
2838 R[d] = result;
2839 if setflags then
2840 APSR.N = result<31>;
2841 APSR.Z = IsZeroBit(result);
2842 APSR.C = carry;
2843 // APSR.V unchanged
2844#endif
2845
2846 return EmulateShiftImm(encoding, SRType_LSL);
2847}
2848
2849// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2850// shifting in zeros, and writes the result to the destination register. The variable number
2851// of bits is read from the bottom byte of a register. It can optionally update the condition
2852// flags based on the result.
2853bool
2854EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2855{
2856#if 0
2857 // ARM pseudo code...
2858 if ConditionPassed() then
2859 EncodingSpecificOperations();
2860 shift_n = UInt(R[m]<7:0>);
2861 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2862 R[d] = result;
2863 if setflags then
2864 APSR.N = result<31>;
2865 APSR.Z = IsZeroBit(result);
2866 APSR.C = carry;
2867 // APSR.V unchanged
2868#endif
2869
2870 return EmulateShiftReg(encoding, SRType_LSL);
2871}
2872
2873// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2874// shifting in zeros, and writes the result to the destination register. It can optionally
2875// update the condition flags based on the result.
2876bool
2877EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2878{
2879#if 0
2880 // ARM pseudo code...
2881 if ConditionPassed() then
2882 EncodingSpecificOperations();
2883 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2884 if d == 15 then // Can only occur for ARM encoding
2885 ALUWritePC(result); // setflags is always FALSE here
2886 else
2887 R[d] = result;
2888 if setflags then
2889 APSR.N = result<31>;
2890 APSR.Z = IsZeroBit(result);
2891 APSR.C = carry;
2892 // APSR.V unchanged
2893#endif
2894
2895 return EmulateShiftImm(encoding, SRType_LSR);
2896}
2897
2898// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2899// shifting in zeros, and writes the result to the destination register. The variable number
2900// of bits is read from the bottom byte of a register. It can optionally update the condition
2901// flags based on the result.
2902bool
2903EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2904{
2905#if 0
2906 // ARM pseudo code...
2907 if ConditionPassed() then
2908 EncodingSpecificOperations();
2909 shift_n = UInt(R[m]<7:0>);
2910 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2911 R[d] = result;
2912 if setflags then
2913 APSR.N = result<31>;
2914 APSR.Z = IsZeroBit(result);
2915 APSR.C = carry;
2916 // APSR.V unchanged
2917#endif
2918
2919 return EmulateShiftReg(encoding, SRType_LSR);
2920}
2921
Johnny Cheneeab4852011-02-16 22:14:44 +00002922// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2923// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2924// It can optionally update the condition flags based on the result.
2925bool
2926EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2927{
2928#if 0
2929 // ARM pseudo code...
2930 if ConditionPassed() then
2931 EncodingSpecificOperations();
2932 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2933 if d == 15 then // Can only occur for ARM encoding
2934 ALUWritePC(result); // setflags is always FALSE here
2935 else
2936 R[d] = result;
2937 if setflags then
2938 APSR.N = result<31>;
2939 APSR.Z = IsZeroBit(result);
2940 APSR.C = carry;
2941 // APSR.V unchanged
2942#endif
2943
2944 return EmulateShiftImm(encoding, SRType_ROR);
2945}
2946
2947// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2948// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2949// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2950// flags based on the result.
2951bool
2952EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2953{
2954#if 0
2955 // ARM pseudo code...
2956 if ConditionPassed() then
2957 EncodingSpecificOperations();
2958 shift_n = UInt(R[m]<7:0>);
2959 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2960 R[d] = result;
2961 if setflags then
2962 APSR.N = result<31>;
2963 APSR.Z = IsZeroBit(result);
2964 APSR.C = carry;
2965 // APSR.V unchanged
2966#endif
2967
2968 return EmulateShiftReg(encoding, SRType_ROR);
2969}
2970
2971// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2972// with the carry flag shifted into bit [31].
2973//
2974// RRX can optionally update the condition flags based on the result.
2975// In that case, bit [0] is shifted into the carry flag.
2976bool
2977EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2978{
2979#if 0
2980 // ARM pseudo code...
2981 if ConditionPassed() then
2982 EncodingSpecificOperations();
2983 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2984 if d == 15 then // Can only occur for ARM encoding
2985 ALUWritePC(result); // setflags is always FALSE here
2986 else
2987 R[d] = result;
2988 if setflags then
2989 APSR.N = result<31>;
2990 APSR.Z = IsZeroBit(result);
2991 APSR.C = carry;
2992 // APSR.V unchanged
2993#endif
2994
2995 return EmulateShiftImm(encoding, SRType_RRX);
2996}
2997
Johnny Chen41a0a152011-02-16 01:27:54 +00002998bool
2999EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
3000{
3001 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
3002
Johnny Chen82f16aa2011-02-15 20:10:55 +00003003 bool success = false;
3004 const uint32_t opcode = OpcodeAsUnsigned (&success);
3005 if (!success)
3006 return false;
3007
3008 if (ConditionPassed())
3009 {
Johnny Chene7f89532011-02-15 23:22:46 +00003010 uint32_t Rd; // the destination register
3011 uint32_t Rm; // the first operand register
3012 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003013 uint32_t carry; // the carry bit after the shift operation
3014 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003015
3016 // Special case handling!
3017 // A8.6.139 ROR (immediate) -- Encoding T1
3018 if (shift_type == SRType_ROR && encoding == eEncodingT1)
3019 {
3020 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3021 // have the same decoding of bit fields as the other Thumb2 shift operations.
3022 encoding = eEncodingT2;
3023 }
3024
Johnny Chen82f16aa2011-02-15 20:10:55 +00003025 switch (encoding) {
3026 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003027 // Due to the above special case handling!
3028 assert(shift_type != SRType_ROR);
3029
Johnny Chen82f16aa2011-02-15 20:10:55 +00003030 Rd = Bits32(opcode, 2, 0);
3031 Rm = Bits32(opcode, 5, 3);
3032 setflags = !InITBlock();
3033 imm5 = Bits32(opcode, 10, 6);
3034 break;
3035 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003036 // A8.6.141 RRX
3037 assert(shift_type != SRType_RRX);
3038
Johnny Chen82f16aa2011-02-15 20:10:55 +00003039 Rd = Bits32(opcode, 11, 8);
3040 Rm = Bits32(opcode, 3, 0);
3041 setflags = BitIsSet(opcode, 20);
3042 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3043 if (BadReg(Rd) || BadReg(Rm))
3044 return false;
3045 break;
3046 case eEncodingA1:
3047 Rd = Bits32(opcode, 15, 12);
3048 Rm = Bits32(opcode, 3, 0);
3049 setflags = BitIsSet(opcode, 20);
3050 imm5 = Bits32(opcode, 11, 7);
3051 break;
3052 default:
3053 return false;
3054 }
3055
Johnny Cheneeab4852011-02-16 22:14:44 +00003056 // A8.6.139 ROR (immediate)
3057 if (shift_type == SRType_ROR && imm5 == 0)
3058 shift_type = SRType_RRX;
3059
Johnny Chen82f16aa2011-02-15 20:10:55 +00003060 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003061 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003062 if (!success)
3063 return false;
3064
Johnny Cheneeab4852011-02-16 22:14:44 +00003065 // Decode the shift amount if not RRX.
3066 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003067
Johnny Chene97c0d52011-02-18 19:32:20 +00003068 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003069
3070 // The context specifies that an immediate is to be moved into Rd.
3071 EmulateInstruction::Context context;
3072 context.type = EmulateInstruction::eContextImmediate;
3073 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003074
Johnny Chen10530c22011-02-17 22:37:12 +00003075 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003076 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003077 }
3078 return true;
3079}
3080
Johnny Chene7f89532011-02-15 23:22:46 +00003081bool
Johnny Chen41a0a152011-02-16 01:27:54 +00003082EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003083{
Johnny Chen41a0a152011-02-16 01:27:54 +00003084 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003085
3086 bool success = false;
3087 const uint32_t opcode = OpcodeAsUnsigned (&success);
3088 if (!success)
3089 return false;
3090
3091 if (ConditionPassed())
3092 {
3093 uint32_t Rd; // the destination register
3094 uint32_t Rn; // the first operand register
3095 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3096 uint32_t carry; // the carry bit after the shift operation
3097 bool setflags;
3098 switch (encoding) {
3099 case eEncodingT1:
3100 Rd = Bits32(opcode, 2, 0);
3101 Rn = Rd;
3102 Rm = Bits32(opcode, 5, 3);
3103 setflags = !InITBlock();
3104 break;
3105 case eEncodingT2:
3106 Rd = Bits32(opcode, 11, 8);
3107 Rn = Bits32(opcode, 19, 16);
3108 Rm = Bits32(opcode, 3, 0);
3109 setflags = BitIsSet(opcode, 20);
3110 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3111 return false;
3112 break;
3113 case eEncodingA1:
3114 Rd = Bits32(opcode, 15, 12);
3115 Rn = Bits32(opcode, 3, 0);
3116 Rm = Bits32(opcode, 11, 8);
3117 setflags = BitIsSet(opcode, 20);
3118 if (Rd == 15 || Rn == 15 || Rm == 15)
3119 return false;
3120 break;
3121 default:
3122 return false;
3123 }
3124
3125 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003126 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003127 if (!success)
3128 return false;
3129 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003130 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003131 if (!success)
3132 return false;
3133
3134 // Get the shift amount.
3135 uint32_t amt = Bits32(val, 7, 0);
3136
Johnny Chene97c0d52011-02-18 19:32:20 +00003137 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003138
3139 // The context specifies that an immediate is to be moved into Rd.
3140 EmulateInstruction::Context context;
3141 context.type = EmulateInstruction::eContextImmediate;
3142 context.SetNoArgs ();
3143
Johnny Chen10530c22011-02-17 22:37:12 +00003144 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003145 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003146 }
3147 return true;
3148}
3149
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003150// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003151// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003152// can be written back to the base register.
3153bool
3154EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
3155{
3156#if 0
3157 // ARM pseudo code...
3158 if ConditionPassed()
3159 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3160 address = R[n];
3161
3162 for i = 0 to 14
3163 if registers<i> == '1' then
3164 R[i] = MemA[address, 4]; address = address + 4;
3165 if registers<15> == '1' then
3166 LoadWritePC (MemA[address, 4]);
3167
3168 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3169 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3170
3171#endif
3172
3173 bool success = false;
3174 const uint32_t opcode = OpcodeAsUnsigned (&success);
3175 if (!success)
3176 return false;
3177
3178 if (ConditionPassed())
3179 {
3180 uint32_t n;
3181 uint32_t registers = 0;
3182 bool wback;
3183 const uint32_t addr_byte_size = GetAddressByteSize();
3184 switch (encoding)
3185 {
3186 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003187 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003188 n = Bits32 (opcode, 10, 8);
3189 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003190 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003191 wback = BitIsClear (registers, n);
3192 // if BitCount(registers) < 1 then UNPREDICTABLE;
3193 if (BitCount(registers) < 1)
3194 return false;
3195 break;
3196 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003197 // if W == ’1’ && Rn == ’1101’ then SEE POP;
3198 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003199 n = Bits32 (opcode, 19, 16);
3200 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003201 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003202 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003203
3204 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003205 if ((n == 15)
3206 || (BitCount (registers) < 2)
3207 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3208 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003209
3210 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003211 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003212 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003213
3214 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003215 if (wback
3216 && BitIsSet (registers, n))
3217 return false;
3218 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003219
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003220 case eEncodingA1:
3221 n = Bits32 (opcode, 19, 16);
3222 registers = Bits32 (opcode, 15, 0);
3223 wback = BitIsSet (opcode, 21);
3224 if ((n == 15)
3225 || (BitCount (registers) < 1))
3226 return false;
3227 break;
3228 default:
3229 return false;
3230 }
3231
3232 int32_t offset = 0;
3233 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3234 if (!success)
3235 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003236
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003237 EmulateInstruction::Context context;
3238 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3239 Register dwarf_reg;
3240 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3241 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003242
3243 for (int i = 0; i < 14; ++i)
3244 {
3245 if (BitIsSet (registers, i))
3246 {
Caroline Tice85aab332011-02-08 23:56:10 +00003247 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003248 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003249 if (wback && (n == 13)) // Pop Instruction
3250 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3251
3252 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003253 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003254 if (!success)
3255 return false;
3256
3257 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3258 return false;
3259
3260 offset += addr_byte_size;
3261 }
3262 }
3263
3264 if (BitIsSet (registers, 15))
3265 {
3266 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003267 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003268 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003269 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003270 if (!success)
3271 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003272 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003273 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003274 return false;
3275 }
3276
3277 if (wback && BitIsClear (registers, n))
3278 {
Caroline Ticefa172202011-02-11 22:49:54 +00003279 // R[n] = R[n] + 4 * BitCount (registers)
3280 int32_t offset = addr_byte_size * BitCount (registers);
3281 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003282 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003283
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003284 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3285 return false;
3286 }
3287 if (wback && BitIsSet (registers, n))
3288 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003289 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003290 }
3291 return true;
3292}
Caroline Tice713c2662011-02-11 17:59:55 +00003293
3294// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3295// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3296// can optionally be written back tot he base registers.
3297bool
3298EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
3299{
3300#if 0
3301 // ARM pseudo code...
3302 if ConditionPassed() then
3303 EncodingSpecificOperations();
3304 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003305
Caroline Tice713c2662011-02-11 17:59:55 +00003306 for i = 0 to 14
3307 if registers<i> == ’1’ then
3308 R[i] = MemA[address,4]; address = address + 4;
3309
3310 if registers<15> == ’1’ then
3311 LoadWritePC(MemA[address,4]);
3312
3313 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3314 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3315#endif
3316
3317 bool success = false;
3318 const uint32_t opcode = OpcodeAsUnsigned (&success);
3319 if (!success)
3320 return false;
3321
3322 if (ConditionPassed())
3323 {
3324 uint32_t n;
3325 uint32_t registers = 0;
3326 bool wback;
3327 const uint32_t addr_byte_size = GetAddressByteSize();
3328
3329 // EncodingSpecificOperations();
3330 switch (encoding)
3331 {
3332 case eEncodingA1:
3333 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3334 n = Bits32 (opcode, 19, 16);
3335 registers = Bits32 (opcode, 15, 0);
3336 wback = BitIsSet (opcode, 21);
3337
3338 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3339 if ((n == 15) || (BitCount (registers) < 1))
3340 return false;
3341
3342 break;
3343
3344 default:
3345 return false;
3346 }
3347 // address = R[n] - 4*BitCount(registers) + 4;
3348
3349 int32_t offset = 0;
3350 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3351
3352 if (!success)
3353 return false;
3354
3355 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3356
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003357 EmulateInstruction::Context context;
3358 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3359 Register dwarf_reg;
3360 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3361 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003362
3363 // for i = 0 to 14
3364 for (int i = 0; i < 14; ++i)
3365 {
3366 // if registers<i> == ’1’ then
3367 if (BitIsSet (registers, i))
3368 {
3369 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003370 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003371 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003372 if (!success)
3373 return false;
3374 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3375 return false;
3376 offset += addr_byte_size;
3377 }
3378 }
3379
3380 // if registers<15> == ’1’ then
3381 // LoadWritePC(MemA[address,4]);
3382 if (BitIsSet (registers, 15))
3383 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003384 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003385 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003386 if (!success)
3387 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003388 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003389 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003390 return false;
3391 }
3392
3393 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3394 if (wback && BitIsClear (registers, n))
3395 {
Caroline Tice713c2662011-02-11 17:59:55 +00003396 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3397 if (!success)
3398 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003399
3400 offset = (addr_byte_size * BitCount (registers)) * -1;
3401 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003402 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003403 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003404 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3405 return false;
3406 }
3407
3408 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3409 if (wback && BitIsSet (registers, n))
3410 return WriteBits32Unknown (n);
3411 }
3412 return true;
3413}
3414
3415// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3416// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3417// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003418bool
3419EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3420{
3421#if 0
3422 // ARM pseudo code...
3423 if ConditionPassed() then
3424 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3425 address = R[n] - 4*BitCount(registers);
3426
3427 for i = 0 to 14
3428 if registers<i> == ’1’ then
3429 R[i] = MemA[address,4]; address = address + 4;
3430 if registers<15> == ’1’ then
3431 LoadWritePC(MemA[address,4]);
3432
3433 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3434 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3435#endif
3436
3437 bool success = false;
3438 const uint32_t opcode = OpcodeAsUnsigned (&success);
3439 if (!success)
3440 return false;
3441
3442 if (ConditionPassed())
3443 {
3444 uint32_t n;
3445 uint32_t registers = 0;
3446 bool wback;
3447 const uint32_t addr_byte_size = GetAddressByteSize();
3448 switch (encoding)
3449 {
3450 case eEncodingT1:
3451 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3452 n = Bits32 (opcode, 19, 16);
3453 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003454 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003455 wback = BitIsSet (opcode, 21);
3456
3457 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3458 if ((n == 15)
3459 || (BitCount (registers) < 2)
3460 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3461 return false;
3462
3463 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003464 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003465 return false;
3466
3467 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3468 if (wback && BitIsSet (registers, n))
3469 return false;
3470
3471 break;
3472
3473 case eEncodingA1:
3474 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3475 n = Bits32 (opcode, 19, 16);
3476 registers = Bits32 (opcode, 15, 0);
3477 wback = BitIsSet (opcode, 21);
3478
3479 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3480 if ((n == 15) || (BitCount (registers) < 1))
3481 return false;
3482
3483 break;
3484
3485 default:
3486 return false;
3487 }
3488
Caroline Tice713c2662011-02-11 17:59:55 +00003489 // address = R[n] - 4*BitCount(registers);
3490
Caroline Tice0b29e242011-02-08 23:16:02 +00003491 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003492 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3493
3494 if (!success)
3495 return false;
3496
3497 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003498 EmulateInstruction::Context context;
3499 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3500 Register dwarf_reg;
3501 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3502 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003503
3504 for (int i = 0; i < 14; ++i)
3505 {
3506 if (BitIsSet (registers, i))
3507 {
3508 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003509 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003510 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003511 if (!success)
3512 return false;
3513
3514 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3515 return false;
3516
3517 offset += addr_byte_size;
3518 }
3519 }
3520
3521 // if registers<15> == ’1’ then
3522 // LoadWritePC(MemA[address,4]);
3523 if (BitIsSet (registers, 15))
3524 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003525 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003526 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003527 if (!success)
3528 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003529 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003530 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003531 return false;
3532 }
3533
3534 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3535 if (wback && BitIsClear (registers, n))
3536 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003537 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3538 if (!success)
3539 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003540
3541 offset = (addr_byte_size * BitCount (registers)) * -1;
3542 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003543 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003544 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003545 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3546 return false;
3547 }
3548
3549 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3550 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003551 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003552 }
3553 return true;
3554}
Caroline Tice85aab332011-02-08 23:56:10 +00003555
Caroline Tice713c2662011-02-11 17:59:55 +00003556// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3557// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3558// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003559bool
3560EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3561{
3562#if 0
3563 if ConditionPassed() then
3564 EncodingSpecificOperations();
3565 address = R[n] + 4;
3566
3567 for i = 0 to 14
3568 if registers<i> == ’1’ then
3569 R[i] = MemA[address,4]; address = address + 4;
3570 if registers<15> == ’1’ then
3571 LoadWritePC(MemA[address,4]);
3572
3573 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3574 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3575#endif
3576
3577 bool success = false;
3578 const uint32_t opcode = OpcodeAsUnsigned (&success);
3579 if (!success)
3580 return false;
3581
3582 if (ConditionPassed())
3583 {
3584 uint32_t n;
3585 uint32_t registers = 0;
3586 bool wback;
3587 const uint32_t addr_byte_size = GetAddressByteSize();
3588 switch (encoding)
3589 {
3590 case eEncodingA1:
3591 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3592 n = Bits32 (opcode, 19, 16);
3593 registers = Bits32 (opcode, 15, 0);
3594 wback = BitIsSet (opcode, 21);
3595
3596 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3597 if ((n == 15) || (BitCount (registers) < 1))
3598 return false;
3599
3600 break;
3601 default:
3602 return false;
3603 }
3604 // address = R[n] + 4;
3605
3606 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003607 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3608
3609 if (!success)
3610 return false;
3611
3612 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003613
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003614 EmulateInstruction::Context context;
3615 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3616 Register dwarf_reg;
3617 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3618 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003619
3620 for (int i = 0; i < 14; ++i)
3621 {
3622 if (BitIsSet (registers, i))
3623 {
3624 // R[i] = MemA[address,4]; address = address + 4;
3625
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003626 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003627 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003628 if (!success)
3629 return false;
3630
3631 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3632 return false;
3633
3634 offset += addr_byte_size;
3635 }
3636 }
3637
3638 // if registers<15> == ’1’ then
3639 // LoadWritePC(MemA[address,4]);
3640 if (BitIsSet (registers, 15))
3641 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003642 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003643 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003644 if (!success)
3645 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003646 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003647 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003648 return false;
3649 }
3650
3651 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3652 if (wback && BitIsClear (registers, n))
3653 {
Caroline Tice85aab332011-02-08 23:56:10 +00003654 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3655 if (!success)
3656 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003657
3658 offset = addr_byte_size * BitCount (registers);
3659 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003660 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003661 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003662 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3663 return false;
3664 }
3665
3666 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3667 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003668 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003669 }
3670 return true;
3671}
Caroline Tice0b29e242011-02-08 23:16:02 +00003672
Johnny Chenef21b592011-02-10 01:52:38 +00003673// Load Register (immediate) calculates an address from a base register value and
3674// an immediate offset, loads a word from memory, and writes to a register.
3675// LDR (immediate, Thumb)
3676bool
3677EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3678{
3679#if 0
3680 // ARM pseudo code...
3681 if (ConditionPassed())
3682 {
3683 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3684 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3685 address = if index then offset_addr else R[n];
3686 data = MemU[address,4];
3687 if wback then R[n] = offset_addr;
3688 if t == 15 then
3689 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3690 elsif UnalignedSupport() || address<1:0> = '00' then
3691 R[t] = data;
3692 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3693 }
3694#endif
3695
3696 bool success = false;
3697 const uint32_t opcode = OpcodeAsUnsigned (&success);
3698 if (!success)
3699 return false;
3700
3701 if (ConditionPassed())
3702 {
3703 uint32_t Rt; // the destination register
3704 uint32_t Rn; // the base register
3705 uint32_t imm32; // the immediate offset used to form the address
3706 addr_t offset_addr; // the offset address
3707 addr_t address; // the calculated address
3708 uint32_t data; // the literal data value from memory load
3709 bool add, index, wback;
3710 switch (encoding) {
3711 case eEncodingT1:
3712 Rt = Bits32(opcode, 5, 3);
3713 Rn = Bits32(opcode, 2, 0);
3714 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3715 // index = TRUE; add = TRUE; wback = FALSE
3716 add = true;
3717 index = true;
3718 wback = false;
3719 break;
3720 default:
3721 return false;
3722 }
3723 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3724 if (!success)
3725 return false;
3726 if (add)
3727 offset_addr = base + imm32;
3728 else
3729 offset_addr = base - imm32;
3730
3731 address = (index ? offset_addr : base);
3732
3733 if (wback)
3734 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003735 EmulateInstruction::Context ctx;
3736 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3737 Register dwarf_reg;
3738 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3739 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3740
Johnny Chenef21b592011-02-10 01:52:38 +00003741 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3742 return false;
3743 }
3744
3745 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003746 EmulateInstruction::Context context;
3747 context.type = EmulateInstruction::eContextImmediate;
3748 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003749
3750 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003751 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003752 if (!success)
3753 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003754
3755 if (Rt == 15)
3756 {
3757 if (Bits32(address, 1, 0) == 0)
3758 {
Johnny Chen668b4512011-02-15 21:08:58 +00003759 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003760 return false;
3761 }
3762 else
3763 return false;
3764 }
3765 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3766 {
3767 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3768 return false;
3769 }
3770 else
3771 return false;
3772 }
3773 return true;
3774}
3775
Caroline Ticeaf556562011-02-15 18:42:15 +00003776// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3777// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3778// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003779bool
3780EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3781{
3782#if 0
3783 if ConditionPassed() then
3784 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3785 address = R[n];
3786
3787 for i = 0 to 14
3788 if registers<i> == ’1’ then
3789 if i == n && wback && i != LowestSetBit(registers) then
3790 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3791 else
3792 MemA[address,4] = R[i];
3793 address = address + 4;
3794
3795 if registers<15> == ’1’ then // Only possible for encoding A1
3796 MemA[address,4] = PCStoreValue();
3797 if wback then R[n] = R[n] + 4*BitCount(registers);
3798#endif
3799
3800 bool success = false;
3801 const uint32_t opcode = OpcodeAsUnsigned (&success);
3802 if (!success)
3803 return false;
3804
3805 if (ConditionPassed ())
3806 {
3807 uint32_t n;
3808 uint32_t registers = 0;
3809 bool wback;
3810 const uint32_t addr_byte_size = GetAddressByteSize();
3811
3812 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3813 switch (encoding)
3814 {
3815 case eEncodingT1:
3816 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3817 n = Bits32 (opcode, 10, 8);
3818 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003819 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003820 wback = true;
3821
3822 // if BitCount(registers) < 1 then UNPREDICTABLE;
3823 if (BitCount (registers) < 1)
3824 return false;
3825
3826 break;
3827
3828 case eEncodingT2:
3829 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3830 n = Bits32 (opcode, 19, 16);
3831 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003832 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003833 wback = BitIsSet (opcode, 21);
3834
3835 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3836 if ((n == 15) || (BitCount (registers) < 2))
3837 return false;
3838
3839 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3840 if (wback && BitIsSet (registers, n))
3841 return false;
3842
3843 break;
3844
3845 case eEncodingA1:
3846 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3847 n = Bits32 (opcode, 19, 16);
3848 registers = Bits32 (opcode, 15, 0);
3849 wback = BitIsSet (opcode, 21);
3850
3851 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3852 if ((n == 15) || (BitCount (registers) < 1))
3853 return false;
3854
3855 break;
3856
3857 default:
3858 return false;
3859 }
3860
3861 // address = R[n];
3862 int32_t offset = 0;
3863 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3864 if (!success)
3865 return false;
3866
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003867 EmulateInstruction::Context context;
3868 context.type = EmulateInstruction::eContextRegisterStore;
3869 Register base_reg;
3870 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003871
3872 // for i = 0 to 14
3873 for (int i = 0; i < 14; ++i)
3874 {
3875 int lowest_set_bit = 14;
3876 // if registers<i> == ’1’ then
3877 if (BitIsSet (registers, i))
3878 {
3879 if (i < lowest_set_bit)
3880 lowest_set_bit = i;
3881 // if i == n && wback && i != LowestSetBit(registers) then
3882 if ((i == n) && wback && (i != lowest_set_bit))
3883 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3884 WriteBits32UnknownToMemory (address + offset);
3885 else
3886 {
3887 // MemA[address,4] = R[i];
3888 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3889 if (!success)
3890 return false;
3891
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003892 Register data_reg;
3893 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3894 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003895 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003896 return false;
3897 }
3898
3899 // address = address + 4;
3900 offset += addr_byte_size;
3901 }
3902 }
3903
3904 // if registers<15> == ’1’ then // Only possible for encoding A1
3905 // MemA[address,4] = PCStoreValue();
3906 if (BitIsSet (registers, 15))
3907 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003908 Register pc_reg;
3909 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3910 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003911 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3912 if (!success)
3913 return false;
3914
Caroline Ticecc96eb52011-02-17 19:20:40 +00003915 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003916 return false;
3917 }
3918
3919 // if wback then R[n] = R[n] + 4*BitCount(registers);
3920 if (wback)
3921 {
3922 offset = addr_byte_size * BitCount (registers);
3923 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003924 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003925 addr_t data = address + offset;
3926 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3927 return false;
3928 }
3929 }
3930 return true;
3931}
3932
Caroline Ticeaf556562011-02-15 18:42:15 +00003933// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3934// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3935// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003936bool
3937EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3938{
3939#if 0
3940 if ConditionPassed() then
3941 EncodingSpecificOperations();
3942 address = R[n] - 4*BitCount(registers) + 4;
3943
3944 for i = 0 to 14
3945 if registers<i> == ’1’ then
3946 if i == n && wback && i != LowestSetBit(registers) then
3947 MemA[address,4] = bits(32) UNKNOWN;
3948 else
3949 MemA[address,4] = R[i];
3950 address = address + 4;
3951
3952 if registers<15> == ’1’ then
3953 MemA[address,4] = PCStoreValue();
3954
3955 if wback then R[n] = R[n] - 4*BitCount(registers);
3956#endif
3957
3958 bool success = false;
3959 const uint32_t opcode = OpcodeAsUnsigned (&success);
3960 if (!success)
3961 return false;
3962
3963 if (ConditionPassed ())
3964 {
3965 uint32_t n;
3966 uint32_t registers = 0;
3967 bool wback;
3968 const uint32_t addr_byte_size = GetAddressByteSize();
3969
3970 // EncodingSpecificOperations();
3971 switch (encoding)
3972 {
3973 case eEncodingA1:
3974 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3975 n = Bits32 (opcode, 19, 16);
3976 registers = Bits32 (opcode, 15, 0);
3977 wback = BitIsSet (opcode, 21);
3978
3979 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3980 if ((n == 15) || (BitCount (registers) < 1))
3981 return false;
3982 break;
3983 default:
3984 return false;
3985 }
3986
3987 // address = R[n] - 4*BitCount(registers) + 4;
3988 int32_t offset = 0;
3989 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3990 if (!success)
3991 return false;
3992
3993 address = address - (addr_byte_size * BitCount (registers)) + 4;
3994
3995 EmulateInstruction::Context context;
3996 context.type = EmulateInstruction::eContextRegisterStore;
3997 Register base_reg;
3998 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3999
4000 // for i = 0 to 14
4001 for (int i = 0; i < 14; ++i)
4002 {
4003 int lowest_bit_set = 14;
4004 // if registers<i> == ’1’ then
4005 if (BitIsSet (registers, i))
4006 {
4007 if (i < lowest_bit_set)
4008 lowest_bit_set = i;
4009 //if i == n && wback && i != LowestSetBit(registers) then
4010 if ((i == n) && wback && (i != lowest_bit_set))
4011 // MemA[address,4] = bits(32) UNKNOWN;
4012 WriteBits32UnknownToMemory (address + offset);
4013 else
4014 {
4015 // MemA[address,4] = R[i];
4016 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4017 if (!success)
4018 return false;
4019
4020 Register data_reg;
4021 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4022 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004023 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004024 return false;
4025 }
4026
4027 // address = address + 4;
4028 offset += addr_byte_size;
4029 }
4030 }
4031
4032 // if registers<15> == ’1’ then
4033 // MemA[address,4] = PCStoreValue();
4034 if (BitIsSet (registers, 15))
4035 {
4036 Register pc_reg;
4037 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4038 context.SetRegisterPlusOffset (pc_reg, 8);
4039 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4040 if (!success)
4041 return false;
4042
Caroline Ticecc96eb52011-02-17 19:20:40 +00004043 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004044 return false;
4045 }
4046
4047 // if wback then R[n] = R[n] - 4*BitCount(registers);
4048 if (wback)
4049 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004050 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004051 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4052 context.SetImmediateSigned (offset);
4053 addr_t data = address + offset;
4054 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4055 return false;
4056 }
4057 }
4058 return true;
4059}
4060
Caroline Ticeaf556562011-02-15 18:42:15 +00004061// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4062// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4063// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004064bool
4065EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
4066{
4067#if 0
4068 if ConditionPassed() then
4069 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4070 address = R[n] - 4*BitCount(registers);
4071
4072 for i = 0 to 14
4073 if registers<i> == ’1’ then
4074 if i == n && wback && i != LowestSetBit(registers) then
4075 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4076 else
4077 MemA[address,4] = R[i];
4078 address = address + 4;
4079
4080 if registers<15> == ’1’ then // Only possible for encoding A1
4081 MemA[address,4] = PCStoreValue();
4082
4083 if wback then R[n] = R[n] - 4*BitCount(registers);
4084#endif
4085
4086
4087 bool success = false;
4088 const uint32_t opcode = OpcodeAsUnsigned (&success);
4089 if (!success)
4090 return false;
4091
4092 if (ConditionPassed ())
4093 {
4094 uint32_t n;
4095 uint32_t registers = 0;
4096 bool wback;
4097 const uint32_t addr_byte_size = GetAddressByteSize();
4098
4099 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4100 switch (encoding)
4101 {
4102 case eEncodingT1:
4103 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
4104 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4105 {
4106 // See PUSH
4107 }
4108 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
4109 n = Bits32 (opcode, 19, 16);
4110 registers = Bits32 (opcode, 15, 0);
4111 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4112 wback = BitIsSet (opcode, 21);
4113 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4114 if ((n == 15) || BitCount (registers) < 2)
4115 return false;
4116 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
4117 if (wback && BitIsSet (registers, n))
4118 return false;
4119 break;
4120
4121 case eEncodingA1:
4122 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4123 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4124 {
4125 // See Push
4126 }
4127 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4128 n = Bits32 (opcode, 19, 16);
4129 registers = Bits32 (opcode, 15, 0);
4130 wback = BitIsSet (opcode, 21);
4131 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4132 if ((n == 15) || BitCount (registers) < 1)
4133 return false;
4134 break;
4135
4136 default:
4137 return false;
4138 }
4139
4140 // address = R[n] - 4*BitCount(registers);
4141
4142 int32_t offset = 0;
4143 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4144 if (!success)
4145 return false;
4146
4147 address = address - (addr_byte_size * BitCount (registers));
4148
4149 EmulateInstruction::Context context;
4150 context.type = EmulateInstruction::eContextRegisterStore;
4151 Register base_reg;
4152 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4153
4154 // for i = 0 to 14
4155 for (int i = 0; i < 14; ++i)
4156 {
4157 uint32_t lowest_set_bit = 14;
4158 // if registers<i> == ’1’ then
4159 if (BitIsSet (registers, i))
4160 {
4161 if (i < lowest_set_bit)
4162 lowest_set_bit = i;
4163 // if i == n && wback && i != LowestSetBit(registers) then
4164 if ((i == n) && wback && (i != lowest_set_bit))
4165 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4166 WriteBits32UnknownToMemory (address + offset);
4167 else
4168 {
4169 // MemA[address,4] = R[i];
4170 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4171 if (!success)
4172 return false;
4173
4174 Register data_reg;
4175 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4176 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004177 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004178 return false;
4179 }
4180
4181 // address = address + 4;
4182 offset += addr_byte_size;
4183 }
4184 }
4185
4186 // if registers<15> == ’1’ then // Only possible for encoding A1
4187 // MemA[address,4] = PCStoreValue();
4188 if (BitIsSet (registers, 15))
4189 {
4190 Register pc_reg;
4191 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4192 context.SetRegisterPlusOffset (pc_reg, 8);
4193 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4194 if (!success)
4195 return false;
4196
Caroline Ticecc96eb52011-02-17 19:20:40 +00004197 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004198 return false;
4199 }
4200
4201 // if wback then R[n] = R[n] - 4*BitCount(registers);
4202 if (wback)
4203 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004204 offset = (addr_byte_size * BitCount (registers)) * -1;
4205 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4206 context.SetImmediateSigned (offset);
4207 addr_t data = address + offset;
4208 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4209 return false;
4210 }
4211 }
4212 return true;
4213}
4214
4215// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4216// from a base register. The consecutive memory locations start just above this address, and the address of the last
4217// of those locations can optionally be written back to the base register.
4218bool
4219EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
4220{
4221#if 0
4222 if ConditionPassed() then
4223 EncodingSpecificOperations();
4224 address = R[n] + 4;
4225
4226 for i = 0 to 14
4227 if registers<i> == ’1’ then
4228 if i == n && wback && i != LowestSetBit(registers) then
4229 MemA[address,4] = bits(32) UNKNOWN;
4230 else
4231 MemA[address,4] = R[i];
4232 address = address + 4;
4233
4234 if registers<15> == ’1’ then
4235 MemA[address,4] = PCStoreValue();
4236
4237 if wback then R[n] = R[n] + 4*BitCount(registers);
4238#endif
4239
4240 bool success = false;
4241 const uint32_t opcode = OpcodeAsUnsigned (&success);
4242 if (!success)
4243 return false;
4244
4245 if (ConditionPassed())
4246 {
4247 uint32_t n;
4248 uint32_t registers = 0;
4249 bool wback;
4250 const uint32_t addr_byte_size = GetAddressByteSize();
4251
4252 // EncodingSpecificOperations();
4253 switch (encoding)
4254 {
4255 case eEncodingA1:
4256 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4257 n = Bits32 (opcode, 19, 16);
4258 registers = Bits32 (opcode, 15, 0);
4259 wback = BitIsSet (opcode, 21);
4260
4261 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4262 if ((n == 15) && (BitCount (registers) < 1))
4263 return false;
4264 break;
4265 default:
4266 return false;
4267 }
4268 // address = R[n] + 4;
4269
4270 int32_t offset = 0;
4271 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4272 if (!success)
4273 return false;
4274
4275 address = address + addr_byte_size;
4276
4277 EmulateInstruction::Context context;
4278 context.type = EmulateInstruction::eContextRegisterStore;
4279 Register base_reg;
4280 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4281
4282 uint32_t lowest_set_bit = 14;
4283 // for i = 0 to 14
4284 for (int i = 0; i < 14; ++i)
4285 {
4286 // if registers<i> == ’1’ then
4287 if (BitIsSet (registers, i))
4288 {
4289 if (i < lowest_set_bit)
4290 lowest_set_bit = i;
4291 // if i == n && wback && i != LowestSetBit(registers) then
4292 if ((i == n) && wback && (i != lowest_set_bit))
4293 // MemA[address,4] = bits(32) UNKNOWN;
4294 WriteBits32UnknownToMemory (address + offset);
4295 // else
4296 else
4297 {
4298 // MemA[address,4] = R[i];
4299 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4300 if (!success)
4301 return false;
4302
4303 Register data_reg;
4304 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4305 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004306 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004307 return false;
4308 }
4309
4310 // address = address + 4;
4311 offset += addr_byte_size;
4312 }
4313 }
4314
4315 // if registers<15> == ’1’ then
4316 // MemA[address,4] = PCStoreValue();
4317 if (BitIsSet (registers, 15))
4318 {
4319 Register pc_reg;
4320 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4321 context.SetRegisterPlusOffset (pc_reg, 8);
4322 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4323 if (!success)
4324 return false;
4325
Caroline Ticecc96eb52011-02-17 19:20:40 +00004326 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004327 return false;
4328 }
4329
4330 // if wback then R[n] = R[n] + 4*BitCount(registers);
4331 if (wback)
4332 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004333 offset = addr_byte_size * BitCount (registers);
4334 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4335 context.SetImmediateSigned (offset);
4336 addr_t data = address + offset;
4337 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4338 return false;
4339 }
4340 }
4341 return true;
4342}
Caroline Tice7fac8572011-02-15 22:53:54 +00004343
4344// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4345// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4346bool
4347EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4348{
4349#if 0
4350 if ConditionPassed() then
4351 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4352 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4353 address = if index then offset_addr else R[n];
4354 if UnalignedSupport() || address<1:0> == ’00’ then
4355 MemU[address,4] = R[t];
4356 else // Can only occur before ARMv7
4357 MemU[address,4] = bits(32) UNKNOWN;
4358 if wback then R[n] = offset_addr;
4359#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004360
Caroline Tice7fac8572011-02-15 22:53:54 +00004361 bool success = false;
4362 const uint32_t opcode = OpcodeAsUnsigned (&success);
4363 if (!success)
4364 return false;
4365
4366 if (ConditionPassed())
4367 {
4368 const uint32_t addr_byte_size = GetAddressByteSize();
4369
4370 uint32_t t;
4371 uint32_t n;
4372 uint32_t imm32;
4373 bool index;
4374 bool add;
4375 bool wback;
4376 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4377 switch (encoding)
4378 {
4379 case eEncodingT1:
4380 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4381 t = Bits32 (opcode, 2, 0);
4382 n = Bits32 (opcode, 5, 3);
4383 imm32 = Bits32 (opcode, 10, 6) << 2;
4384
4385 // index = TRUE; add = TRUE; wback = FALSE;
4386 index = true;
4387 add = false;
4388 wback = false;
4389 break;
4390
4391 case eEncodingT2:
4392 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4393 t = Bits32 (opcode, 10, 8);
4394 n = 13;
4395 imm32 = Bits32 (opcode, 7, 0) << 2;
4396
4397 // index = TRUE; add = TRUE; wback = FALSE;
4398 index = true;
4399 add = true;
4400 wback = false;
4401 break;
4402
4403 case eEncodingT3:
4404 // if Rn == ’1111’ then UNDEFINED;
4405 if (Bits32 (opcode, 19, 16) == 15)
4406 return false;
4407
4408 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4409 t = Bits32 (opcode, 15, 12);
4410 n = Bits32 (opcode, 19, 16);
4411 imm32 = Bits32 (opcode, 11, 0);
4412
4413 // index = TRUE; add = TRUE; wback = FALSE;
4414 index = true;
4415 add = true;
4416 wback = false;
4417
4418 // if t == 15 then UNPREDICTABLE;
4419 if (t == 15)
4420 return false;
4421 break;
4422
4423 case eEncodingT4:
4424 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4425 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4426 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4427 if ((Bits32 (opcode, 19, 16) == 15)
4428 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4429 return false;
4430
4431 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4432 t = Bits32 (opcode, 15, 12);
4433 n = Bits32 (opcode, 19, 16);
4434 imm32 = Bits32 (opcode, 7, 0);
4435
4436 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4437 index = BitIsSet (opcode, 10);
4438 add = BitIsSet (opcode, 9);
4439 wback = BitIsSet (opcode, 8);
4440
4441 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4442 if ((t == 15) || (wback && (n == t)))
4443 return false;
4444 break;
4445
4446 default:
4447 return false;
4448 }
4449
4450 addr_t offset_addr;
4451 addr_t address;
4452
4453 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4454 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4455 if (!success)
4456 return false;
4457
4458 if (add)
4459 offset_addr = base_address + imm32;
4460 else
4461 offset_addr = base_address - imm32;
4462
4463 // address = if index then offset_addr else R[n];
4464 if (index)
4465 address = offset_addr;
4466 else
4467 address = base_address;
4468
4469 EmulateInstruction::Context context;
4470 context.type = eContextRegisterStore;
4471 Register base_reg;
4472 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4473
4474 // if UnalignedSupport() || address<1:0> == ’00’ then
4475 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4476 {
4477 // MemU[address,4] = R[t];
4478 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4479 if (!success)
4480 return false;
4481
4482 Register data_reg;
4483 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4484 int32_t offset = address - base_address;
4485 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004486 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004487 return false;
4488 }
4489 else
4490 {
4491 // MemU[address,4] = bits(32) UNKNOWN;
4492 WriteBits32UnknownToMemory (address);
4493 }
4494
4495 // if wback then R[n] = offset_addr;
4496 if (wback)
4497 {
4498 context.type = eContextRegisterLoad;
4499 context.SetAddress (offset_addr);
4500 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4501 return false;
4502 }
4503 }
4504 return true;
4505}
Caroline Ticeaf556562011-02-15 18:42:15 +00004506
Caroline Tice3fd63e92011-02-16 00:33:43 +00004507// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4508// word from a register to memory. The offset register value can optionally be shifted.
4509bool
4510EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4511{
4512#if 0
4513 if ConditionPassed() then
4514 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4515 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4516 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4517 address = if index then offset_addr else R[n];
4518 if t == 15 then // Only possible for encoding A1
4519 data = PCStoreValue();
4520 else
4521 data = R[t];
4522 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4523 MemU[address,4] = data;
4524 else // Can only occur before ARMv7
4525 MemU[address,4] = bits(32) UNKNOWN;
4526 if wback then R[n] = offset_addr;
4527#endif
4528
4529 bool success = false;
4530 const uint32_t opcode = OpcodeAsUnsigned (&success);
4531 if (!success)
4532 return false;
4533
4534 if (ConditionPassed())
4535 {
4536 const uint32_t addr_byte_size = GetAddressByteSize();
4537
4538 uint32_t t;
4539 uint32_t n;
4540 uint32_t m;
4541 ARM_ShifterType shift_t;
4542 uint32_t shift_n;
4543 bool index;
4544 bool add;
4545 bool wback;
4546
4547 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4548 switch (encoding)
4549 {
4550 case eEncodingT1:
4551 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4552 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4553 t = Bits32 (opcode, 2, 0);
4554 n = Bits32 (opcode, 5, 3);
4555 m = Bits32 (opcode, 8, 6);
4556
4557 // index = TRUE; add = TRUE; wback = FALSE;
4558 index = true;
4559 add = true;
4560 wback = false;
4561
4562 // (shift_t, shift_n) = (SRType_LSL, 0);
4563 shift_t = SRType_LSL;
4564 shift_n = 0;
4565 break;
4566
4567 case eEncodingT2:
4568 // if Rn == ’1111’ then UNDEFINED;
4569 if (Bits32 (opcode, 19, 16) == 15)
4570 return false;
4571
4572 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4573 t = Bits32 (opcode, 15, 12);
4574 n = Bits32 (opcode, 19, 16);
4575 m = Bits32 (opcode, 3, 0);
4576
4577 // index = TRUE; add = TRUE; wback = FALSE;
4578 index = true;
4579 add = true;
4580 wback = false;
4581
4582 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4583 shift_t = SRType_LSL;
4584 shift_n = Bits32 (opcode, 5, 4);
4585
4586 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4587 if ((t == 15) || (BadReg (m)))
4588 return false;
4589 break;
4590
4591 case eEncodingA1:
4592 {
4593 // if P == ’0’ && W == ’1’ then SEE STRT;
4594 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4595 t = Bits32 (opcode, 15, 12);
4596 n = Bits32 (opcode, 19, 16);
4597 m = Bits32 (opcode, 3, 0);
4598
4599 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4600 index = BitIsSet (opcode, 24);
4601 add = BitIsSet (opcode, 23);
4602 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4603
4604 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4605 uint32_t typ = Bits32 (opcode, 6, 5);
4606 uint32_t imm5 = Bits32 (opcode, 11, 7);
4607 shift_n = DecodeImmShift(typ, imm5, shift_t);
4608
4609 // if m == 15 then UNPREDICTABLE;
4610 if (m == 15)
4611 return false;
4612
4613 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4614 if (wback && ((n == 15) || (n == t)))
4615 return false;
4616
4617 break;
4618 }
4619 default:
4620 return false;
4621 }
4622
4623 addr_t offset_addr;
4624 addr_t address;
4625 int32_t offset = 0;
4626
4627 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4628 if (!success)
4629 return false;
4630
4631 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4632 if (!success)
4633 return false;
4634
4635 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004636 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004637
4638 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4639 if (add)
4640 offset_addr = base_address + offset;
4641 else
4642 offset_addr = base_address - offset;
4643
4644 // address = if index then offset_addr else R[n];
4645 if (index)
4646 address = offset_addr;
4647 else
4648 address = base_address;
4649
4650 uint32_t data;
4651 // if t == 15 then // Only possible for encoding A1
4652 if (t == 15)
4653 // data = PCStoreValue();
4654 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4655 else
4656 // data = R[t];
4657 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4658
4659 if (!success)
4660 return false;
4661
4662 EmulateInstruction::Context context;
4663 context.type = eContextRegisterStore;
4664
4665 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4666 if (UnalignedSupport ()
4667 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4668 || CurrentInstrSet() == eModeARM)
4669 {
4670 // MemU[address,4] = data;
4671
4672 Register base_reg;
4673 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4674
4675 Register data_reg;
4676 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4677
4678 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004679 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004680 return false;
4681
4682 }
4683 else
4684 // MemU[address,4] = bits(32) UNKNOWN;
4685 WriteBits32UnknownToMemory (address);
4686
4687 // if wback then R[n] = offset_addr;
4688 if (wback)
4689 {
4690 context.type = eContextRegisterLoad;
4691 context.SetAddress (offset_addr);
4692 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4693 return false;
4694 }
4695
4696 }
4697 return true;
4698}
Caroline Tice73a29de2011-02-16 20:22:22 +00004699
4700bool
4701EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4702{
4703#if 0
4704 if ConditionPassed() then
4705 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4706 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4707 address = if index then offset_addr else R[n];
4708 MemU[address,1] = R[t]<7:0>;
4709 if wback then R[n] = offset_addr;
4710#endif
4711
4712
4713 bool success = false;
4714 const uint32_t opcode = OpcodeAsUnsigned (&success);
4715 if (!success)
4716 return false;
4717
4718 if (ConditionPassed ())
4719 {
4720 uint32_t t;
4721 uint32_t n;
4722 uint32_t imm32;
4723 bool index;
4724 bool add;
4725 bool wback;
4726 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4727 switch (encoding)
4728 {
4729 case eEncodingT1:
4730 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4731 t = Bits32 (opcode, 2, 0);
4732 n = Bits32 (opcode, 5, 3);
4733 imm32 = Bits32 (opcode, 10, 6);
4734
4735 // index = TRUE; add = TRUE; wback = FALSE;
4736 index = true;
4737 add = true;
4738 wback = false;
4739 break;
4740
4741 case eEncodingT2:
4742 // if Rn == ’1111’ then UNDEFINED;
4743 if (Bits32 (opcode, 19, 16) == 15)
4744 return false;
4745
4746 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4747 t = Bits32 (opcode, 15, 12);
4748 n = Bits32 (opcode, 19, 16);
4749 imm32 = Bits32 (opcode, 11, 0);
4750
4751 // index = TRUE; add = TRUE; wback = FALSE;
4752 index = true;
4753 add = true;
4754 wback = false;
4755
4756 // if BadReg(t) then UNPREDICTABLE;
4757 if (BadReg (t))
4758 return false;
4759 break;
4760
4761 case eEncodingT3:
4762 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4763 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4764 if (Bits32 (opcode, 19, 16) == 15)
4765 return false;
4766
4767 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4768 t = Bits32 (opcode, 15, 12);
4769 n = Bits32 (opcode, 19, 16);
4770 imm32 = Bits32 (opcode, 7, 0);
4771
4772 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4773 index = BitIsSet (opcode, 10);
4774 add = BitIsSet (opcode, 9);
4775 wback = BitIsSet (opcode, 8);
4776
4777 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4778 if ((BadReg (t)) || (wback && (n == t)))
4779 return false;
4780 break;
4781
4782 default:
4783 return false;
4784 }
4785
4786 addr_t offset_addr;
4787 addr_t address;
4788 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4789 if (!success)
4790 return false;
4791
4792 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4793 if (add)
4794 offset_addr = base_address + imm32;
4795 else
4796 offset_addr = base_address - imm32;
4797
4798 // address = if index then offset_addr else R[n];
4799 if (index)
4800 address = offset_addr;
4801 else
4802 address = base_address;
4803
Caroline Ticecc96eb52011-02-17 19:20:40 +00004804 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004805 Register base_reg;
4806 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4807
4808 Register data_reg;
4809 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4810
4811 EmulateInstruction::Context context;
4812 context.type = eContextRegisterStore;
4813 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4814
4815 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4816 if (!success)
4817 return false;
4818
4819 data = Bits32 (data, 7, 0);
4820
Caroline Ticecc96eb52011-02-17 19:20:40 +00004821 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004822 return false;
4823
4824 // if wback then R[n] = offset_addr;
4825 if (wback)
4826 {
4827 context.type = eContextRegisterLoad;
4828 context.SetAddress (offset_addr);
4829 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4830 return false;
4831 }
4832
4833 }
4834
4835 return true;
4836}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004837
Johnny Chen157b9592011-02-18 21:13:05 +00004838// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4839// and writes the result to the destination register. It can optionally update the condition flags
4840// based on the result.
4841bool
4842EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4843{
4844#if 0
4845 // ARM pseudo code...
4846 if ConditionPassed() then
4847 EncodingSpecificOperations();
4848 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4849 if d == 15 then // Can only occur for ARM encoding
4850 ALUWritePC(result); // setflags is always FALSE here
4851 else
4852 R[d] = result;
4853 if setflags then
4854 APSR.N = result<31>;
4855 APSR.Z = IsZeroBit(result);
4856 APSR.C = carry;
4857 APSR.V = overflow;
4858#endif
4859
4860 bool success = false;
4861 const uint32_t opcode = OpcodeAsUnsigned (&success);
4862 if (!success)
4863 return false;
4864
4865 if (ConditionPassed())
4866 {
4867 uint32_t Rd, Rn;
4868 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4869 bool setflags;
4870 switch (encoding)
4871 {
4872 case eEncodingT1:
4873 Rd = Bits32(opcode, 11, 8);
4874 Rn = Bits32(opcode, 19, 16);
4875 setflags = BitIsSet(opcode, 20);
4876 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4877 if (BadReg(Rd) || BadReg(Rn))
4878 return false;
4879 break;
4880 case eEncodingA1:
4881 Rd = Bits32(opcode, 15, 12);
4882 Rn = Bits32(opcode, 19, 16);
4883 setflags = BitIsSet(opcode, 20);
4884 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4885 // TODO: Emulate SUBS PC, LR and related instructions.
4886 if (Rd == 15 && setflags)
4887 return false;
4888 break;
4889 default:
4890 return false;
4891 }
4892
4893 // Read the first operand.
4894 int32_t val1 = ReadCoreReg(Rn, &success);
4895 if (!success)
4896 return false;
4897
4898 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4899
4900 EmulateInstruction::Context context;
4901 context.type = EmulateInstruction::eContextImmediate;
4902 context.SetNoArgs ();
4903
4904 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4905 return false;
4906 }
4907 return true;
4908}
4909
4910// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4911// register value, and writes the result to the destination register. It can optionally update the
4912// condition flags based on the result.
4913bool
4914EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4915{
4916#if 0
4917 // ARM pseudo code...
4918 if ConditionPassed() then
4919 EncodingSpecificOperations();
4920 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4921 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4922 if d == 15 then // Can only occur for ARM encoding
4923 ALUWritePC(result); // setflags is always FALSE here
4924 else
4925 R[d] = result;
4926 if setflags then
4927 APSR.N = result<31>;
4928 APSR.Z = IsZeroBit(result);
4929 APSR.C = carry;
4930 APSR.V = overflow;
4931#endif
4932
4933 bool success = false;
4934 const uint32_t opcode = OpcodeAsUnsigned (&success);
4935 if (!success)
4936 return false;
4937
4938 if (ConditionPassed())
4939 {
4940 uint32_t Rd, Rn, Rm;
4941 ARM_ShifterType shift_t;
4942 uint32_t shift_n; // the shift applied to the value read from Rm
4943 bool setflags;
4944 switch (encoding)
4945 {
4946 case eEncodingT1:
4947 Rd = Rn = Bits32(opcode, 2, 0);
4948 Rm = Bits32(opcode, 5, 3);
4949 setflags = !InITBlock();
4950 shift_t = SRType_LSL;
4951 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004952 break;
Johnny Chen157b9592011-02-18 21:13:05 +00004953 case eEncodingT2:
4954 Rd = Bits32(opcode, 11, 8);
4955 Rn = Bits32(opcode, 19, 16);
4956 Rm = Bits32(opcode, 3, 0);
4957 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004958 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004959 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4960 return false;
4961 break;
4962 case eEncodingA1:
4963 Rd = Bits32(opcode, 15, 12);
4964 Rn = Bits32(opcode, 19, 16);
4965 Rm = Bits32(opcode, 3, 0);
4966 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004967 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004968 // TODO: Emulate SUBS PC, LR and related instructions.
4969 if (Rd == 15 && setflags)
4970 return false;
4971 break;
4972 default:
4973 return false;
4974 }
4975
4976 // Read the first operand.
4977 int32_t val1 = ReadCoreReg(Rn, &success);
4978 if (!success)
4979 return false;
4980
4981 // Read the second operand.
4982 int32_t val2 = ReadCoreReg(Rm, &success);
4983 if (!success)
4984 return false;
4985
4986 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4987 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4988
4989 EmulateInstruction::Context context;
4990 context.type = EmulateInstruction::eContextImmediate;
4991 context.SetNoArgs ();
4992
4993 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4994 return false;
4995 }
4996 return true;
4997}
4998
Johnny Chena695f952011-02-23 21:24:25 +00004999// This instruction adds an immediate value to the PC value to form a PC-relative address,
5000// and writes the result to the destination register.
5001bool
5002EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
5003{
5004#if 0
5005 // ARM pseudo code...
5006 if ConditionPassed() then
5007 EncodingSpecificOperations();
5008 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5009 if d == 15 then // Can only occur for ARM encodings
5010 ALUWritePC(result);
5011 else
5012 R[d] = result;
5013#endif
5014
5015 bool success = false;
5016 const uint32_t opcode = OpcodeAsUnsigned (&success);
5017 if (!success)
5018 return false;
5019
5020 if (ConditionPassed())
5021 {
5022 uint32_t Rd;
5023 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5024 bool add;
5025 switch (encoding)
5026 {
5027 case eEncodingT1:
5028 Rd = Bits32(opcode, 10, 8);
5029 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5030 break;
5031 case eEncodingT2:
5032 case eEncodingT3:
5033 Rd = Bits32(opcode, 11, 8);
5034 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5035 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5036 if (BadReg(Rd))
5037 return false;
5038 break;
5039 case eEncodingA1:
5040 case eEncodingA2:
5041 Rd = Bits32(opcode, 15, 12);
5042 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5043 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5044 break;
5045 default:
5046 return false;
5047 }
5048
5049 // Read the PC value.
5050 uint32_t pc = ReadCoreReg(PC_REG, &success);
5051 if (!success)
5052 return false;
5053
5054 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5055
5056 EmulateInstruction::Context context;
5057 context.type = EmulateInstruction::eContextImmediate;
5058 context.SetNoArgs ();
5059
5060 if (!WriteCoreReg(context, result, Rd))
5061 return false;
5062 }
5063 return true;
5064}
5065
Johnny Chene97c0d52011-02-18 19:32:20 +00005066// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5067// to the destination register. It can optionally update the condition flags based on the result.
5068bool
5069EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
5070{
5071#if 0
5072 // ARM pseudo code...
5073 if ConditionPassed() then
5074 EncodingSpecificOperations();
5075 result = R[n] AND imm32;
5076 if d == 15 then // Can only occur for ARM encoding
5077 ALUWritePC(result); // setflags is always FALSE here
5078 else
5079 R[d] = result;
5080 if setflags then
5081 APSR.N = result<31>;
5082 APSR.Z = IsZeroBit(result);
5083 APSR.C = carry;
5084 // APSR.V unchanged
5085#endif
5086
5087 bool success = false;
5088 const uint32_t opcode = OpcodeAsUnsigned (&success);
5089 if (!success)
5090 return false;
5091
5092 if (ConditionPassed())
5093 {
5094 uint32_t Rd, Rn;
5095 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5096 bool setflags;
5097 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5098 switch (encoding)
5099 {
5100 case eEncodingT1:
5101 Rd = Bits32(opcode, 11, 8);
5102 Rn = Bits32(opcode, 19, 16);
5103 setflags = BitIsSet(opcode, 20);
5104 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005105 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005106 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005107 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005108 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5109 return false;
5110 break;
5111 case eEncodingA1:
5112 Rd = Bits32(opcode, 15, 12);
5113 Rn = Bits32(opcode, 19, 16);
5114 setflags = BitIsSet(opcode, 20);
5115 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5116 // TODO: Emulate SUBS PC, LR and related instructions.
5117 if (Rd == 15 && setflags)
5118 return false;
5119 break;
5120 default:
5121 return false;
5122 }
5123
Johnny Chene97c0d52011-02-18 19:32:20 +00005124 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005125 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005126 if (!success)
5127 return false;
5128
5129 uint32_t result = val1 & imm32;
5130
5131 EmulateInstruction::Context context;
5132 context.type = EmulateInstruction::eContextImmediate;
5133 context.SetNoArgs ();
5134
5135 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5136 return false;
5137 }
5138 return true;
5139}
5140
5141// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5142// and writes the result to the destination register. It can optionally update the condition flags
5143// based on the result.
5144bool
5145EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
5146{
5147#if 0
5148 // ARM pseudo code...
5149 if ConditionPassed() then
5150 EncodingSpecificOperations();
5151 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5152 result = R[n] AND shifted;
5153 if d == 15 then // Can only occur for ARM encoding
5154 ALUWritePC(result); // setflags is always FALSE here
5155 else
5156 R[d] = result;
5157 if setflags then
5158 APSR.N = result<31>;
5159 APSR.Z = IsZeroBit(result);
5160 APSR.C = carry;
5161 // APSR.V unchanged
5162#endif
5163
5164 bool success = false;
5165 const uint32_t opcode = OpcodeAsUnsigned (&success);
5166 if (!success)
5167 return false;
5168
5169 if (ConditionPassed())
5170 {
5171 uint32_t Rd, Rn, Rm;
5172 ARM_ShifterType shift_t;
5173 uint32_t shift_n; // the shift applied to the value read from Rm
5174 bool setflags;
5175 uint32_t carry;
5176 switch (encoding)
5177 {
5178 case eEncodingT1:
5179 Rd = Rn = Bits32(opcode, 2, 0);
5180 Rm = Bits32(opcode, 5, 3);
5181 setflags = !InITBlock();
5182 shift_t = SRType_LSL;
5183 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005184 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005185 case eEncodingT2:
5186 Rd = Bits32(opcode, 11, 8);
5187 Rn = Bits32(opcode, 19, 16);
5188 Rm = Bits32(opcode, 3, 0);
5189 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005190 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005191 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005192 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005193 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005194 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5195 return false;
5196 break;
5197 case eEncodingA1:
5198 Rd = Bits32(opcode, 15, 12);
5199 Rn = Bits32(opcode, 19, 16);
5200 Rm = Bits32(opcode, 3, 0);
5201 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005202 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005203 // TODO: Emulate SUBS PC, LR and related instructions.
5204 if (Rd == 15 && setflags)
5205 return false;
5206 break;
5207 default:
5208 return false;
5209 }
5210
Johnny Chene97c0d52011-02-18 19:32:20 +00005211 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005212 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005213 if (!success)
5214 return false;
5215
5216 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005217 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005218 if (!success)
5219 return false;
5220
5221 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5222 uint32_t result = val1 & shifted;
5223
5224 EmulateInstruction::Context context;
5225 context.type = EmulateInstruction::eContextImmediate;
5226 context.SetNoArgs ();
5227
5228 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5229 return false;
5230 }
5231 return true;
5232}
5233
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005234// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5235// immediate value, and writes the result to the destination register. It can optionally update the
5236// condition flags based on the result.
5237bool
5238EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
5239{
5240#if 0
5241 // ARM pseudo code...
5242 if ConditionPassed() then
5243 EncodingSpecificOperations();
5244 result = R[n] AND NOT(imm32);
5245 if d == 15 then // Can only occur for ARM encoding
5246 ALUWritePC(result); // setflags is always FALSE here
5247 else
5248 R[d] = result;
5249 if setflags then
5250 APSR.N = result<31>;
5251 APSR.Z = IsZeroBit(result);
5252 APSR.C = carry;
5253 // APSR.V unchanged
5254#endif
5255
5256 bool success = false;
5257 const uint32_t opcode = OpcodeAsUnsigned (&success);
5258 if (!success)
5259 return false;
5260
5261 if (ConditionPassed())
5262 {
5263 uint32_t Rd, Rn;
5264 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5265 bool setflags;
5266 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5267 switch (encoding)
5268 {
5269 case eEncodingT1:
5270 Rd = Bits32(opcode, 11, 8);
5271 Rn = Bits32(opcode, 19, 16);
5272 setflags = BitIsSet(opcode, 20);
5273 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5274 if (BadReg(Rd) || BadReg(Rn))
5275 return false;
5276 break;
5277 case eEncodingA1:
5278 Rd = Bits32(opcode, 15, 12);
5279 Rn = Bits32(opcode, 19, 16);
5280 setflags = BitIsSet(opcode, 20);
5281 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5282 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5283 // TODO: Emulate SUBS PC, LR and related instructions.
5284 if (Rd == 15 && setflags)
5285 return false;
5286 break;
5287 default:
5288 return false;
5289 }
5290
5291 // Read the first operand.
5292 uint32_t val1 = ReadCoreReg(Rn, &success);
5293 if (!success)
5294 return false;
5295
5296 uint32_t result = val1 & ~imm32;
5297
5298 EmulateInstruction::Context context;
5299 context.type = EmulateInstruction::eContextImmediate;
5300 context.SetNoArgs ();
5301
5302 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5303 return false;
5304 }
5305 return true;
5306}
5307
5308// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5309// optionally-shifted register value, and writes the result to the destination register.
5310// It can optionally update the condition flags based on the result.
5311bool
5312EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5313{
5314#if 0
5315 // ARM pseudo code...
5316 if ConditionPassed() then
5317 EncodingSpecificOperations();
5318 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5319 result = R[n] AND NOT(shifted);
5320 if d == 15 then // Can only occur for ARM encoding
5321 ALUWritePC(result); // setflags is always FALSE here
5322 else
5323 R[d] = result;
5324 if setflags then
5325 APSR.N = result<31>;
5326 APSR.Z = IsZeroBit(result);
5327 APSR.C = carry;
5328 // APSR.V unchanged
5329#endif
5330
5331 bool success = false;
5332 const uint32_t opcode = OpcodeAsUnsigned (&success);
5333 if (!success)
5334 return false;
5335
5336 if (ConditionPassed())
5337 {
5338 uint32_t Rd, Rn, Rm;
5339 ARM_ShifterType shift_t;
5340 uint32_t shift_n; // the shift applied to the value read from Rm
5341 bool setflags;
5342 uint32_t carry;
5343 switch (encoding)
5344 {
5345 case eEncodingT1:
5346 Rd = Rn = Bits32(opcode, 2, 0);
5347 Rm = Bits32(opcode, 5, 3);
5348 setflags = !InITBlock();
5349 shift_t = SRType_LSL;
5350 shift_n = 0;
5351 break;
5352 case eEncodingT2:
5353 Rd = Bits32(opcode, 11, 8);
5354 Rn = Bits32(opcode, 19, 16);
5355 Rm = Bits32(opcode, 3, 0);
5356 setflags = BitIsSet(opcode, 20);
5357 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5358 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5359 return false;
5360 break;
5361 case eEncodingA1:
5362 Rd = Bits32(opcode, 15, 12);
5363 Rn = Bits32(opcode, 19, 16);
5364 Rm = Bits32(opcode, 3, 0);
5365 setflags = BitIsSet(opcode, 20);
5366 shift_n = DecodeImmShiftARM(opcode, shift_t);
5367 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5368 // TODO: Emulate SUBS PC, LR and related instructions.
5369 if (Rd == 15 && setflags)
5370 return false;
5371 break;
5372 default:
5373 return false;
5374 }
5375
5376 // Read the first operand.
5377 uint32_t val1 = ReadCoreReg(Rn, &success);
5378 if (!success)
5379 return false;
5380
5381 // Read the second operand.
5382 uint32_t val2 = ReadCoreReg(Rm, &success);
5383 if (!success)
5384 return false;
5385
5386 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5387 uint32_t result = val1 & ~shifted;
5388
5389 EmulateInstruction::Context context;
5390 context.type = EmulateInstruction::eContextImmediate;
5391 context.SetNoArgs ();
5392
5393 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5394 return false;
5395 }
5396 return true;
5397}
5398
Caroline Tice4d729c52011-02-18 00:55:53 +00005399// 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 +00005400// 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 +00005401bool
5402EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5403{
5404#if 0
5405 if ConditionPassed() then
5406 EncodingSpecificOperations();
5407 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5408 address = if index then offset_addr else R[n];
5409 data = MemU[address,4];
5410 if wback then R[n] = offset_addr;
5411 if t == 15 then
5412 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5413 elsif UnalignedSupport() || address<1:0> = ’00’ then
5414 R[t] = data;
5415 else // Can only apply before ARMv7
5416 R[t] = ROR(data, 8*UInt(address<1:0>));
5417#endif
5418
5419 bool success = false;
5420 const uint32_t opcode = OpcodeAsUnsigned (&success);
5421 if (!success)
5422 return false;
5423
5424 if (ConditionPassed ())
5425 {
5426 const uint32_t addr_byte_size = GetAddressByteSize();
5427
5428 uint32_t t;
5429 uint32_t n;
5430 uint32_t imm32;
5431 bool index;
5432 bool add;
5433 bool wback;
5434
5435 switch (encoding)
5436 {
5437 case eEncodingA1:
5438 // if Rn == ’1111’ then SEE LDR (literal);
5439 // if P == ’0’ && W == ’1’ then SEE LDRT;
5440 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5441 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5442 t = Bits32 (opcode, 15, 12);
5443 n = Bits32 (opcode, 19, 16);
5444 imm32 = Bits32 (opcode, 11, 0);
5445
5446 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5447 index = BitIsSet (opcode, 24);
5448 add = BitIsSet (opcode, 23);
5449 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5450
5451 // if wback && n == t then UNPREDICTABLE;
5452 if (wback && (n == t))
5453 return false;
5454
5455 break;
5456
5457 default:
5458 return false;
5459 }
5460
5461 addr_t address;
5462 addr_t offset_addr;
5463 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5464 if (!success)
5465 return false;
5466
5467 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5468 if (add)
5469 offset_addr = base_address + imm32;
5470 else
5471 offset_addr = base_address - imm32;
5472
5473 // address = if index then offset_addr else R[n];
5474 if (index)
5475 address = offset_addr;
5476 else
5477 address = base_address;
5478
5479 // data = MemU[address,4];
5480
5481 Register base_reg;
5482 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5483
5484 EmulateInstruction::Context context;
5485 context.type = eContextRegisterLoad;
5486 context.SetRegisterPlusOffset (base_reg, address - base_address);
5487
5488 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5489 if (!success)
5490 return false;
5491
5492 // if wback then R[n] = offset_addr;
5493 if (wback)
5494 {
5495 context.type = eContextAdjustBaseRegister;
5496 context.SetAddress (offset_addr);
5497 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5498 return false;
5499 }
5500
5501 // if t == 15 then
5502 if (t == 15)
5503 {
5504 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5505 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5506 {
5507 // LoadWritePC (data);
5508 context.type = eContextRegisterLoad;
5509 context.SetRegisterPlusOffset (base_reg, address - base_address);
5510 LoadWritePC (context, data);
5511 }
5512 else
5513 return false;
5514 }
5515 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5516 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5517 {
5518 // R[t] = data;
5519 context.type = eContextRegisterLoad;
5520 context.SetRegisterPlusOffset (base_reg, address - base_address);
5521 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5522 return false;
5523 }
5524 // else // Can only apply before ARMv7
5525 else
5526 {
5527 // R[t] = ROR(data, 8*UInt(address<1:0>));
5528 data = ROR (data, Bits32 (address, 1, 0));
5529 context.type = eContextRegisterLoad;
5530 context.SetImmediate (data);
5531 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5532 return false;
5533 }
5534
5535 }
5536 return true;
5537}
5538
Caroline Ticefe479112011-02-18 18:52:37 +00005539// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5540// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5541bool
5542EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5543{
5544#if 0
5545 if ConditionPassed() then
5546 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5547 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5548 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5549 address = if index then offset_addr else R[n];
5550 data = MemU[address,4];
5551 if wback then R[n] = offset_addr;
5552 if t == 15 then
5553 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5554 elsif UnalignedSupport() || address<1:0> = ’00’ then
5555 R[t] = data;
5556 else // Can only apply before ARMv7
5557 if CurrentInstrSet() == InstrSet_ARM then
5558 R[t] = ROR(data, 8*UInt(address<1:0>));
5559 else
5560 R[t] = bits(32) UNKNOWN;
5561#endif
5562
5563 bool success = false;
5564 const uint32_t opcode = OpcodeAsUnsigned (&success);
5565 if (!success)
5566 return false;
5567
5568 if (ConditionPassed ())
5569 {
5570 const uint32_t addr_byte_size = GetAddressByteSize();
5571
5572 uint32_t t;
5573 uint32_t n;
5574 uint32_t m;
5575 bool index;
5576 bool add;
5577 bool wback;
5578 ARM_ShifterType shift_t;
5579 uint32_t shift_n;
5580
5581 switch (encoding)
5582 {
5583 case eEncodingT1:
5584 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5585 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5586 t = Bits32 (opcode, 2, 0);
5587 n = Bits32 (opcode, 5, 3);
5588 m = Bits32 (opcode, 8, 6);
5589
5590 // index = TRUE; add = TRUE; wback = FALSE;
5591 index = true;
5592 add = true;
5593 wback = false;
5594
5595 // (shift_t, shift_n) = (SRType_LSL, 0);
5596 shift_t = SRType_LSL;
5597 shift_n = 0;
5598
5599 break;
5600
5601 case eEncodingT2:
5602 // if Rn == ’1111’ then SEE LDR (literal);
5603 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5604 t = Bits32 (opcode, 15, 12);
5605 n = Bits32 (opcode, 19, 16);
5606 m = Bits32 (opcode, 3, 0);
5607
5608 // index = TRUE; add = TRUE; wback = FALSE;
5609 index = true;
5610 add = true;
5611 wback = false;
5612
5613 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5614 shift_t = SRType_LSL;
5615 shift_n = Bits32 (opcode, 5, 4);
5616
5617 // if BadReg(m) then UNPREDICTABLE;
5618 if (BadReg (m))
5619 return false;
5620
5621 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5622 if ((t == 15) && InITBlock() && !LastInITBlock())
5623 return false;
5624
5625 break;
5626
5627 case eEncodingA1:
5628 {
5629 // if P == ’0’ && W == ’1’ then SEE LDRT;
5630 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5631 t = Bits32 (opcode, 15, 12);
5632 n = Bits32 (opcode, 19, 16);
5633 m = Bits32 (opcode, 3, 0);
5634
5635 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5636 index = BitIsSet (opcode, 24);
5637 add = BitIsSet (opcode, 23);
5638 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5639
5640 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5641 uint32_t type = Bits32 (opcode, 6, 5);
5642 uint32_t imm5 = Bits32 (opcode, 11, 7);
5643 shift_n = DecodeImmShift (type, imm5, shift_t);
5644
5645 // if m == 15 then UNPREDICTABLE;
5646 if (m == 15)
5647 return false;
5648
5649 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5650 if (wback && ((n == 15) || (n == t)))
5651 return false;
5652 }
5653 break;
5654
5655
5656 default:
5657 return false;
5658 }
5659
5660 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5661 if (!success)
5662 return false;
5663
5664 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5665 if (!success)
5666 return false;
5667
5668 addr_t offset_addr;
5669 addr_t address;
5670
5671 // 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 +00005672 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005673
5674 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5675 if (add)
5676 offset_addr = Rn + offset;
5677 else
5678 offset_addr = Rn - offset;
5679
5680 // address = if index then offset_addr else R[n];
5681 if (index)
5682 address = offset_addr;
5683 else
5684 address = Rn;
5685
5686 // data = MemU[address,4];
5687 Register base_reg;
5688 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5689
5690 EmulateInstruction::Context context;
5691 context.type = eContextRegisterLoad;
5692 context.SetRegisterPlusOffset (base_reg, address - Rn);
5693
5694 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5695 if (!success)
5696 return false;
5697
5698 // if wback then R[n] = offset_addr;
5699 if (wback)
5700 {
5701 context.type = eContextAdjustBaseRegister;
5702 context.SetAddress (offset_addr);
5703 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5704 return false;
5705 }
5706
5707 // if t == 15 then
5708 if (t == 15)
5709 {
5710 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5711 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5712 {
5713 context.type = eContextRegisterLoad;
5714 context.SetRegisterPlusOffset (base_reg, address - Rn);
5715 LoadWritePC (context, data);
5716 }
5717 else
5718 return false;
5719 }
5720 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5721 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5722 {
5723 // R[t] = data;
5724 context.type = eContextRegisterLoad;
5725 context.SetRegisterPlusOffset (base_reg, address - Rn);
5726 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5727 return false;
5728 }
5729 else // Can only apply before ARMv7
5730 {
5731 // if CurrentInstrSet() == InstrSet_ARM then
5732 if (CurrentInstrSet () == eModeARM)
5733 {
5734 // R[t] = ROR(data, 8*UInt(address<1:0>));
5735 data = ROR (data, Bits32 (address, 1, 0));
5736 context.type = eContextRegisterLoad;
5737 context.SetImmediate (data);
5738 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5739 return false;
5740 }
5741 else
5742 {
5743 // R[t] = bits(32) UNKNOWN;
5744 WriteBits32Unknown (t);
5745 }
5746 }
5747 }
5748 return true;
5749}
Caroline Tice21b604b2011-02-18 21:06:04 +00005750
5751// LDRB (immediate, Thumb)
5752bool
5753EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5754{
5755#if 0
5756 if ConditionPassed() then
5757 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5758 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5759 address = if index then offset_addr else R[n];
5760 R[t] = ZeroExtend(MemU[address,1], 32);
5761 if wback then R[n] = offset_addr;
5762#endif
5763
5764 bool success = false;
5765 const uint32_t opcode = OpcodeAsUnsigned (&success);
5766 if (!success)
5767 return false;
5768
5769 if (ConditionPassed ())
5770 {
5771 uint32_t t;
5772 uint32_t n;
5773 uint32_t imm32;
5774 bool index;
5775 bool add;
5776 bool wback;
5777
5778 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5779 switch (encoding)
5780 {
5781 case eEncodingT1:
5782 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5783 t = Bits32 (opcode, 2, 0);
5784 n = Bits32 (opcode, 5, 3);
5785 imm32 = Bits32 (opcode, 10, 6);
5786
5787 // index = TRUE; add = TRUE; wback = FALSE;
5788 index = true;
5789 add = true;
5790 wback= false;
5791
5792 break;
5793
5794 case eEncodingT2:
5795 // if Rt == ’1111’ then SEE PLD;
5796 // if Rn == ’1111’ then SEE LDRB (literal);
5797 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5798 t = Bits32 (opcode, 15, 12);
5799 n = Bits32 (opcode, 19, 16);
5800 imm32 = Bits32 (opcode, 11, 0);
5801
5802 // index = TRUE; add = TRUE; wback = FALSE;
5803 index = true;
5804 add = true;
5805 wback = false;
5806
5807 // if t == 13 then UNPREDICTABLE;
5808 if (t == 13)
5809 return false;
5810
5811 break;
5812
5813 case eEncodingT3:
5814 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5815 // if Rn == ’1111’ then SEE LDRB (literal);
5816 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5817 // if P == ’0’ && W == ’0’ then UNDEFINED;
5818 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5819 return false;
5820
5821 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5822 t = Bits32 (opcode, 15, 12);
5823 n = Bits32 (opcode, 19, 16);
5824 imm32 = Bits32 (opcode, 7, 0);
5825
5826 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5827 index = BitIsSet (opcode, 10);
5828 add = BitIsSet (opcode, 9);
5829 wback = BitIsSet (opcode, 8);
5830
5831 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5832 if (BadReg (t) || (wback && (n == t)))
5833 return false;
5834
5835 break;
5836
5837 default:
5838 return false;
5839 }
5840
5841 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5842 if (!success)
5843 return false;
5844
5845 addr_t address;
5846 addr_t offset_addr;
5847
5848 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5849 if (add)
5850 offset_addr = Rn + imm32;
5851 else
5852 offset_addr = Rn - imm32;
5853
5854 // address = if index then offset_addr else R[n];
5855 if (index)
5856 address = offset_addr;
5857 else
5858 address = Rn;
5859
5860 // R[t] = ZeroExtend(MemU[address,1], 32);
5861 Register base_reg;
5862 Register data_reg;
5863 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5864 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5865
5866 EmulateInstruction::Context context;
5867 context.type = eContextRegisterLoad;
5868 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5869
5870 uint64_t data = MemURead (context, address, 1, 0, &success);
5871 if (!success)
5872 return false;
5873
5874 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5875 return false;
5876
5877 // if wback then R[n] = offset_addr;
5878 if (wback)
5879 {
5880 context.type = eContextAdjustBaseRegister;
5881 context.SetAddress (offset_addr);
5882 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5883 return false;
5884 }
5885 }
5886 return true;
5887}
Caroline Ticef55261f2011-02-18 22:24:22 +00005888
5889// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5890// zero-extends it to form a 32-bit word and writes it to a register.
5891bool
5892EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5893{
5894#if 0
5895 if ConditionPassed() then
5896 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5897 base = Align(PC,4);
5898 address = if add then (base + imm32) else (base - imm32);
5899 R[t] = ZeroExtend(MemU[address,1], 32);
5900#endif
5901
5902 bool success = false;
5903 const uint32_t opcode = OpcodeAsUnsigned (&success);
5904 if (!success)
5905 return false;
5906
5907 if (ConditionPassed ())
5908 {
5909 uint32_t t;
5910 uint32_t imm32;
5911 bool add;
5912 switch (encoding)
5913 {
5914 case eEncodingT1:
5915 // if Rt == ’1111’ then SEE PLD;
5916 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5917 t = Bits32 (opcode, 15, 12);
5918 imm32 = Bits32 (opcode, 11, 0);
5919 add = BitIsSet (opcode, 23);
5920
5921 // if t == 13 then UNPREDICTABLE;
5922 if (t == 13)
5923 return false;
5924
5925 break;
5926
5927 case eEncodingA1:
5928 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5929 t = Bits32 (opcode, 15, 12);
5930 imm32 = Bits32 (opcode, 11, 0);
5931 add = BitIsSet (opcode, 23);
5932
5933 // if t == 15 then UNPREDICTABLE;
5934 if (t == 15)
5935 return false;
5936 break;
5937
5938 default:
5939 return false;
5940 }
5941
5942 // base = Align(PC,4);
5943 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5944 if (!success)
5945 return false;
5946
5947 uint32_t base = AlignPC (pc_val);
5948
5949 addr_t address;
5950 // address = if add then (base + imm32) else (base - imm32);
5951 if (add)
5952 address = base + imm32;
5953 else
5954 address = base - imm32;
5955
5956 // R[t] = ZeroExtend(MemU[address,1], 32);
5957 EmulateInstruction::Context context;
5958 context.type = eContextRelativeBranchImmediate;
5959 context.SetImmediate (address - base);
5960
5961 uint64_t data = MemURead (context, address, 1, 0, &success);
5962 if (!success)
5963 return false;
5964
5965 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5966 return false;
5967 }
5968 return true;
5969}
Caroline Tice30fec122011-02-18 23:52:21 +00005970
5971// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5972// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5973// optionally be shifted.
5974bool
5975EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5976{
5977#if 0
5978 if ConditionPassed() then
5979 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5980 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5981 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5982 address = if index then offset_addr else R[n];
5983 R[t] = ZeroExtend(MemU[address,1],32);
5984 if wback then R[n] = offset_addr;
5985#endif
5986
5987 bool success = false;
5988 const uint32_t opcode = OpcodeAsUnsigned (&success);
5989 if (!success)
5990 return false;
5991
5992 if (ConditionPassed ())
5993 {
5994 uint32_t t;
5995 uint32_t n;
5996 uint32_t m;
5997 bool index;
5998 bool add;
5999 bool wback;
6000 ARM_ShifterType shift_t;
6001 uint32_t shift_n;
6002
6003 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6004 switch (encoding)
6005 {
6006 case eEncodingT1:
6007 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6008 t = Bits32 (opcode, 2, 0);
6009 n = Bits32 (opcode, 5, 3);
6010 m = Bits32 (opcode, 8, 6);
6011
6012 // index = TRUE; add = TRUE; wback = FALSE;
6013 index = true;
6014 add = true;
6015 wback = false;
6016
6017 // (shift_t, shift_n) = (SRType_LSL, 0);
6018 shift_t = SRType_LSL;
6019 shift_n = 0;
6020 break;
6021
6022 case eEncodingT2:
6023 // if Rt == ’1111’ then SEE PLD;
6024 // if Rn == ’1111’ then SEE LDRB (literal);
6025 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6026 t = Bits32 (opcode, 15, 12);
6027 n = Bits32 (opcode, 19, 16);
6028 m = Bits32 (opcode, 3, 0);
6029
6030 // index = TRUE; add = TRUE; wback = FALSE;
6031 index = true;
6032 add = true;
6033 wback = false;
6034
6035 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6036 shift_t = SRType_LSL;
6037 shift_n = Bits32 (opcode, 5, 4);
6038
6039 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6040 if ((t == 13) || BadReg (m))
6041 return false;
6042 break;
6043
6044 case eEncodingA1:
6045 {
6046 // if P == ’0’ && W == ’1’ then SEE LDRBT;
6047 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6048 t = Bits32 (opcode, 15, 12);
6049 n = Bits32 (opcode, 19, 16);
6050 m = Bits32 (opcode, 3, 0);
6051
6052 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6053 index = BitIsSet (opcode, 24);
6054 add = BitIsSet (opcode, 23);
6055 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6056
6057 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6058 uint32_t type = Bits32 (opcode, 6, 5);
6059 uint32_t imm5 = Bits32 (opcode, 11, 7);
6060 shift_n = DecodeImmShift (type, imm5, shift_t);
6061
6062 // if t == 15 || m == 15 then UNPREDICTABLE;
6063 if ((t == 15) || (m == 15))
6064 return false;
6065
6066 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6067 if (wback && ((n == 15) || (n == t)))
6068 return false;
6069 }
6070 break;
6071
6072 default:
6073 return false;
6074 }
6075
6076 addr_t offset_addr;
6077 addr_t address;
6078
6079 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6080 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6081 if (!success)
6082 return false;
6083
6084 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6085
6086 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6087 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6088 if (!success)
6089 return false;
6090
6091 if (add)
6092 offset_addr = Rn + offset;
6093 else
6094 offset_addr = Rn - offset;
6095
6096 // address = if index then offset_addr else R[n];
6097 if (index)
6098 address = offset_addr;
6099 else
6100 address = Rn;
6101
6102 // R[t] = ZeroExtend(MemU[address,1],32);
6103 Register base_reg;
6104 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6105
6106 EmulateInstruction::Context context;
6107 context.type = eContextRegisterLoad;
6108 context.SetRegisterPlusOffset (base_reg, address - Rn);
6109
6110 uint64_t data = MemURead (context, address, 1, 0, &success);
6111 if (!success)
6112 return false;
6113
6114 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6115 return false;
6116
6117 // if wback then R[n] = offset_addr;
6118 if (wback)
6119 {
6120 context.type = eContextAdjustBaseRegister;
6121 context.SetAddress (offset_addr);
6122 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6123 return false;
6124 }
6125 }
6126 return true;
6127}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006128
6129// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6130// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6131// post-indexed, or pre-indexed addressing.
6132bool
6133EmulateInstructionARM::EmulateLDRHImmediate (ARMEncoding encoding)
6134{
6135#if 0
6136 if ConditionPassed() then
6137 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6138 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6139 address = if index then offset_addr else R[n];
6140 data = MemU[address,2];
6141 if wback then R[n] = offset_addr;
6142 if UnalignedSupport() || address<0> = ’0’ then
6143 R[t] = ZeroExtend(data, 32);
6144 else // Can only apply before ARMv7
6145 R[t] = bits(32) UNKNOWN;
6146#endif
6147
6148
6149 bool success = false;
6150 const uint32_t opcode = OpcodeAsUnsigned (&success);
6151 if (!success)
6152 return false;
6153
6154 if (ConditionPassed())
6155 {
6156 uint32_t t;
6157 uint32_t n;
6158 uint32_t imm32;
6159 bool index;
6160 bool add;
6161 bool wback;
6162
6163 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6164 switch (encoding)
6165 {
6166 case eEncodingT1:
6167 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
6168 t = Bits32 (opcode, 2, 0);
6169 n = Bits32 (opcode, 5, 3);
6170 imm32 = Bits32 (opcode, 10, 6) << 1;
6171
6172 // index = TRUE; add = TRUE; wback = FALSE;
6173 index = true;
6174 add = true;
6175 wback = false;
6176
6177 break;
6178
6179 case eEncodingT2:
6180 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6181 // if Rn == ’1111’ then SEE LDRH (literal);
6182 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6183 t = Bits32 (opcode, 15, 12);
6184 n = Bits32 (opcode, 19, 16);
6185 imm32 = Bits32 (opcode, 11, 0);
6186
6187 // index = TRUE; add = TRUE; wback = FALSE;
6188 index = true;
6189 add = true;
6190 wback = false;
6191
6192 // if t == 13 then UNPREDICTABLE;
6193 if (t == 13)
6194 return false;
6195 break;
6196
6197 case eEncodingT3:
6198 // if Rn == ’1111’ then SEE LDRH (literal);
6199 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6200 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
6201 // if P == ’0’ && W == ’0’ then UNDEFINED;
6202 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6203 return false;
6204
6205 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6206 t = Bits32 (opcode, 15, 12);
6207 n = Bits32 (opcode, 19, 16);
6208 imm32 = Bits32 (opcode, 7, 0);
6209
6210 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6211 index = BitIsSet (opcode, 10);
6212 add = BitIsSet (opcode, 9);
6213 wback = BitIsSet (opcode, 8);
6214
6215 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6216 if (BadReg (t) || (wback && (n == t)))
6217 return false;
6218 break;
6219
6220 default:
6221 return false;
6222 }
6223
6224 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6225 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6226 if (!success)
6227 return false;
6228
6229 addr_t offset_addr;
6230 addr_t address;
6231
6232 if (add)
6233 offset_addr = Rn + imm32;
6234 else
6235 offset_addr = Rn - imm32;
6236
6237 // address = if index then offset_addr else R[n];
6238 if (index)
6239 address = offset_addr;
6240 else
6241 address = Rn;
6242
6243 // data = MemU[address,2];
6244 Register base_reg;
6245 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6246
6247 EmulateInstruction::Context context;
6248 context.type = eContextRegisterLoad;
6249 context.SetRegisterPlusOffset (base_reg, address - Rn);
6250
6251 uint64_t data = MemURead (context, address, 2, 0, &success);
6252 if (!success)
6253 return false;
6254
6255 // if wback then R[n] = offset_addr;
6256 if (wback)
6257 {
6258 context.type = eContextAdjustBaseRegister;
6259 context.SetAddress (offset_addr);
6260 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6261 return false;
6262 }
6263
6264 // if UnalignedSupport() || address<0> = ’0’ then
6265 if (UnalignedSupport () || BitIsClear (address, 0))
6266 {
6267 // R[t] = ZeroExtend(data, 32);
6268 context.type = eContextRegisterLoad;
6269 context.SetRegisterPlusOffset (base_reg, address - Rn);
6270 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6271 return false;
6272 }
6273 else // Can only apply before ARMv7
6274 {
6275 // R[t] = bits(32) UNKNOWN;
6276 WriteBits32Unknown (t);
6277 }
6278 }
6279 return true;
6280}
Caroline Ticefe479112011-02-18 18:52:37 +00006281
Caroline Tice952b5382011-02-28 23:15:24 +00006282// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6283// zero-extends it to form a 32-bit word, and writes it to a register.
6284bool
6285EmulateInstructionARM::EmulateLDRHLiteral (ARMEncoding encoding)
6286{
6287#if 0
6288 if ConditionPassed() then
6289 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6290 base = Align(PC,4);
6291 address = if add then (base + imm32) else (base - imm32);
6292 data = MemU[address,2];
6293 if UnalignedSupport() || address<0> = ’0’ then
6294 R[t] = ZeroExtend(data, 32);
6295 else // Can only apply before ARMv7
6296 R[t] = bits(32) UNKNOWN;
6297#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006298
Caroline Tice952b5382011-02-28 23:15:24 +00006299 bool success = false;
6300 const uint32_t opcode = OpcodeAsUnsigned (&success);
6301 if (!success)
6302 return false;
6303
6304 if (ConditionPassed())
6305 {
6306 uint32_t t;
6307 uint32_t imm32;
6308 bool add;
6309
6310 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6311 switch (encoding)
6312 {
6313 case eEncodingT1:
6314 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6315 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6316 t = Bits32 (opcode, 15, 12);
6317 imm32 = Bits32 (opcode, 11, 0);
6318 add = BitIsSet (opcode, 23);
6319
6320 // if t == 13 then UNPREDICTABLE;
6321 if (t == 13)
6322 return false;
6323
6324 break;
6325
6326 case eEncodingA1:
6327 {
6328 uint32_t imm4H = Bits32 (opcode, 11, 8);
6329 uint32_t imm4L = Bits32 (opcode, 3, 0);
6330
6331 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6332 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006333 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006334 add = BitIsSet (opcode, 23);
6335
6336 // if t == 15 then UNPREDICTABLE;
6337 if (t == 15)
6338 return false;
6339 break;
6340 }
6341
6342 default:
6343 return false;
6344 }
6345
6346 // base = Align(PC,4);
6347 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
6348 if (!success)
6349 return false;
6350
6351 addr_t base = AlignPC (pc_value);
6352 addr_t address;
6353
6354 // address = if add then (base + imm32) else (base - imm32);
6355 if (add)
6356 address = base + imm32;
6357 else
6358 address = base - imm32;
6359
6360 // data = MemU[address,2];
6361 Register base_reg;
6362 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6363
6364 EmulateInstruction::Context context;
6365 context.type = eContextRegisterLoad;
6366 context.SetRegisterPlusOffset (base_reg, address - base);
6367
6368 uint64_t data = MemURead (context, address, 2, 0, &success);
6369 if (!success)
6370 return false;
6371
6372
6373 // if UnalignedSupport() || address<0> = ’0’ then
6374 if (UnalignedSupport () || BitIsClear (address, 0))
6375 {
6376 // R[t] = ZeroExtend(data, 32);
6377 context.type = eContextRegisterLoad;
6378 context.SetRegisterPlusOffset (base_reg, address - base);
6379 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6380 return false;
6381
6382 }
6383 else // Can only apply before ARMv7
6384 {
6385 // R[t] = bits(32) UNKNOWN;
6386 WriteBits32Unknown (t);
6387 }
6388 }
6389 return true;
6390}
6391
Caroline Tice0e6bc952011-03-01 18:00:42 +00006392// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6393// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6394// be shifted left by 0, 1, 2, or 3 bits.
6395bool
6396EmulateInstructionARM::EmulateLDRHRegister (ARMEncoding encoding)
6397{
6398#if 0
6399 if ConditionPassed() then
6400 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6401 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6402 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6403 address = if index then offset_addr else R[n];
6404 data = MemU[address,2];
6405 if wback then R[n] = offset_addr;
6406 if UnalignedSupport() || address<0> = ’0’ then
6407 R[t] = ZeroExtend(data, 32);
6408 else // Can only apply before ARMv7
6409 R[t] = bits(32) UNKNOWN;
6410#endif
6411
6412 bool success = false;
6413 const uint32_t opcode = OpcodeAsUnsigned (&success);
6414 if (!success)
6415 return false;
6416
6417 if (ConditionPassed())
6418 {
6419 uint32_t t;
6420 uint32_t n;
6421 uint32_t m;
6422 bool index;
6423 bool add;
6424 bool wback;
6425 ARM_ShifterType shift_t;
6426 uint32_t shift_n;
6427
6428 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6429 switch (encoding)
6430 {
6431 case eEncodingT1:
6432 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6433 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6434 t = Bits32 (opcode, 2, 0);
6435 n = Bits32 (opcode, 5, 3);
6436 m = Bits32 (opcode, 8, 6);
6437
6438 // index = TRUE; add = TRUE; wback = FALSE;
6439 index = true;
6440 add = true;
6441 wback = false;
6442
6443 // (shift_t, shift_n) = (SRType_LSL, 0);
6444 shift_t = SRType_LSL;
6445 shift_n = 0;
6446
6447 break;
6448
6449 case eEncodingT2:
6450 // if Rn == ’1111’ then SEE LDRH (literal);
6451 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6452 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6453 t = Bits32 (opcode, 15, 12);
6454 n = Bits32 (opcode, 19, 16);
6455 m = Bits32 (opcode, 3, 0);
6456
6457 // index = TRUE; add = TRUE; wback = FALSE;
6458 index = true;
6459 add = true;
6460 wback = false;
6461
6462 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6463 shift_t = SRType_LSL;
6464 shift_n = Bits32 (opcode, 5, 4);
6465
6466 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6467 if ((t == 13) || BadReg (m))
6468 return false;
6469 break;
6470
6471 case eEncodingA1:
6472 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6473 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6474 t = Bits32 (opcode, 15, 12);
6475 n = Bits32 (opcode, 19, 16);
6476 m = Bits32 (opcode, 3, 0);
6477
6478 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6479 index = BitIsSet (opcode, 24);
6480 add = BitIsSet (opcode, 23);
6481 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6482
6483 // (shift_t, shift_n) = (SRType_LSL, 0);
6484 shift_t = SRType_LSL;
6485 shift_n = 0;
6486
6487 // if t == 15 || m == 15 then UNPREDICTABLE;
6488 if ((t == 15) || (m == 15))
6489 return false;
6490
6491 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6492 if (wback && ((n == 15) || (n == t)))
6493 return false;
6494
6495 break;
6496
6497 default:
6498 return false;
6499 }
6500
6501 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6502
6503 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6504 if (!success)
6505 return false;
6506
6507 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6508
6509 addr_t offset_addr;
6510 addr_t address;
6511
6512 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6513 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6514 if (!success)
6515 return false;
6516
6517 if (add)
6518 offset_addr = Rn + offset;
6519 else
6520 offset_addr = Rn - offset;
6521
6522 // address = if index then offset_addr else R[n];
6523 if (index)
6524 address = offset_addr;
6525 else
6526 address = Rn;
6527
6528 // data = MemU[address,2];
6529 Register base_reg;
6530 Register offset_reg;
6531 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6532 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6533
6534 EmulateInstruction::Context context;
6535 context.type = eContextRegisterLoad;
6536 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6537 uint64_t data = MemURead (context, address, 2, 0, &success);
6538 if (!success)
6539 return false;
6540
6541 // if wback then R[n] = offset_addr;
6542 if (wback)
6543 {
6544 context.type = eContextAdjustBaseRegister;
6545 context.SetAddress (offset_addr);
6546 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6547 return false;
6548 }
6549
6550 // if UnalignedSupport() || address<0> = ’0’ then
6551 if (UnalignedSupport() || BitIsClear (address, 0))
6552 {
6553 // R[t] = ZeroExtend(data, 32);
6554 context.type = eContextRegisterLoad;
6555 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6556 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6557 return false;
6558 }
6559 else // Can only apply before ARMv7
6560 {
6561 // R[t] = bits(32) UNKNOWN;
6562 WriteBits32Unknown (t);
6563 }
6564 }
6565 return true;
6566}
6567
Caroline Ticea5e28af2011-03-01 21:53:03 +00006568// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6569// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6570// or pre-indexed addressing.
6571bool
6572EmulateInstructionARM::EmulateLDRSBImmediate (ARMEncoding encoding)
6573{
6574#if 0
6575 if ConditionPassed() then
6576 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6577 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6578 address = if index then offset_addr else R[n];
6579 R[t] = SignExtend(MemU[address,1], 32);
6580 if wback then R[n] = offset_addr;
6581#endif
6582
6583 bool success = false;
6584 const uint32_t opcode = OpcodeAsUnsigned (&success);
6585 if (!success)
6586 return false;
6587
6588 if (ConditionPassed ())
6589 {
6590 uint32_t t;
6591 uint32_t n;
6592 uint32_t imm32;
6593 bool index;
6594 bool add;
6595 bool wback;
6596
6597 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6598 switch (encoding)
6599 {
6600 case eEncodingT1:
6601 // if Rt == ’1111’ then SEE PLI;
6602 // if Rn == ’1111’ then SEE LDRSB (literal);
6603 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6604 t = Bits32 (opcode, 15, 12);
6605 n = Bits32 (opcode, 19, 16);
6606 imm32 = Bits32 (opcode, 11, 0);
6607
6608 // index = TRUE; add = TRUE; wback = FALSE;
6609 index = true;
6610 add = true;
6611 wback = false;
6612
6613 // if t == 13 then UNPREDICTABLE;
6614 if (t == 13)
6615 return false;
6616
6617 break;
6618
6619 case eEncodingT2:
6620 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6621 // if Rn == ’1111’ then SEE LDRSB (literal);
6622 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6623 // if P == ’0’ && W == ’0’ then UNDEFINED;
6624 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6625 return false;
6626
6627 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6628 t = Bits32 (opcode, 15, 12);
6629 n = Bits32 (opcode, 19, 16);
6630 imm32 = Bits32 (opcode, 7, 0);
6631
6632 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6633 index = BitIsSet (opcode, 10);
6634 add = BitIsSet (opcode, 9);
6635 wback = BitIsSet (opcode, 8);
6636
6637 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6638 if (BadReg (t) || (wback && (n == t)))
6639 return false;
6640
6641 break;
6642
6643 case eEncodingA1:
6644 {
6645 // if Rn == ’1111’ then SEE LDRSB (literal);
6646 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6647 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6648 t = Bits32 (opcode, 15, 12);
6649 n = Bits32 (opcode, 19, 16);
6650
6651 uint32_t imm4H = Bits32 (opcode, 11, 8);
6652 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006653 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006654
6655 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6656 index = BitIsSet (opcode, 24);
6657 add = BitIsSet (opcode, 23);
6658 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6659
6660 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6661 if ((t == 15) || (wback && (n == t)))
6662 return false;
6663
6664 break;
6665 }
6666
6667 default:
6668 return false;
6669 }
6670
6671 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6672 if (!success)
6673 return false;
6674
6675 addr_t offset_addr;
6676 addr_t address;
6677
6678 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6679 if (add)
6680 offset_addr = Rn + imm32;
6681 else
6682 offset_addr = Rn - imm32;
6683
6684 // address = if index then offset_addr else R[n];
6685 if (index)
6686 address = offset_addr;
6687 else
6688 address = Rn;
6689
6690 // R[t] = SignExtend(MemU[address,1], 32);
6691 Register base_reg;
6692 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6693
6694 EmulateInstruction::Context context;
6695 context.type = eContextRegisterLoad;
6696 context.SetRegisterPlusOffset (base_reg, address - Rn);
6697
6698 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6699 if (!success)
6700 return false;
6701
6702 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6703 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6704 return false;
6705
6706 // if wback then R[n] = offset_addr;
6707 if (wback)
6708 {
6709 context.type = eContextAdjustBaseRegister;
6710 context.SetAddress (offset_addr);
6711 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6712 return false;
6713 }
6714 }
6715
6716 return true;
6717}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006718
Caroline Tice5f593912011-03-01 22:25:17 +00006719// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6720// sign-extends it to form a 32-bit word, and writes tit to a register.
6721bool
6722EmulateInstructionARM::EmulateLDRSBLiteral (ARMEncoding encoding)
6723{
6724#if 0
6725 if ConditionPassed() then
6726 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6727 base = Align(PC,4);
6728 address = if add then (base + imm32) else (base - imm32);
6729 R[t] = SignExtend(MemU[address,1], 32);
6730#endif
6731
6732 bool success = false;
6733 const uint32_t opcode = OpcodeAsUnsigned (&success);
6734 if (!success)
6735 return false;
6736
6737 if (ConditionPassed ())
6738 {
6739 uint32_t t;
6740 uint32_t imm32;
6741 bool add;
6742
6743 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6744 switch (encoding)
6745 {
6746 case eEncodingT1:
6747 // if Rt == ’1111’ then SEE PLI;
6748 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6749 t = Bits32 (opcode, 15, 12);
6750 imm32 = Bits32 (opcode, 11, 0);
6751 add = BitIsSet (opcode, 23);
6752
6753 // if t == 13 then UNPREDICTABLE;
6754 if (t == 13)
6755 return false;
6756
6757 break;
6758
6759 case eEncodingA1:
6760 {
6761 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6762 t = Bits32 (opcode, 15, 12);
6763 uint32_t imm4H = Bits32 (opcode, 11, 8);
6764 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006765 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006766 add = BitIsSet (opcode, 23);
6767
6768 // if t == 15 then UNPREDICTABLE;
6769 if (t == 15)
6770 return false;
6771
6772 break;
6773 }
6774
6775 default:
6776 return false;
6777 }
6778
6779 // base = Align(PC,4);
6780 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS,
6781 &success);
6782 if (!success)
6783 return false;
6784 uint64_t base = AlignPC (pc_value);
6785
6786 // address = if add then (base + imm32) else (base - imm32);
6787 addr_t address;
6788 if (add)
6789 address = base + imm32;
6790 else
6791 address = base - imm32;
6792
6793 // R[t] = SignExtend(MemU[address,1], 32);
6794 Register base_reg;
6795 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6796
6797 EmulateInstruction::Context context;
6798 context.type = eContextRegisterLoad;
6799 context.SetRegisterPlusOffset (base_reg, address - base);
6800
6801 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6802 if (!success)
6803 return false;
6804
6805 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6806 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6807 return false;
6808 }
6809 return true;
6810}
6811
Caroline Tice672f3112011-03-01 23:55:59 +00006812// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6813// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6814// shifted left by 0, 1, 2, or 3 bits.
6815bool
6816EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
6817{
6818#if 0
6819 if ConditionPassed() then
6820 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6821 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6822 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6823 address = if index then offset_addr else R[n];
6824 R[t] = SignExtend(MemU[address,1], 32);
6825 if wback then R[n] = offset_addr;
6826#endif
6827
6828 bool success = false;
6829 const uint32_t opcode = OpcodeAsUnsigned (&success);
6830 if (!success)
6831 return false;
6832
6833 if (ConditionPassed ())
6834 {
6835 uint32_t t;
6836 uint32_t n;
6837 uint32_t m;
6838 bool index;
6839 bool add;
6840 bool wback;
6841 ARM_ShifterType shift_t;
6842 uint32_t shift_n;
6843
6844 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6845 switch (encoding)
6846 {
6847 case eEncodingT1:
6848 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6849 t = Bits32 (opcode, 2, 0);
6850 n = Bits32 (opcode, 5, 3);
6851 m = Bits32 (opcode, 8, 6);
6852
6853 // index = TRUE; add = TRUE; wback = FALSE;
6854 index = true;
6855 add = true;
6856 wback = false;
6857
6858 // (shift_t, shift_n) = (SRType_LSL, 0);
6859 shift_t = SRType_LSL;
6860 shift_n = 0;
6861
6862 break;
6863
6864 case eEncodingT2:
6865 // if Rt == ’1111’ then SEE PLI;
6866 // if Rn == ’1111’ then SEE LDRSB (literal);
6867 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6868 t = Bits32 (opcode, 15, 12);
6869 n = Bits32 (opcode, 19, 16);
6870 m = Bits32 (opcode, 3, 0);
6871
6872 // index = TRUE; add = TRUE; wback = FALSE;
6873 index = true;
6874 add = true;
6875 wback = false;
6876
6877 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6878 shift_t = SRType_LSL;
6879 shift_n = Bits32 (opcode, 5, 4);
6880
6881 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6882 if ((t == 13) || BadReg (m))
6883 return false;
6884 break;
6885
6886 case eEncodingA1:
6887 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6888 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6889 t = Bits32 (opcode, 15, 12);
6890 n = Bits32 (opcode, 19, 16);
6891 m = Bits32 (opcode, 3, 0);
6892
6893 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6894 index = BitIsSet (opcode, 24);
6895 add = BitIsSet (opcode, 23);
6896 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
6897
6898 // (shift_t, shift_n) = (SRType_LSL, 0);
6899 shift_t = SRType_LSL;
6900 shift_n = 0;
6901
6902 // if t == 15 || m == 15 then UNPREDICTABLE;
6903 if ((t == 15) || (m == 15))
6904 return false;
6905
6906 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6907 if (wback && ((n == 15) || (n == t)))
6908 return false;
6909 break;
6910
6911 default:
6912 return false;
6913 }
6914
6915 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6916 if (!success)
6917 return false;
6918
6919 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6920 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6921
6922 addr_t offset_addr;
6923 addr_t address;
6924
6925 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6926 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6927 if (!success)
6928 return false;
6929
6930 if (add)
6931 offset_addr = Rn + offset;
6932 else
6933 offset_addr = Rn - offset;
6934
6935 // address = if index then offset_addr else R[n];
6936 if (index)
6937 address = offset_addr;
6938 else
6939 address = Rn;
6940
6941 // R[t] = SignExtend(MemU[address,1], 32);
6942 Register base_reg;
6943 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6944 Register offset_reg;
6945 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6946
6947 EmulateInstruction::Context context;
6948 context.type = eContextRegisterLoad;
6949 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6950
6951 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6952 if (!success)
6953 return false;
6954
6955 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6956 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6957 return false;
6958
6959 // if wback then R[n] = offset_addr;
6960 if (wback)
6961 {
6962 context.type = eContextAdjustBaseRegister;
6963 context.SetAddress (offset_addr);
6964 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6965 return false;
6966 }
6967 }
6968 return true;
6969}
6970
Caroline Tice78fb5632011-03-02 00:39:42 +00006971// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
6972// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
6973// pre-indexed addressing.
6974bool
6975EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
6976{
6977#if 0
6978 if ConditionPassed() then
6979 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6980 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6981 address = if index then offset_addr else R[n];
6982 data = MemU[address,2];
6983 if wback then R[n] = offset_addr;
6984 if UnalignedSupport() || address<0> = ’0’ then
6985 R[t] = SignExtend(data, 32);
6986 else // Can only apply before ARMv7
6987 R[t] = bits(32) UNKNOWN;
6988#endif
6989
6990 bool success = false;
6991 const uint32_t opcode = OpcodeAsUnsigned (&success);
6992 if (!success)
6993 return false;
6994
6995 if (ConditionPassed())
6996 {
6997 uint32_t t;
6998 uint32_t n;
6999 uint32_t imm32;
7000 bool index;
7001 bool add;
7002 bool wback;
7003
7004 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7005 switch (encoding)
7006 {
7007 case eEncodingT1:
7008 // if Rn == ’1111’ then SEE LDRSH (literal);
7009 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7010 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7011 t = Bits32 (opcode, 15, 12);
7012 n = Bits32 (opcode, 19, 16);
7013 imm32 = Bits32 (opcode, 11, 0);
7014
7015 // index = TRUE; add = TRUE; wback = FALSE;
7016 index = true;
7017 add = true;
7018 wback = false;
7019
7020 // if t == 13 then UNPREDICTABLE;
7021 if (t == 13)
7022 return false;
7023
7024 break;
7025
7026 case eEncodingT2:
7027 // if Rn == ’1111’ then SEE LDRSH (literal);
7028 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
7029 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
7030 // if P == ’0’ && W == ’0’ then UNDEFINED;
7031 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7032 return false;
7033
7034 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7035 t = Bits32 (opcode, 15, 12);
7036 n = Bits32 (opcode, 19, 16);
7037 imm32 = Bits32 (opcode, 7, 0);
7038
7039 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
7040 index = BitIsSet (opcode, 10);
7041 add = BitIsSet (opcode, 9);
7042 wback = BitIsSet (opcode, 8);
7043
7044 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7045 if (BadReg (t) || (wback && (n == t)))
7046 return false;
7047
7048 break;
7049
7050 case eEncodingA1:
7051 {
7052 // if Rn == ’1111’ then SEE LDRSH (literal);
7053 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7054 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7055 t = Bits32 (opcode, 15, 12);
7056 n = Bits32 (opcode, 19, 16);
7057 uint32_t imm4H = Bits32 (opcode, 11,8);
7058 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007059 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007060
7061 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7062 index = BitIsSet (opcode, 24);
7063 add = BitIsSet (opcode, 23);
7064 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7065
7066 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7067 if ((t == 15) || (wback && (n == t)))
7068 return false;
7069
7070 break;
7071 }
7072
7073 default:
7074 return false;
7075 }
7076
7077 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7078 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7079 if (!success)
7080 return false;
7081
7082 addr_t offset_addr;
7083 if (add)
7084 offset_addr = Rn + imm32;
7085 else
7086 offset_addr = Rn - imm32;
7087
7088 // address = if index then offset_addr else R[n];
7089 addr_t address;
7090 if (index)
7091 address = offset_addr;
7092 else
7093 address = Rn;
7094
7095 // data = MemU[address,2];
7096 Register base_reg;
7097 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7098
7099 EmulateInstruction::Context context;
7100 context.type = eContextRegisterLoad;
7101 context.SetRegisterPlusOffset (base_reg, address - Rn);
7102
7103 uint64_t data = MemURead (context, address, 2, 0, &success);
7104 if (!success)
7105 return false;
7106
7107 // if wback then R[n] = offset_addr;
7108 if (wback)
7109 {
7110 context.type = eContextAdjustBaseRegister;
7111 context.SetAddress (offset_addr);
7112 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7113 return false;
7114 }
7115
7116 // if UnalignedSupport() || address<0> = ’0’ then
7117 if (UnalignedSupport() || BitIsClear (address, 0))
7118 {
7119 // R[t] = SignExtend(data, 32);
7120 int64_t signed_data = llvm::SignExtend64<16>(data);
7121 context.type = eContextRegisterLoad;
7122 context.SetRegisterPlusOffset (base_reg, address - Rn);
7123 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7124 return false;
7125 }
7126 else // Can only apply before ARMv7
7127 {
7128 // R[t] = bits(32) UNKNOWN;
7129 WriteBits32Unknown (t);
7130 }
7131 }
7132 return true;
7133}
7134
Caroline Ticed2fac092011-03-02 19:45:34 +00007135// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7136// sign-extends it to from a 32-bit word, and writes it to a register.
7137bool
7138EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
7139{
7140#if 0
7141 if ConditionPassed() then
7142 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7143 base = Align(PC,4);
7144 address = if add then (base + imm32) else (base - imm32);
7145 data = MemU[address,2];
7146 if UnalignedSupport() || address<0> = ’0’ then
7147 R[t] = SignExtend(data, 32);
7148 else // Can only apply before ARMv7
7149 R[t] = bits(32) UNKNOWN;
7150#endif
7151
7152 bool success = false;
7153 const uint32_t opcode = OpcodeAsUnsigned (&success);
7154 if (!success)
7155 return false;
7156
7157 if (ConditionPassed())
7158 {
7159 uint32_t t;
7160 uint32_t imm32;
7161 bool add;
7162
7163 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7164 switch (encoding)
7165 {
7166 case eEncodingT1:
7167 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7168 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7169 t = Bits32 (opcode, 15, 12);
7170 imm32 = Bits32 (opcode, 11, 0);
7171 add = BitIsSet (opcode, 23);
7172
7173 // if t == 13 then UNPREDICTABLE;
7174 if (t == 13)
7175 return false;
7176
7177 break;
7178
7179 case eEncodingA1:
7180 {
7181 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7182 t = Bits32 (opcode, 15, 12);
7183 uint32_t imm4H = Bits32 (opcode, 11, 8);
7184 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007185 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007186 add = BitIsSet (opcode, 23);
7187
7188 // if t == 15 then UNPREDICTABLE;
7189 if (t == 15)
7190 return false;
7191
7192 break;
7193 }
7194 default:
7195 return false;
7196 }
7197
7198 // base = Align(PC,4);
7199 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
7200 if (!success)
7201 return false;
7202
7203 uint64_t base = AlignPC (pc_value);
7204
7205 addr_t address;
7206 // address = if add then (base + imm32) else (base - imm32);
7207 if (add)
7208 address = base + imm32;
7209 else
7210 address = base - imm32;
7211
7212 // data = MemU[address,2];
7213 Register base_reg;
7214 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7215
7216 EmulateInstruction::Context context;
7217 context.type = eContextRegisterLoad;
7218 context.SetRegisterPlusOffset (base_reg, imm32);
7219
7220 uint64_t data = MemURead (context, address, 2, 0, &success);
7221 if (!success)
7222 return false;
7223
7224 // if UnalignedSupport() || address<0> = ’0’ then
7225 if (UnalignedSupport() || BitIsClear (address, 0))
7226 {
7227 // R[t] = SignExtend(data, 32);
7228 int64_t signed_data = llvm::SignExtend64<16>(data);
7229 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7230 return false;
7231 }
7232 else // Can only apply before ARMv7
7233 {
7234 // R[t] = bits(32) UNKNOWN;
7235 WriteBits32Unknown (t);
7236 }
7237 }
7238 return true;
7239}
7240
Caroline Tice291a3e92011-03-02 21:13:44 +00007241// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7242// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7243// shifted left by 0, 1, 2, or 3 bits.
7244bool
7245EmulateInstructionARM::EmulateLDRSHRegister (ARMEncoding encoding)
7246{
7247#if 0
7248 if ConditionPassed() then
7249 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7250 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7251 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7252 address = if index then offset_addr else R[n];
7253 data = MemU[address,2];
7254 if wback then R[n] = offset_addr;
7255 if UnalignedSupport() || address<0> = ’0’ then
7256 R[t] = SignExtend(data, 32);
7257 else // Can only apply before ARMv7
7258 R[t] = bits(32) UNKNOWN;
7259#endif
7260
7261 bool success = false;
7262 const uint32_t opcode = OpcodeAsUnsigned (&success);
7263 if (!success)
7264 return false;
7265
7266 if (ConditionPassed())
7267 {
7268 uint32_t t;
7269 uint32_t n;
7270 uint32_t m;
7271 bool index;
7272 bool add;
7273 bool wback;
7274 ARM_ShifterType shift_t;
7275 uint32_t shift_n;
7276
7277 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7278 switch (encoding)
7279 {
7280 case eEncodingT1:
7281 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7282 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7283 t = Bits32 (opcode, 2, 0);
7284 n = Bits32 (opcode, 5, 3);
7285 m = Bits32 (opcode, 8, 6);
7286
7287 // index = TRUE; add = TRUE; wback = FALSE;
7288 index = true;
7289 add = true;
7290 wback = false;
7291
7292 // (shift_t, shift_n) = (SRType_LSL, 0);
7293 shift_t = SRType_LSL;
7294 shift_n = 0;
7295
7296 break;
7297
7298 case eEncodingT2:
7299 // if Rn == ’1111’ then SEE LDRSH (literal);
7300 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7301 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7302 t = Bits32 (opcode, 15, 12);
7303 n = Bits32 (opcode, 19, 16);
7304 m = Bits32 (opcode, 3, 0);
7305
7306 // index = TRUE; add = TRUE; wback = FALSE;
7307 index = true;
7308 add = true;
7309 wback = false;
7310
7311 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7312 shift_t = SRType_LSL;
7313 shift_n = Bits32 (opcode, 5, 4);
7314
7315 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7316 if ((t == 13) || BadReg (m))
7317 return false;
7318
7319 break;
7320
7321 case eEncodingA1:
7322 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7323 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7324 t = Bits32 (opcode, 15, 12);
7325 n = Bits32 (opcode, 19, 16);
7326 m = Bits32 (opcode, 3, 0);
7327
7328 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7329 index = BitIsSet (opcode, 24);
7330 add = BitIsSet (opcode, 23);
7331 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7332
7333 // (shift_t, shift_n) = (SRType_LSL, 0);
7334 shift_t = SRType_LSL;
7335 shift_n = 0;
7336
7337 // if t == 15 || m == 15 then UNPREDICTABLE;
7338 if ((t == 15) || (m == 15))
7339 return false;
7340
7341 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7342 if (wback && ((n == 15) || (n == t)))
7343 return false;
7344
7345 break;
7346
7347 default:
7348 break;
7349 }
7350
7351 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7352 if (!success)
7353 return false;
7354
7355 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7356 if (!success)
7357 return false;
7358
7359 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7360 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7361
7362 addr_t offset_addr;
7363 addr_t address;
7364
7365 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7366 if (add)
7367 offset_addr = Rn + offset;
7368 else
7369 offset_addr = Rn - offset;
7370
7371 // address = if index then offset_addr else R[n];
7372 if (index)
7373 address = offset_addr;
7374 else
7375 address = Rn;
7376
7377 // data = MemU[address,2];
7378 Register base_reg;
7379 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7380
7381 Register offset_reg;
7382 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7383
7384 EmulateInstruction::Context context;
7385 context.type = eContextRegisterLoad;
7386 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7387
7388 uint64_t data = MemURead (context, address, 2, 0, &success);
7389 if (!success)
7390 return false;
7391
7392 // if wback then R[n] = offset_addr;
7393 if (wback)
7394 {
7395 context.type = eContextAdjustBaseRegister;
7396 context.SetAddress (offset_addr);
7397 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7398 return false;
7399 }
7400
7401 // if UnalignedSupport() || address<0> = ’0’ then
7402 if (UnalignedSupport() || BitIsClear (address, 0))
7403 {
7404 // R[t] = SignExtend(data, 32);
7405 context.type = eContextRegisterLoad;
7406 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7407
7408 int64_t signed_data = llvm::SignExtend64<16>(data);
7409 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7410 return false;
7411 }
7412 else // Can only apply before ARMv7
7413 {
7414 // R[t] = bits(32) UNKNOWN;
7415 WriteBits32Unknown (t);
7416 }
7417 }
7418 return true;
7419}
Caroline Tice6bf65162011-03-03 17:42:58 +00007420
7421// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7422// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7423bool
7424EmulateInstructionARM::EmulateSXTB (ARMEncoding encoding)
7425{
7426#if 0
7427 if ConditionPassed() then
7428 EncodingSpecificOperations();
7429 rotated = ROR(R[m], rotation);
7430 R[d] = SignExtend(rotated<7:0>, 32);
7431#endif
7432
7433 bool success = false;
7434 const uint32_t opcode = OpcodeAsUnsigned (&success);
7435 if (!success)
7436 return false;
7437
7438 if (ConditionPassed())
7439 {
7440 uint32_t d;
7441 uint32_t m;
7442 uint32_t rotation;
7443
7444 // EncodingSpecificOperations();
7445 switch (encoding)
7446 {
7447 case eEncodingT1:
7448 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7449 d = Bits32 (opcode, 2, 0);
7450 m = Bits32 (opcode, 5, 3);
7451 rotation = 0;
7452
7453 break;
7454
7455 case eEncodingT2:
7456 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7457 d = Bits32 (opcode, 11, 8);
7458 m = Bits32 (opcode, 3, 0);
7459 rotation = Bits32 (opcode, 5, 4) << 3;
7460
7461 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7462 if (BadReg (d) || BadReg (m))
7463 return false;
7464
7465 break;
7466
7467 case eEncodingA1:
7468 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7469 d = Bits32 (opcode, 15, 12);
7470 m = Bits32 (opcode, 3, 0);
7471 rotation = Bits32 (opcode, 11, 10) << 3;
7472
7473 // if d == 15 || m == 15 then UNPREDICTABLE;
7474 if ((d == 15) || (m == 15))
7475 return false;
7476
7477 break;
7478
7479 default:
7480 return false;
7481 }
7482
Caroline Tice868198b2011-03-03 18:04:49 +00007483 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7484 if (!success)
7485 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007486
7487 // rotated = ROR(R[m], rotation);
7488 uint64_t rotated = ROR (Rm, rotation);
7489
7490 // R[d] = SignExtend(rotated<7:0>, 32);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007491 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007492
7493 Register source_reg;
7494 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7495
7496 EmulateInstruction::Context context;
7497 context.type = eContextRegisterLoad;
7498 context.SetRegister (source_reg);
7499
Caroline Tice8ce96d92011-03-03 18:27:17 +00007500 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007501 return false;
7502 }
7503 return true;
7504}
Caroline Tice291a3e92011-03-02 21:13:44 +00007505
Caroline Tice868198b2011-03-03 18:04:49 +00007506// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7507// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7508bool
7509EmulateInstructionARM::EmulateSXTH (ARMEncoding encoding)
7510{
7511#if 0
7512 if ConditionPassed() then
7513 EncodingSpecificOperations();
7514 rotated = ROR(R[m], rotation);
7515 R[d] = SignExtend(rotated<15:0>, 32);
7516#endif
7517
7518 bool success = false;
7519 const uint32_t opcode = OpcodeAsUnsigned (&success);
7520 if (!success)
7521 return false;
7522
7523 if (ConditionPassed())
7524 {
7525 uint32_t d;
7526 uint32_t m;
7527 uint32_t rotation;
7528
7529 // EncodingSpecificOperations();
7530 switch (encoding)
7531 {
7532 case eEncodingT1:
7533 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7534 d = Bits32 (opcode, 2, 0);
7535 m = Bits32 (opcode, 5, 3);
7536 rotation = 0;
7537
7538 break;
7539
7540 case eEncodingT2:
7541 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7542 d = Bits32 (opcode, 11, 8);
7543 m = Bits32 (opcode, 3, 0);
7544 rotation = Bits32 (opcode, 5, 4) << 3;
7545
7546 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7547 if (BadReg (d) || BadReg (m))
7548 return false;
7549
7550 break;
7551
7552 case eEncodingA1:
7553 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7554 d = Bits32 (opcode, 15, 12);
7555 m = Bits32 (opcode, 3, 0);
7556 rotation = Bits32 (opcode, 11, 10) << 3;
7557
7558 // if d == 15 || m == 15 then UNPREDICTABLE;
7559 if ((d == 15) || (m == 15))
7560 return false;
7561
7562 break;
7563
7564 default:
7565 return false;
7566 }
7567
7568 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7569 if (!success)
7570 return false;
7571
7572 // rotated = ROR(R[m], rotation);
7573 uint64_t rotated = ROR (Rm, rotation);
7574
7575 // R[d] = SignExtend(rotated<15:0>, 32);
7576 Register source_reg;
7577 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7578
7579 EmulateInstruction::Context context;
7580 context.type = eContextRegisterLoad;
7581 context.SetRegister (source_reg);
7582
Caroline Tice8ce96d92011-03-03 18:27:17 +00007583 int64_t data = llvm::SignExtend64<16> (rotated);
7584 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007585 return false;
7586 }
7587
7588 return true;
7589}
7590
Caroline Tice8ce96d92011-03-03 18:27:17 +00007591// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7592// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7593bool
7594EmulateInstructionARM::EmulateUXTB (ARMEncoding encoding)
7595{
7596#if 0
7597 if ConditionPassed() then
7598 EncodingSpecificOperations();
7599 rotated = ROR(R[m], rotation);
7600 R[d] = ZeroExtend(rotated<7:0>, 32);
7601#endif
7602
7603 bool success = false;
7604 const uint32_t opcode = OpcodeAsUnsigned (&success);
7605 if (!success)
7606 return false;
7607
7608 if (ConditionPassed())
7609 {
7610 uint32_t d;
7611 uint32_t m;
7612 uint32_t rotation;
7613
7614 // EncodingSpecificOperations();
7615 switch (encoding)
7616 {
7617 case eEncodingT1:
7618 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7619 d = Bits32 (opcode, 2, 0);
7620 m = Bits32 (opcode, 5, 3);
7621 rotation = 0;
7622
7623 break;
7624
7625 case eEncodingT2:
7626 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7627 d = Bits32 (opcode, 11, 8);
7628 m = Bits32 (opcode, 3, 0);
7629 rotation = Bits32 (opcode, 5, 4) << 3;
7630
7631 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7632 if (BadReg (d) || BadReg (m))
7633 return false;
7634
7635 break;
7636
7637 case eEncodingA1:
7638 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7639 d = Bits32 (opcode, 15, 12);
7640 m = Bits32 (opcode, 3, 0);
7641 rotation = Bits32 (opcode, 11, 10) << 3;
7642
7643 // if d == 15 || m == 15 then UNPREDICTABLE;
7644 if ((d == 15) || (m == 15))
7645 return false;
7646
7647 break;
7648
7649 default:
7650 return false;
7651 }
7652
7653 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7654 if (!success)
7655 return false;
7656
7657 // rotated = ROR(R[m], rotation);
7658 uint64_t rotated = ROR (Rm, rotation);
7659
7660 // R[d] = ZeroExtend(rotated<7:0>, 32);
7661 Register source_reg;
7662 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7663
7664 EmulateInstruction::Context context;
7665 context.type = eContextRegisterLoad;
7666 context.SetRegister (source_reg);
7667
7668 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7669 return false;
7670 }
7671 return true;
7672}
7673
Caroline Tice11555f22011-03-03 18:48:58 +00007674// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7675// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7676bool
7677EmulateInstructionARM::EmulateUXTH (ARMEncoding encoding)
7678{
7679#if 0
7680 if ConditionPassed() then
7681 EncodingSpecificOperations();
7682 rotated = ROR(R[m], rotation);
7683 R[d] = ZeroExtend(rotated<15:0>, 32);
7684#endif
7685
7686 bool success = false;
7687 const uint32_t opcode = OpcodeAsUnsigned (&success);
7688 if (!success)
7689 return false;
7690
7691 if (ConditionPassed ())
7692 {
7693 uint32_t d;
7694 uint32_t m;
7695 uint32_t rotation;
7696
7697 switch (encoding)
7698 {
7699 case eEncodingT1:
7700 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7701 d = Bits32 (opcode, 2, 0);
7702 m = Bits32 (opcode, 5, 3);
7703 rotation = 0;
7704
7705 break;
7706
7707 case eEncodingT2:
7708 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7709 d = Bits32 (opcode, 11, 8);
7710 m = Bits32 (opcode, 3, 0);
7711 rotation = Bits32 (opcode, 5, 4) << 3;
7712
7713 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7714 if (BadReg (d) || BadReg (m))
7715 return false;
7716
7717 break;
7718
7719 case eEncodingA1:
7720 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7721 d = Bits32 (opcode, 15, 12);
7722 m = Bits32 (opcode, 3, 0);
7723 rotation = Bits32 (opcode, 11, 10) << 3;
7724
7725 // if d == 15 || m == 15 then UNPREDICTABLE;
7726 if ((d == 15) || (m == 15))
7727 return false;
7728
7729 break;
7730
7731 default:
7732 return false;
7733 }
7734
7735 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7736 if (!success)
7737 return false;
7738
7739 // rotated = ROR(R[m], rotation);
7740 uint64_t rotated = ROR (Rm, rotation);
7741
7742 // R[d] = ZeroExtend(rotated<15:0>, 32);
7743 Register source_reg;
7744 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7745
7746 EmulateInstruction::Context context;
7747 context.type = eContextRegisterLoad;
7748 context.SetRegister (source_reg);
7749
7750 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7751 return false;
7752 }
7753 return true;
7754}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007755
7756// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7757// word respectively.
7758bool
7759EmulateInstructionARM::EmulateRFE (ARMEncoding encoding)
7760{
7761#if 0
7762 if ConditionPassed() then
7763 EncodingSpecificOperations();
7764 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7765 UNPREDICTABLE;
7766 else
7767 address = if increment then R[n] else R[n]-8;
7768 if wordhigher then address = address+4;
7769 CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
7770 BranchWritePC(MemA[address,4]);
7771 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7772#endif
7773
7774 bool success = false;
7775 const uint32_t opcode = OpcodeAsUnsigned (&success);
7776 if (!success)
7777 return false;
7778
7779 if (ConditionPassed())
7780 {
7781 uint32_t n;
7782 bool wback;
7783 bool increment;
7784 bool wordhigher;
7785
7786 // EncodingSpecificOperations();
7787 switch (encoding)
7788 {
7789 case eEncodingT1:
7790 // n = UInt(Rn); wback = (W == ’1’); increment = FALSE; wordhigher = FALSE;
7791 n = Bits32 (opcode, 19, 16);
7792 wback = BitIsSet (opcode, 21);
7793 increment = false;
7794 wordhigher = false;
7795
7796 // if n == 15 then UNPREDICTABLE;
7797 if (n == 15)
7798 return false;
7799
7800 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7801 if (InITBlock() && !LastInITBlock())
7802 return false;
7803
7804 break;
7805
7806 case eEncodingT2:
7807 // n = UInt(Rn); wback = (W == ’1’); increment = TRUE; wordhigher = FALSE;
7808 n = Bits32 (opcode, 19, 16);
7809 wback = BitIsSet (opcode, 21);
7810 increment = true;
7811 wordhigher = false;
7812
7813 // if n == 15 then UNPREDICTABLE;
7814 if (n == 15)
7815 return false;
7816
7817 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7818 if (InITBlock() && !LastInITBlock())
7819 return false;
7820
7821 break;
7822
7823 case eEncodingA1:
7824 // n = UInt(Rn);
7825 n = Bits32 (opcode, 19, 16);
7826
7827 // wback = (W == ’1’); inc = (U == ’1’); wordhigher = (P == U);
7828 wback = BitIsSet (opcode, 21);
7829 increment = BitIsSet (opcode, 23);
7830 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
7831
7832 // if n == 15 then UNPREDICTABLE;
7833 if (n == 15)
7834 return false;
7835
7836 break;
7837
7838 default:
7839 return false;
7840 }
7841
7842 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7843 if (!CurrentModeIsPrivileged ())
7844 // UNPREDICTABLE;
7845 return false;
7846 else
7847 {
7848 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7849 if (!success)
7850 return false;
7851
7852 addr_t address;
7853 // address = if increment then R[n] else R[n]-8;
7854 if (increment)
7855 address = Rn;
7856 else
7857 address = Rn - 8;
7858
7859 // if wordhigher then address = address+4;
7860 if (wordhigher)
7861 address = address + 4;
7862
7863 // CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
7864 Register base_reg;
7865 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7866
7867 EmulateInstruction::Context context;
7868 context.type = eContextReturnFromException;
7869 context.SetRegisterPlusOffset (base_reg, address - Rn);
7870
7871 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
7872 if (!success)
7873 return false;
7874
7875 CPSRWriteByInstr (data, 15, true);
7876
7877 // BranchWritePC(MemA[address,4]);
7878 uint64_t data2 = MemARead (context, address, 4, 0, &success);
7879 if (!success)
7880 return false;
7881
7882 BranchWritePC (context, data2);
7883
7884 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7885 if (wback)
7886 {
7887 context.type = eContextAdjustBaseRegister;
7888 if (increment)
7889 {
7890 context.SetOffset (8);
7891 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
7892 return false;
7893 }
7894 else
7895 {
7896 context.SetOffset (-8);
7897 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
7898 return false;
7899 }
7900 } // if wback
7901 }
7902 } // if ConditionPassed()
7903 return true;
7904}
Caroline Tice11555f22011-03-03 18:48:58 +00007905
Johnny Chen2115b412011-02-21 23:42:44 +00007906// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
7907// and writes the result to the destination register. It can optionally update the condition flags based on
7908// the result.
7909bool
7910EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
7911{
7912#if 0
7913 // ARM pseudo code...
7914 if ConditionPassed() then
7915 EncodingSpecificOperations();
7916 result = R[n] EOR imm32;
7917 if d == 15 then // Can only occur for ARM encoding
7918 ALUWritePC(result); // setflags is always FALSE here
7919 else
7920 R[d] = result;
7921 if setflags then
7922 APSR.N = result<31>;
7923 APSR.Z = IsZeroBit(result);
7924 APSR.C = carry;
7925 // APSR.V unchanged
7926#endif
7927
7928 bool success = false;
7929 const uint32_t opcode = OpcodeAsUnsigned (&success);
7930 if (!success)
7931 return false;
7932
7933 if (ConditionPassed())
7934 {
7935 uint32_t Rd, Rn;
7936 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7937 bool setflags;
7938 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7939 switch (encoding)
7940 {
7941 case eEncodingT1:
7942 Rd = Bits32(opcode, 11, 8);
7943 Rn = Bits32(opcode, 19, 16);
7944 setflags = BitIsSet(opcode, 20);
7945 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7946 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
7947 if (Rd == 15 && setflags)
7948 return EmulateTEQImm(eEncodingT1);
7949 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
7950 return false;
7951 break;
7952 case eEncodingA1:
7953 Rd = Bits32(opcode, 15, 12);
7954 Rn = Bits32(opcode, 19, 16);
7955 setflags = BitIsSet(opcode, 20);
7956 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7957 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7958 // TODO: Emulate SUBS PC, LR and related instructions.
7959 if (Rd == 15 && setflags)
7960 return false;
7961 break;
7962 default:
7963 return false;
7964 }
7965
7966 // Read the first operand.
7967 uint32_t val1 = ReadCoreReg(Rn, &success);
7968 if (!success)
7969 return false;
7970
7971 uint32_t result = val1 ^ imm32;
7972
7973 EmulateInstruction::Context context;
7974 context.type = EmulateInstruction::eContextImmediate;
7975 context.SetNoArgs ();
7976
7977 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7978 return false;
7979 }
7980 return true;
7981}
7982
7983// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
7984// optionally-shifted register value, and writes the result to the destination register.
7985// It can optionally update the condition flags based on the result.
7986bool
7987EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
7988{
7989#if 0
7990 // ARM pseudo code...
7991 if ConditionPassed() then
7992 EncodingSpecificOperations();
7993 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7994 result = R[n] EOR shifted;
7995 if d == 15 then // Can only occur for ARM encoding
7996 ALUWritePC(result); // setflags is always FALSE here
7997 else
7998 R[d] = result;
7999 if setflags then
8000 APSR.N = result<31>;
8001 APSR.Z = IsZeroBit(result);
8002 APSR.C = carry;
8003 // APSR.V unchanged
8004#endif
8005
8006 bool success = false;
8007 const uint32_t opcode = OpcodeAsUnsigned (&success);
8008 if (!success)
8009 return false;
8010
8011 if (ConditionPassed())
8012 {
8013 uint32_t Rd, Rn, Rm;
8014 ARM_ShifterType shift_t;
8015 uint32_t shift_n; // the shift applied to the value read from Rm
8016 bool setflags;
8017 uint32_t carry;
8018 switch (encoding)
8019 {
8020 case eEncodingT1:
8021 Rd = Rn = Bits32(opcode, 2, 0);
8022 Rm = Bits32(opcode, 5, 3);
8023 setflags = !InITBlock();
8024 shift_t = SRType_LSL;
8025 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008026 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008027 case eEncodingT2:
8028 Rd = Bits32(opcode, 11, 8);
8029 Rn = Bits32(opcode, 19, 16);
8030 Rm = Bits32(opcode, 3, 0);
8031 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008032 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8033 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008034 if (Rd == 15 && setflags)
8035 return EmulateTEQReg(eEncodingT1);
8036 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8037 return false;
8038 break;
8039 case eEncodingA1:
8040 Rd = Bits32(opcode, 15, 12);
8041 Rn = Bits32(opcode, 19, 16);
8042 Rm = Bits32(opcode, 3, 0);
8043 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008044 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008045 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8046 // TODO: Emulate SUBS PC, LR and related instructions.
8047 if (Rd == 15 && setflags)
8048 return false;
8049 break;
8050 default:
8051 return false;
8052 }
8053
8054 // Read the first operand.
8055 uint32_t val1 = ReadCoreReg(Rn, &success);
8056 if (!success)
8057 return false;
8058
8059 // Read the second operand.
8060 uint32_t val2 = ReadCoreReg(Rm, &success);
8061 if (!success)
8062 return false;
8063
8064 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8065 uint32_t result = val1 ^ shifted;
8066
8067 EmulateInstruction::Context context;
8068 context.type = EmulateInstruction::eContextImmediate;
8069 context.SetNoArgs ();
8070
8071 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8072 return false;
8073 }
8074 return true;
8075}
8076
Johnny Chen7c5234d2011-02-18 23:41:11 +00008077// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8078// writes the result to the destination register. It can optionally update the condition flags based
8079// on the result.
8080bool
8081EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
8082{
8083#if 0
8084 // ARM pseudo code...
8085 if ConditionPassed() then
8086 EncodingSpecificOperations();
8087 result = R[n] OR imm32;
8088 if d == 15 then // Can only occur for ARM encoding
8089 ALUWritePC(result); // setflags is always FALSE here
8090 else
8091 R[d] = result;
8092 if setflags then
8093 APSR.N = result<31>;
8094 APSR.Z = IsZeroBit(result);
8095 APSR.C = carry;
8096 // APSR.V unchanged
8097#endif
8098
8099 bool success = false;
8100 const uint32_t opcode = OpcodeAsUnsigned (&success);
8101 if (!success)
8102 return false;
8103
8104 if (ConditionPassed())
8105 {
8106 uint32_t Rd, Rn;
8107 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8108 bool setflags;
8109 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8110 switch (encoding)
8111 {
8112 case eEncodingT1:
8113 Rd = Bits32(opcode, 11, 8);
8114 Rn = Bits32(opcode, 19, 16);
8115 setflags = BitIsSet(opcode, 20);
8116 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8117 // if Rn == ‘1111’ then SEE MOV (immediate);
8118 if (Rn == 15)
8119 return EmulateMOVRdImm(eEncodingT2);
8120 if (BadReg(Rd) || Rn == 13)
8121 return false;
8122 break;
8123 case eEncodingA1:
8124 Rd = Bits32(opcode, 15, 12);
8125 Rn = Bits32(opcode, 19, 16);
8126 setflags = BitIsSet(opcode, 20);
8127 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8128 // TODO: Emulate SUBS PC, LR and related instructions.
8129 if (Rd == 15 && setflags)
8130 return false;
8131 break;
8132 default:
8133 return false;
8134 }
8135
8136 // Read the first operand.
8137 uint32_t val1 = ReadCoreReg(Rn, &success);
8138 if (!success)
8139 return false;
8140
8141 uint32_t result = val1 | imm32;
8142
8143 EmulateInstruction::Context context;
8144 context.type = EmulateInstruction::eContextImmediate;
8145 context.SetNoArgs ();
8146
8147 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8148 return false;
8149 }
8150 return true;
8151}
8152
8153// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8154// value, and writes the result to the destination register. It can optionally update the condition flags based
8155// on the result.
8156bool
8157EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
8158{
8159#if 0
8160 // ARM pseudo code...
8161 if ConditionPassed() then
8162 EncodingSpecificOperations();
8163 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8164 result = R[n] OR shifted;
8165 if d == 15 then // Can only occur for ARM encoding
8166 ALUWritePC(result); // setflags is always FALSE here
8167 else
8168 R[d] = result;
8169 if setflags then
8170 APSR.N = result<31>;
8171 APSR.Z = IsZeroBit(result);
8172 APSR.C = carry;
8173 // APSR.V unchanged
8174#endif
8175
8176 bool success = false;
8177 const uint32_t opcode = OpcodeAsUnsigned (&success);
8178 if (!success)
8179 return false;
8180
8181 if (ConditionPassed())
8182 {
8183 uint32_t Rd, Rn, Rm;
8184 ARM_ShifterType shift_t;
8185 uint32_t shift_n; // the shift applied to the value read from Rm
8186 bool setflags;
8187 uint32_t carry;
8188 switch (encoding)
8189 {
8190 case eEncodingT1:
8191 Rd = Rn = Bits32(opcode, 2, 0);
8192 Rm = Bits32(opcode, 5, 3);
8193 setflags = !InITBlock();
8194 shift_t = SRType_LSL;
8195 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008196 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008197 case eEncodingT2:
8198 Rd = Bits32(opcode, 11, 8);
8199 Rn = Bits32(opcode, 19, 16);
8200 Rm = Bits32(opcode, 3, 0);
8201 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008202 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8203 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008204 if (Rn == 15)
8205 return EmulateMOVRdRm(eEncodingT3);
8206 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8207 return false;
8208 break;
8209 case eEncodingA1:
8210 Rd = Bits32(opcode, 15, 12);
8211 Rn = Bits32(opcode, 19, 16);
8212 Rm = Bits32(opcode, 3, 0);
8213 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008214 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008215 // TODO: Emulate SUBS PC, LR and related instructions.
8216 if (Rd == 15 && setflags)
8217 return false;
8218 break;
8219 default:
8220 return false;
8221 }
8222
8223 // Read the first operand.
8224 uint32_t val1 = ReadCoreReg(Rn, &success);
8225 if (!success)
8226 return false;
8227
8228 // Read the second operand.
8229 uint32_t val2 = ReadCoreReg(Rm, &success);
8230 if (!success)
8231 return false;
8232
8233 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008234 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008235
8236 EmulateInstruction::Context context;
8237 context.type = EmulateInstruction::eContextImmediate;
8238 context.SetNoArgs ();
8239
8240 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8241 return false;
8242 }
8243 return true;
8244}
8245
Johnny Chened32e7c2011-02-22 23:42:58 +00008246// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8247// the destination register. It can optionally update the condition flags based on the result.
8248bool
8249EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
8250{
8251#if 0
8252 // ARM pseudo code...
8253 if ConditionPassed() then
8254 EncodingSpecificOperations();
8255 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8256 if d == 15 then // Can only occur for ARM encoding
8257 ALUWritePC(result); // setflags is always FALSE here
8258 else
8259 R[d] = result;
8260 if setflags then
8261 APSR.N = result<31>;
8262 APSR.Z = IsZeroBit(result);
8263 APSR.C = carry;
8264 APSR.V = overflow;
8265#endif
8266
8267 bool success = false;
8268 const uint32_t opcode = OpcodeAsUnsigned (&success);
8269 if (!success)
8270 return false;
8271
8272 uint32_t Rd; // the destination register
8273 uint32_t Rn; // the first operand
8274 bool setflags;
8275 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8276 switch (encoding) {
8277 case eEncodingT1:
8278 Rd = Bits32(opcode, 2, 0);
8279 Rn = Bits32(opcode, 5, 3);
8280 setflags = !InITBlock();
8281 imm32 = 0;
8282 break;
8283 case eEncodingT2:
8284 Rd = Bits32(opcode, 11, 8);
8285 Rn = Bits32(opcode, 19, 16);
8286 setflags = BitIsSet(opcode, 20);
8287 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8288 if (BadReg(Rd) || BadReg(Rn))
8289 return false;
8290 break;
8291 case eEncodingA1:
8292 Rd = Bits32(opcode, 15, 12);
8293 Rn = Bits32(opcode, 19, 16);
8294 setflags = BitIsSet(opcode, 20);
8295 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8296 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8297 // TODO: Emulate SUBS PC, LR and related instructions.
8298 if (Rd == 15 && setflags)
8299 return false;
8300 break;
8301 default:
8302 return false;
8303 }
8304 // Read the register value from the operand register Rn.
8305 uint32_t reg_val = ReadCoreReg(Rn, &success);
8306 if (!success)
8307 return false;
8308
8309 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8310
8311 EmulateInstruction::Context context;
8312 context.type = EmulateInstruction::eContextImmediate;
8313 context.SetNoArgs ();
8314
8315 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8316 return false;
8317
8318 return true;
8319}
8320
8321// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8322// result to the destination register. It can optionally update the condition flags based on the result.
8323bool
8324EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
8325{
8326#if 0
8327 // ARM pseudo code...
8328 if ConditionPassed() then
8329 EncodingSpecificOperations();
8330 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8331 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8332 if d == 15 then // Can only occur for ARM encoding
8333 ALUWritePC(result); // setflags is always FALSE here
8334 else
8335 R[d] = result;
8336 if setflags then
8337 APSR.N = result<31>;
8338 APSR.Z = IsZeroBit(result);
8339 APSR.C = carry;
8340 APSR.V = overflow;
8341#endif
8342
8343 bool success = false;
8344 const uint32_t opcode = OpcodeAsUnsigned (&success);
8345 if (!success)
8346 return false;
8347
8348 uint32_t Rd; // the destination register
8349 uint32_t Rn; // the first operand
8350 uint32_t Rm; // the second operand
8351 bool setflags;
8352 ARM_ShifterType shift_t;
8353 uint32_t shift_n; // the shift applied to the value read from Rm
8354 switch (encoding) {
8355 case eEncodingT1:
8356 Rd = Bits32(opcode, 11, 8);
8357 Rn = Bits32(opcode, 19, 16);
8358 Rm = Bits32(opcode, 3, 0);
8359 setflags = BitIsSet(opcode, 20);
8360 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8361 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8362 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8363 return false;
8364 break;
8365 case eEncodingA1:
8366 Rd = Bits32(opcode, 15, 12);
8367 Rn = Bits32(opcode, 19, 16);
8368 Rm = Bits32(opcode, 3, 0);
8369 setflags = BitIsSet(opcode, 20);
8370 shift_n = DecodeImmShiftARM(opcode, shift_t);
8371 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8372 // TODO: Emulate SUBS PC, LR and related instructions.
8373 if (Rd == 15 && setflags)
8374 return false;
8375 break;
8376 default:
8377 return false;
8378 }
8379 // Read the register value from register Rn.
8380 uint32_t val1 = ReadCoreReg(Rn, &success);
8381 if (!success)
8382 return false;
8383
8384 // Read the register value from register Rm.
8385 uint32_t val2 = ReadCoreReg(Rm, &success);
8386 if (!success)
8387 return false;
8388
8389 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8390 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8391
8392 EmulateInstruction::Context context;
8393 context.type = EmulateInstruction::eContextImmediate;
8394 context.SetNoArgs();
8395 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8396 return false;
8397
8398 return true;
8399}
8400
Johnny Chen90e607b2011-02-23 00:07:09 +00008401// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8402// an immediate value, and writes the result to the destination register. It can optionally update the condition
8403// flags based on the result.
8404bool
8405EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
8406{
8407#if 0
8408 // ARM pseudo code...
8409 if ConditionPassed() then
8410 EncodingSpecificOperations();
8411 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8412 if d == 15 then
8413 ALUWritePC(result); // setflags is always FALSE here
8414 else
8415 R[d] = result;
8416 if setflags then
8417 APSR.N = result<31>;
8418 APSR.Z = IsZeroBit(result);
8419 APSR.C = carry;
8420 APSR.V = overflow;
8421#endif
8422
8423 bool success = false;
8424 const uint32_t opcode = OpcodeAsUnsigned (&success);
8425 if (!success)
8426 return false;
8427
8428 uint32_t Rd; // the destination register
8429 uint32_t Rn; // the first operand
8430 bool setflags;
8431 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8432 switch (encoding) {
8433 case eEncodingA1:
8434 Rd = Bits32(opcode, 15, 12);
8435 Rn = Bits32(opcode, 19, 16);
8436 setflags = BitIsSet(opcode, 20);
8437 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8438 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8439 // TODO: Emulate SUBS PC, LR and related instructions.
8440 if (Rd == 15 && setflags)
8441 return false;
8442 break;
8443 default:
8444 return false;
8445 }
8446 // Read the register value from the operand register Rn.
8447 uint32_t reg_val = ReadCoreReg(Rn, &success);
8448 if (!success)
8449 return false;
8450
8451 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8452
8453 EmulateInstruction::Context context;
8454 context.type = EmulateInstruction::eContextImmediate;
8455 context.SetNoArgs ();
8456
8457 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8458 return false;
8459
8460 return true;
8461}
8462
8463// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8464// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8465// condition flags based on the result.
8466bool
8467EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
8468{
8469#if 0
8470 // ARM pseudo code...
8471 if ConditionPassed() then
8472 EncodingSpecificOperations();
8473 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8474 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8475 if d == 15 then
8476 ALUWritePC(result); // setflags is always FALSE here
8477 else
8478 R[d] = result;
8479 if setflags then
8480 APSR.N = result<31>;
8481 APSR.Z = IsZeroBit(result);
8482 APSR.C = carry;
8483 APSR.V = overflow;
8484#endif
8485
8486 bool success = false;
8487 const uint32_t opcode = OpcodeAsUnsigned (&success);
8488 if (!success)
8489 return false;
8490
8491 uint32_t Rd; // the destination register
8492 uint32_t Rn; // the first operand
8493 uint32_t Rm; // the second operand
8494 bool setflags;
8495 ARM_ShifterType shift_t;
8496 uint32_t shift_n; // the shift applied to the value read from Rm
8497 switch (encoding) {
8498 case eEncodingA1:
8499 Rd = Bits32(opcode, 15, 12);
8500 Rn = Bits32(opcode, 19, 16);
8501 Rm = Bits32(opcode, 3, 0);
8502 setflags = BitIsSet(opcode, 20);
8503 shift_n = DecodeImmShiftARM(opcode, shift_t);
8504 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8505 // TODO: Emulate SUBS PC, LR and related instructions.
8506 if (Rd == 15 && setflags)
8507 return false;
8508 break;
8509 default:
8510 return false;
8511 }
8512 // Read the register value from register Rn.
8513 uint32_t val1 = ReadCoreReg(Rn, &success);
8514 if (!success)
8515 return false;
8516
8517 // Read the register value from register Rm.
8518 uint32_t val2 = ReadCoreReg(Rm, &success);
8519 if (!success)
8520 return false;
8521
8522 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8523 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8524
8525 EmulateInstruction::Context context;
8526 context.type = EmulateInstruction::eContextImmediate;
8527 context.SetNoArgs();
8528 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8529 return false;
8530
8531 return true;
8532}
8533
Johnny Chen9b381772011-02-23 01:01:21 +00008534// Subtract with Carry (immediate) subtracts an immediate value and the value of
8535// NOT (Carry flag) from a register value, and writes the result to the destination register.
8536// It can optionally update the condition flags based on the result.
8537bool
8538EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
8539{
8540#if 0
8541 // ARM pseudo code...
8542 if ConditionPassed() then
8543 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008544 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008545 if d == 15 then // Can only occur for ARM encoding
8546 ALUWritePC(result); // setflags is always FALSE here
8547 else
8548 R[d] = result;
8549 if setflags then
8550 APSR.N = result<31>;
8551 APSR.Z = IsZeroBit(result);
8552 APSR.C = carry;
8553 APSR.V = overflow;
8554#endif
8555
8556 bool success = false;
8557 const uint32_t opcode = OpcodeAsUnsigned (&success);
8558 if (!success)
8559 return false;
8560
8561 uint32_t Rd; // the destination register
8562 uint32_t Rn; // the first operand
8563 bool setflags;
8564 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8565 switch (encoding) {
8566 case eEncodingT1:
8567 Rd = Bits32(opcode, 11, 8);
8568 Rn = Bits32(opcode, 19, 16);
8569 setflags = BitIsSet(opcode, 20);
8570 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8571 if (BadReg(Rd) || BadReg(Rn))
8572 return false;
8573 break;
8574 case eEncodingA1:
8575 Rd = Bits32(opcode, 15, 12);
8576 Rn = Bits32(opcode, 19, 16);
8577 setflags = BitIsSet(opcode, 20);
8578 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8579 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8580 // TODO: Emulate SUBS PC, LR and related instructions.
8581 if (Rd == 15 && setflags)
8582 return false;
8583 break;
8584 default:
8585 return false;
8586 }
8587 // Read the register value from the operand register Rn.
8588 uint32_t reg_val = ReadCoreReg(Rn, &success);
8589 if (!success)
8590 return false;
8591
8592 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8593
8594 EmulateInstruction::Context context;
8595 context.type = EmulateInstruction::eContextImmediate;
8596 context.SetNoArgs ();
8597
8598 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8599 return false;
8600
8601 return true;
8602}
8603
8604// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8605// NOT (Carry flag) from a register value, and writes the result to the destination register.
8606// It can optionally update the condition flags based on the result.
8607bool
8608EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8609{
8610#if 0
8611 // ARM pseudo code...
8612 if ConditionPassed() then
8613 EncodingSpecificOperations();
8614 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8615 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8616 if d == 15 then // Can only occur for ARM encoding
8617 ALUWritePC(result); // setflags is always FALSE here
8618 else
8619 R[d] = result;
8620 if setflags then
8621 APSR.N = result<31>;
8622 APSR.Z = IsZeroBit(result);
8623 APSR.C = carry;
8624 APSR.V = overflow;
8625#endif
8626
8627 bool success = false;
8628 const uint32_t opcode = OpcodeAsUnsigned (&success);
8629 if (!success)
8630 return false;
8631
8632 uint32_t Rd; // the destination register
8633 uint32_t Rn; // the first operand
8634 uint32_t Rm; // the second operand
8635 bool setflags;
8636 ARM_ShifterType shift_t;
8637 uint32_t shift_n; // the shift applied to the value read from Rm
8638 switch (encoding) {
8639 case eEncodingT1:
8640 Rd = Rn = Bits32(opcode, 2, 0);
8641 Rm = Bits32(opcode, 5, 3);
8642 setflags = !InITBlock();
8643 shift_t = SRType_LSL;
8644 shift_n = 0;
8645 break;
8646 case eEncodingT2:
8647 Rd = Bits32(opcode, 11, 8);
8648 Rn = Bits32(opcode, 19, 16);
8649 Rm = Bits32(opcode, 3, 0);
8650 setflags = BitIsSet(opcode, 20);
8651 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8652 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8653 return false;
8654 break;
8655 case eEncodingA1:
8656 Rd = Bits32(opcode, 15, 12);
8657 Rn = Bits32(opcode, 19, 16);
8658 Rm = Bits32(opcode, 3, 0);
8659 setflags = BitIsSet(opcode, 20);
8660 shift_n = DecodeImmShiftARM(opcode, shift_t);
8661 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8662 // TODO: Emulate SUBS PC, LR and related instructions.
8663 if (Rd == 15 && setflags)
8664 return false;
8665 break;
8666 default:
8667 return false;
8668 }
8669 // Read the register value from register Rn.
8670 uint32_t val1 = ReadCoreReg(Rn, &success);
8671 if (!success)
8672 return false;
8673
8674 // Read the register value from register Rm.
8675 uint32_t val2 = ReadCoreReg(Rm, &success);
8676 if (!success)
8677 return false;
8678
8679 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8680 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8681
8682 EmulateInstruction::Context context;
8683 context.type = EmulateInstruction::eContextImmediate;
8684 context.SetNoArgs();
8685 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8686 return false;
8687
8688 return true;
8689}
8690
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008691// This instruction subtracts an immediate value from a register value, and writes the result
8692// to the destination register. It can optionally update the condition flags based on the result.
8693bool
8694EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8695{
8696#if 0
8697 // ARM pseudo code...
8698 if ConditionPassed() then
8699 EncodingSpecificOperations();
8700 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8701 R[d] = result;
8702 if setflags then
8703 APSR.N = result<31>;
8704 APSR.Z = IsZeroBit(result);
8705 APSR.C = carry;
8706 APSR.V = overflow;
8707#endif
8708
8709 bool success = false;
8710 const uint32_t opcode = OpcodeAsUnsigned (&success);
8711 if (!success)
8712 return false;
8713
8714 uint32_t Rd; // the destination register
8715 uint32_t Rn; // the first operand
8716 bool setflags;
8717 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8718 switch (encoding) {
8719 case eEncodingT1:
8720 Rd = Bits32(opcode, 2, 0);
8721 Rn = Bits32(opcode, 5, 3);
8722 setflags = !InITBlock();
8723 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8724 break;
8725 case eEncodingT2:
8726 Rd = Rn = Bits32(opcode, 10, 8);
8727 setflags = !InITBlock();
8728 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8729 break;
8730 case eEncodingT3:
8731 Rd = Bits32(opcode, 11, 8);
8732 Rn = Bits32(opcode, 19, 16);
8733 setflags = BitIsSet(opcode, 20);
8734 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8735
8736 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8737 if (Rd == 15 && setflags)
8738 return EmulateCMPImm(eEncodingT2);
8739
8740 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8741 if (Rn == 13)
8742 return EmulateSUBSPImm(eEncodingT2);
8743
8744 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8745 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8746 return false;
8747 break;
8748 case eEncodingT4:
8749 Rd = Bits32(opcode, 11, 8);
8750 Rn = Bits32(opcode, 19, 16);
8751 setflags = BitIsSet(opcode, 20);
8752 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8753
8754 // if Rn == '1111' then SEE ADR;
8755 if (Rn == 15)
8756 return EmulateADR(eEncodingT2);
8757
8758 // if Rn == '1101' then SEE SUB (SP minus immediate);
8759 if (Rn == 13)
8760 return EmulateSUBSPImm(eEncodingT3);
8761
8762 if (BadReg(Rd))
8763 return false;
8764 break;
8765 default:
8766 return false;
8767 }
8768 // Read the register value from the operand register Rn.
8769 uint32_t reg_val = ReadCoreReg(Rn, &success);
8770 if (!success)
8771 return false;
8772
8773 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8774
8775 EmulateInstruction::Context context;
8776 context.type = EmulateInstruction::eContextImmediate;
8777 context.SetNoArgs ();
8778
8779 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8780 return false;
8781
8782 return true;
8783}
8784
8785// This instruction subtracts an immediate value from a register value, and writes the result
8786// to the destination register. It can optionally update the condition flags based on the result.
8787bool
8788EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
8789{
8790#if 0
8791 // ARM pseudo code...
8792 if ConditionPassed() then
8793 EncodingSpecificOperations();
8794 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8795 if d == 15 then
8796 ALUWritePC(result); // setflags is always FALSE here
8797 else
8798 R[d] = result;
8799 if setflags then
8800 APSR.N = result<31>;
8801 APSR.Z = IsZeroBit(result);
8802 APSR.C = carry;
8803 APSR.V = overflow;
8804#endif
8805
8806 bool success = false;
8807 const uint32_t opcode = OpcodeAsUnsigned (&success);
8808 if (!success)
8809 return false;
8810
8811 uint32_t Rd; // the destination register
8812 uint32_t Rn; // the first operand
8813 bool setflags;
8814 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8815 switch (encoding) {
8816 case eEncodingA1:
8817 Rd = Bits32(opcode, 15, 12);
8818 Rn = Bits32(opcode, 19, 16);
8819 setflags = BitIsSet(opcode, 20);
8820 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8821
8822 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
8823 if (Rn == 15 && !setflags)
8824 return EmulateADR(eEncodingA2);
8825
8826 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8827 if (Rn == 13)
8828 return EmulateSUBSPImm(eEncodingA1);
8829
8830 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8831 // TODO: Emulate SUBS PC, LR and related instructions.
8832 if (Rd == 15 && setflags)
8833 return false;
8834 break;
8835 default:
8836 return false;
8837 }
8838 // Read the register value from the operand register Rn.
8839 uint32_t reg_val = ReadCoreReg(Rn, &success);
8840 if (!success)
8841 return false;
8842
8843 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8844
8845 EmulateInstruction::Context context;
8846 context.type = EmulateInstruction::eContextImmediate;
8847 context.SetNoArgs ();
8848
8849 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8850 return false;
8851
8852 return true;
8853}
8854
Johnny Chen2115b412011-02-21 23:42:44 +00008855// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8856// immediate value. It updates the condition flags based on the result, and discards the result.
8857bool
8858EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
8859{
8860#if 0
8861 // ARM pseudo code...
8862 if ConditionPassed() then
8863 EncodingSpecificOperations();
8864 result = R[n] EOR imm32;
8865 APSR.N = result<31>;
8866 APSR.Z = IsZeroBit(result);
8867 APSR.C = carry;
8868 // APSR.V unchanged
8869#endif
8870
8871 bool success = false;
8872 const uint32_t opcode = OpcodeAsUnsigned (&success);
8873 if (!success)
8874 return false;
8875
8876 if (ConditionPassed())
8877 {
8878 uint32_t Rn;
8879 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8880 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8881 switch (encoding)
8882 {
8883 case eEncodingT1:
8884 Rn = Bits32(opcode, 19, 16);
8885 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8886 if (BadReg(Rn))
8887 return false;
8888 break;
8889 case eEncodingA1:
8890 Rn = Bits32(opcode, 19, 16);
8891 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8892 break;
8893 default:
8894 return false;
8895 }
8896
8897 // Read the first operand.
8898 uint32_t val1 = ReadCoreReg(Rn, &success);
8899 if (!success)
8900 return false;
8901
8902 uint32_t result = val1 ^ imm32;
8903
8904 EmulateInstruction::Context context;
8905 context.type = EmulateInstruction::eContextImmediate;
8906 context.SetNoArgs ();
8907
8908 if (!WriteFlags(context, result, carry))
8909 return false;
8910 }
8911 return true;
8912}
8913
8914// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8915// optionally-shifted register value. It updates the condition flags based on the result, and discards
8916// the result.
8917bool
8918EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
8919{
8920#if 0
8921 // ARM pseudo code...
8922 if ConditionPassed() then
8923 EncodingSpecificOperations();
8924 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8925 result = R[n] EOR shifted;
8926 APSR.N = result<31>;
8927 APSR.Z = IsZeroBit(result);
8928 APSR.C = carry;
8929 // APSR.V unchanged
8930#endif
8931
8932 bool success = false;
8933 const uint32_t opcode = OpcodeAsUnsigned (&success);
8934 if (!success)
8935 return false;
8936
8937 if (ConditionPassed())
8938 {
8939 uint32_t Rn, Rm;
8940 ARM_ShifterType shift_t;
8941 uint32_t shift_n; // the shift applied to the value read from Rm
8942 uint32_t carry;
8943 switch (encoding)
8944 {
8945 case eEncodingT1:
8946 Rn = Bits32(opcode, 19, 16);
8947 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008948 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008949 if (BadReg(Rn) || BadReg(Rm))
8950 return false;
8951 break;
8952 case eEncodingA1:
8953 Rn = Bits32(opcode, 19, 16);
8954 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008955 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008956 break;
8957 default:
8958 return false;
8959 }
8960
8961 // Read the first operand.
8962 uint32_t val1 = ReadCoreReg(Rn, &success);
8963 if (!success)
8964 return false;
8965
8966 // Read the second operand.
8967 uint32_t val2 = ReadCoreReg(Rm, &success);
8968 if (!success)
8969 return false;
8970
8971 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8972 uint32_t result = val1 ^ shifted;
8973
8974 EmulateInstruction::Context context;
8975 context.type = EmulateInstruction::eContextImmediate;
8976 context.SetNoArgs ();
8977
8978 if (!WriteFlags(context, result, carry))
8979 return false;
8980 }
8981 return true;
8982}
8983
Johnny Chende3cce32011-02-21 21:24:49 +00008984// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
8985// It updates the condition flags based on the result, and discards the result.
8986bool
8987EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
8988{
8989#if 0
8990 // ARM pseudo code...
8991 if ConditionPassed() then
8992 EncodingSpecificOperations();
8993 result = R[n] AND imm32;
8994 APSR.N = result<31>;
8995 APSR.Z = IsZeroBit(result);
8996 APSR.C = carry;
8997 // APSR.V unchanged
8998#endif
8999
9000 bool success = false;
9001 const uint32_t opcode = OpcodeAsUnsigned (&success);
9002 if (!success)
9003 return false;
9004
9005 if (ConditionPassed())
9006 {
9007 uint32_t Rn;
9008 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9009 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9010 switch (encoding)
9011 {
9012 case eEncodingT1:
9013 Rn = Bits32(opcode, 19, 16);
9014 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9015 if (BadReg(Rn))
9016 return false;
9017 break;
9018 case eEncodingA1:
9019 Rn = Bits32(opcode, 19, 16);
9020 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9021 break;
9022 default:
9023 return false;
9024 }
9025
9026 // Read the first operand.
9027 uint32_t val1 = ReadCoreReg(Rn, &success);
9028 if (!success)
9029 return false;
9030
9031 uint32_t result = val1 & imm32;
9032
9033 EmulateInstruction::Context context;
9034 context.type = EmulateInstruction::eContextImmediate;
9035 context.SetNoArgs ();
9036
9037 if (!WriteFlags(context, result, carry))
9038 return false;
9039 }
9040 return true;
9041}
9042
9043// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9044// It updates the condition flags based on the result, and discards the result.
9045bool
9046EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
9047{
9048#if 0
9049 // ARM pseudo code...
9050 if ConditionPassed() then
9051 EncodingSpecificOperations();
9052 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9053 result = R[n] AND shifted;
9054 APSR.N = result<31>;
9055 APSR.Z = IsZeroBit(result);
9056 APSR.C = carry;
9057 // APSR.V unchanged
9058#endif
9059
9060 bool success = false;
9061 const uint32_t opcode = OpcodeAsUnsigned (&success);
9062 if (!success)
9063 return false;
9064
9065 if (ConditionPassed())
9066 {
9067 uint32_t Rn, Rm;
9068 ARM_ShifterType shift_t;
9069 uint32_t shift_n; // the shift applied to the value read from Rm
9070 uint32_t carry;
9071 switch (encoding)
9072 {
9073 case eEncodingT1:
9074 Rn = Bits32(opcode, 2, 0);
9075 Rm = Bits32(opcode, 5, 3);
9076 shift_t = SRType_LSL;
9077 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009078 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009079 case eEncodingT2:
9080 Rn = Bits32(opcode, 19, 16);
9081 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009082 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009083 if (BadReg(Rn) || BadReg(Rm))
9084 return false;
9085 break;
9086 case eEncodingA1:
9087 Rn = Bits32(opcode, 19, 16);
9088 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009089 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009090 break;
9091 default:
9092 return false;
9093 }
9094
9095 // Read the first operand.
9096 uint32_t val1 = ReadCoreReg(Rn, &success);
9097 if (!success)
9098 return false;
9099
9100 // Read the second operand.
9101 uint32_t val2 = ReadCoreReg(Rm, &success);
9102 if (!success)
9103 return false;
9104
9105 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9106 uint32_t result = val1 & shifted;
9107
9108 EmulateInstruction::Context context;
9109 context.type = EmulateInstruction::eContextImmediate;
9110 context.SetNoArgs ();
9111
9112 if (!WriteFlags(context, result, carry))
9113 return false;
9114 }
9115 return true;
9116}
9117
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009118EmulateInstructionARM::ARMOpcode*
9119EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009120{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009121 static ARMOpcode
9122 g_arm_opcodes[] =
9123 {
9124 //----------------------------------------------------------------------
9125 // Prologue instructions
9126 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009127
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009128 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009129 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9130 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009131
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009132 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009133 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009134 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009135 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009136 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9137 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009138 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009139
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009140 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009141 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009142
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009143 // push one register
9144 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00009145 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009146
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009147 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009148 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9149 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009150
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009151 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009152 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009153 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009154
Johnny Chen9f687722011-02-18 00:02:28 +00009155 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9156 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009157 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009158 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9159
9160 //----------------------------------------------------------------------
9161 // Supervisor Call (previously Software Interrupt)
9162 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009163 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9164
9165 //----------------------------------------------------------------------
9166 // Branch instructions
9167 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009168 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009169 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9170 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9171 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9172 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009173 // for example, "bx lr"
9174 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009175 // bxj
9176 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009177
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009178 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009179 // Data-processing instructions
9180 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009181 // adc (immediate)
9182 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9183 // adc (register)
9184 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009185 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009186 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009187 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009188 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009189 // adr
9190 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9191 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009192 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009193 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009194 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009195 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009196 // bic (immediate)
9197 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9198 // bic (register)
9199 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009200 // eor (immediate)
9201 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9202 // eor (register)
9203 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009204 // orr (immediate)
9205 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9206 // orr (register)
9207 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009208 // rsb (immediate)
9209 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9210 // rsb (register)
9211 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009212 // rsc (immediate)
9213 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9214 // rsc (register)
9215 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009216 // sbc (immediate)
9217 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9218 // sbc (register)
9219 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009220 // sub (immediate, ARM)
9221 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009222 // sub (sp minus immediate)
9223 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009224 // teq (immediate)
9225 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9226 // teq (register)
9227 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009228 // tst (immediate)
9229 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9230 // tst (register)
9231 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9232
9233
Johnny Chen01d61572011-02-25 00:23:25 +00009234 // mov (register)
9235 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009236 // mvn (immediate)
9237 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9238 // mvn (register)
9239 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009240 // cmn (immediate)
9241 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9242 // cmn (register)
9243 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009244 // cmp (immediate)
9245 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9246 // cmp (register)
9247 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009248 // asr (immediate)
9249 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009250 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009251 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009252 // lsl (immediate)
9253 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9254 // lsl (register)
9255 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9256 // lsr (immediate)
9257 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9258 // lsr (register)
9259 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009260 // rrx is a special case encoding of ror (immediate)
9261 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9262 // ror (immediate)
9263 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9264 // ror (register)
9265 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009266 // mul
9267 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009268
9269 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009270 // Load instructions
9271 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009272 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009273 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009274 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009275 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009276 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009277 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009278 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009279 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009280 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009281 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009282 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009283 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009284 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009285 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009286 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9287 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009288
9289 //----------------------------------------------------------------------
9290 // Store instructions
9291 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009292 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009293 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009294 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009295 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009296 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009297
Caroline Tice6bf65162011-03-03 17:42:58 +00009298 //----------------------------------------------------------------------
9299 // Other instructions
9300 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009301 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009302 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009303 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009304 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9305 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009306
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009307 };
9308 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9309
9310 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9311 {
9312 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9313 return &g_arm_opcodes[i];
9314 }
9315 return NULL;
9316}
Greg Clayton64c84432011-01-21 22:02:52 +00009317
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009318
9319EmulateInstructionARM::ARMOpcode*
9320EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009321{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009322
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009323 static ARMOpcode
9324 g_thumb_opcodes[] =
9325 {
9326 //----------------------------------------------------------------------
9327 // Prologue instructions
9328 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009329
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009330 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009331 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9332 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9333 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009334
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009335 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009336 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009337 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009338 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009339 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009340 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009341
Johnny Chen864a8e82011-02-18 00:07:39 +00009342 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009343 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009344
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009345 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009346 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009347 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009348 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9349 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009350
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009351 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009352 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9353 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009354
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009355 //----------------------------------------------------------------------
9356 // Epilogue instructions
9357 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009358
Johnny Chen864a8e82011-02-18 00:07:39 +00009359 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009360 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9361 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9362 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009363 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9364 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009365
9366 //----------------------------------------------------------------------
9367 // Supervisor Call (previously Software Interrupt)
9368 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009369 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9370
9371 //----------------------------------------------------------------------
9372 // If Then makes up to four following instructions conditional.
9373 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009374 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9375
9376 //----------------------------------------------------------------------
9377 // Branch instructions
9378 //----------------------------------------------------------------------
9379 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9380 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009381 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009382 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009383 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009384 // J1 == J2 == 1
9385 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9386 // J1 == J2 == 1
9387 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9388 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009389 // for example, "bx lr"
9390 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009391 // bxj
9392 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009393 // compare and branch
9394 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009395 // table branch byte
9396 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9397 // table branch halfword
9398 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009399
9400 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009401 // Data-processing instructions
9402 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009403 // adc (immediate)
9404 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9405 // adc (register)
9406 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9407 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9408 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009409 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009410 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009411 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009412 // adr
9413 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9414 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9415 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009416 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009417 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009418 // and (register)
9419 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9420 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009421 // bic (immediate)
9422 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9423 // bic (register)
9424 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9425 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009426 // eor (immediate)
9427 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9428 // eor (register)
9429 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9430 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009431 // orr (immediate)
9432 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9433 // orr (register)
9434 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9435 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009436 // rsb (immediate)
9437 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9438 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9439 // rsb (register)
9440 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009441 // sbc (immediate)
9442 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9443 // sbc (register)
9444 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9445 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009446 // add (immediate, Thumb)
9447 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9448 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9449 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9450 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009451 // sub (immediate, Thumb)
9452 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9453 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9454 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9455 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009456 // sub (sp minus immediate)
9457 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9458 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009459 // teq (immediate)
9460 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9461 // teq (register)
9462 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009463 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009464 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009465 // tst (register)
9466 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9467 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9468
Johnny Chen7c5234d2011-02-18 23:41:11 +00009469
Johnny Chen338bf542011-02-10 19:29:03 +00009470 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009471 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009472 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009473 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009474 // mov{s}<c>.w <Rd>, <Rm>
9475 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009476 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009477 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9478 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009479 // mvn (immediate)
9480 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9481 // mvn (register)
9482 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9483 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009484 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009485 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009486 // cmn (register)
9487 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009488 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009489 // cmp (immediate)
9490 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009491 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009492 // cmp (register) (Rn and Rm both from r0-r7)
9493 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9494 // cmp (register) (Rn and Rm not both from r0-r7)
9495 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009496 // asr (immediate)
9497 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009498 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009499 // asr (register)
9500 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9501 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009502 // lsl (immediate)
9503 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9504 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9505 // lsl (register)
9506 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9507 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9508 // lsr (immediate)
9509 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9510 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9511 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009512 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009513 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009514 // rrx is a special case encoding of ror (immediate)
9515 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9516 // ror (immediate)
9517 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9518 // ror (register)
9519 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9520 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009521 // mul
9522 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9523 // mul
9524 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009525
Johnny Chen26863dc2011-02-09 23:43:29 +00009526 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009527 // Load instructions
9528 //----------------------------------------------------------------------
9529 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009530 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009531 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00009532 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9533 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009534 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009535 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9536 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009537 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9538 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9539 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009540 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009541 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9542 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009543 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9544 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9545 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009546 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009547 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9548 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009549 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9550 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009551 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009552 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9553 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009554 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9555 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009556 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009557 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9558 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009559
9560 //----------------------------------------------------------------------
9561 // Store instructions
9562 //----------------------------------------------------------------------
9563 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009564 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009565 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009566 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9567 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9568 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9569 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9570 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9571 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9572 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9573 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009574 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
9575
9576 //----------------------------------------------------------------------
9577 // Other instructions
9578 //----------------------------------------------------------------------
9579 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009580 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9581 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009582 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9583 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009584 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9585 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009586 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9587 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9588 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009589
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009590 };
9591
9592 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9593 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9594 {
9595 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9596 return &g_thumb_opcodes[i];
9597 }
9598 return NULL;
9599}
Greg Clayton64c84432011-01-21 22:02:52 +00009600
Greg Clayton31e2a382011-01-30 20:03:56 +00009601bool
Greg Clayton395fc332011-02-15 21:59:32 +00009602EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009603{
9604 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009605 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009606 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009607 {
Greg Clayton395fc332011-02-15 21:59:32 +00009608 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9609 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9610 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9611 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9612 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9613 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9614 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9615 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9616 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9617 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009618 }
9619 return m_arm_isa != 0;
9620}
9621
9622
Greg Clayton64c84432011-01-21 22:02:52 +00009623bool
9624EmulateInstructionARM::ReadInstruction ()
9625{
9626 bool success = false;
9627 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
9628 if (success)
9629 {
9630 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9631 if (success)
9632 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009633 Context read_inst_context;
9634 read_inst_context.type = eContextReadOpcode;
9635 read_inst_context.SetNoArgs ();
9636
Greg Clayton64c84432011-01-21 22:02:52 +00009637 if (m_inst_cpsr & MASK_CPSR_T)
9638 {
9639 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009640 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009641
9642 if (success)
9643 {
9644 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9645 {
9646 m_inst.opcode_type = eOpcode16;
9647 m_inst.opcode.inst16 = thumb_opcode;
9648 }
9649 else
9650 {
9651 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009652 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009653 }
9654 }
9655 }
9656 else
9657 {
9658 m_inst_mode = eModeARM;
9659 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009660 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009661 }
9662 }
9663 }
9664 if (!success)
9665 {
9666 m_inst_mode = eModeInvalid;
9667 m_inst_pc = LLDB_INVALID_ADDRESS;
9668 }
9669 return success;
9670}
9671
Johnny Chenee9b1f72011-02-09 01:00:31 +00009672uint32_t
9673EmulateInstructionARM::ArchVersion ()
9674{
9675 return m_arm_isa;
9676}
9677
Greg Clayton64c84432011-01-21 22:02:52 +00009678bool
9679EmulateInstructionARM::ConditionPassed ()
9680{
9681 if (m_inst_cpsr == 0)
9682 return false;
9683
9684 const uint32_t cond = CurrentCond ();
9685
9686 if (cond == UINT32_MAX)
9687 return false;
9688
9689 bool result = false;
9690 switch (UnsignedBits(cond, 3, 1))
9691 {
9692 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9693 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9694 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9695 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9696 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9697 case 5:
9698 {
9699 bool n = (m_inst_cpsr & MASK_CPSR_N);
9700 bool v = (m_inst_cpsr & MASK_CPSR_V);
9701 result = n == v;
9702 }
9703 break;
9704 case 6:
9705 {
9706 bool n = (m_inst_cpsr & MASK_CPSR_N);
9707 bool v = (m_inst_cpsr & MASK_CPSR_V);
9708 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
9709 }
9710 break;
9711 case 7:
9712 result = true;
9713 break;
9714 }
9715
9716 if (cond & 1)
9717 result = !result;
9718 return result;
9719}
9720
Johnny Chen9ee056b2011-02-08 00:06:35 +00009721uint32_t
9722EmulateInstructionARM::CurrentCond ()
9723{
9724 switch (m_inst_mode)
9725 {
9726 default:
9727 case eModeInvalid:
9728 break;
9729
9730 case eModeARM:
9731 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
9732
9733 case eModeThumb:
9734 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9735 // 'cond' field of the encoding.
9736 if (m_inst.opcode_type == eOpcode16 &&
9737 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
9738 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
9739 {
9740 return Bits32(m_inst.opcode.inst16, 11, 7);
9741 }
9742 else if (m_inst.opcode_type == eOpcode32 &&
9743 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
9744 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
9745 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
9746 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
9747 {
9748 return Bits32(m_inst.opcode.inst32, 25, 22);
9749 }
9750
9751 return m_it_session.GetCond();
9752 }
9753 return UINT32_MAX; // Return invalid value
9754}
9755
Johnny Chen9ee056b2011-02-08 00:06:35 +00009756bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009757EmulateInstructionARM::InITBlock()
9758{
9759 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9760}
9761
9762bool
9763EmulateInstructionARM::LastInITBlock()
9764{
9765 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9766}
9767
Caroline Ticeb27771d2011-03-03 22:37:46 +00009768bool
9769EmulateInstructionARM::BadMode (uint32_t mode)
9770{
9771
9772 switch (mode)
9773 {
9774 case 16: return false; // '10000'
9775 case 17: return false; // '10001'
9776 case 18: return false; // '10010'
9777 case 19: return false; // '10011'
9778 case 22: return false; // '10110'
9779 case 23: return false; // '10111'
9780 case 27: return false; // '11011'
9781 case 31: return false; // '11111'
9782 default: return true;
9783 }
9784 return true;
9785}
9786
9787bool
9788EmulateInstructionARM::CurrentModeIsPrivileged ()
9789{
9790 uint32_t mode = Bits32 (m_inst_cpsr, 4, 0);
9791
9792 if (BadMode (mode))
9793 return false;
9794
9795 if (mode == 16)
9796 return false;
9797
9798 return true;
9799}
9800
9801void
9802EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
9803{
9804 bool privileged = CurrentModeIsPrivileged();
9805
9806 uint32_t tmp_cpsr = 0;
9807
9808 tmp_cpsr = tmp_cpsr | (Bits32 (m_inst_cpsr, 23, 20) << 20);
9809
9810 if (BitIsSet (bytemask, 3))
9811 {
9812 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
9813 if (affect_execstate)
9814 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
9815 }
9816
9817 if (BitIsSet (bytemask, 2))
9818 {
9819 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
9820 }
9821
9822 if (BitIsSet (bytemask, 1))
9823 {
9824 if (affect_execstate)
9825 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
9826 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
9827 if (privileged)
9828 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
9829 }
9830
9831 if (BitIsSet (bytemask, 0))
9832 {
9833 if (privileged)
9834 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
9835 if (affect_execstate)
9836 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
9837 if (privileged)
9838 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
9839 }
9840
9841 m_inst_cpsr = tmp_cpsr;
9842}
9843
9844
Johnny Chen098ae2d2011-02-12 00:50:05 +00009845bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00009846EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
9847{
9848 addr_t target;
9849
Johnny Chenee9b1f72011-02-09 01:00:31 +00009850 // Check the current instruction set.
9851 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009852 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009853 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00009854 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009855
Johnny Chen9ee056b2011-02-08 00:06:35 +00009856 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009857 return false;
9858
9859 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009860}
9861
9862// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
9863bool
Johnny Chen668b4512011-02-15 21:08:58 +00009864EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009865{
9866 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00009867 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
9868 // we want to record it and issue a WriteRegister callback so the clients
9869 // can track the mode changes accordingly.
9870 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009871
9872 if (BitIsSet(addr, 0))
9873 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009874 if (CurrentInstrSet() != eModeThumb)
9875 {
9876 SelectInstrSet(eModeThumb);
9877 cpsr_changed = true;
9878 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009879 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00009880 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009881 }
9882 else if (BitIsClear(addr, 1))
9883 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009884 if (CurrentInstrSet() != eModeARM)
9885 {
9886 SelectInstrSet(eModeARM);
9887 cpsr_changed = true;
9888 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009889 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00009890 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009891 }
9892 else
9893 return false; // address<1:0> == '10' => UNPREDICTABLE
9894
Johnny Chen0f309db2011-02-09 19:11:32 +00009895 if (cpsr_changed)
9896 {
Johnny Chen558133b2011-02-09 23:59:17 +00009897 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00009898 return false;
9899 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009900 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009901 return false;
9902
9903 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009904}
Greg Clayton64c84432011-01-21 22:02:52 +00009905
Johnny Chenee9b1f72011-02-09 01:00:31 +00009906// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
9907bool
Johnny Chen668b4512011-02-15 21:08:58 +00009908EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00009909{
9910 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00009911 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00009912 else
9913 return BranchWritePC((const Context)context, addr);
9914}
9915
Johnny Chen26863dc2011-02-09 23:43:29 +00009916// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
9917bool
Johnny Chen668b4512011-02-15 21:08:58 +00009918EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00009919{
9920 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00009921 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00009922 else
9923 return BranchWritePC((const Context)context, addr);
9924}
9925
Johnny Chenee9b1f72011-02-09 01:00:31 +00009926EmulateInstructionARM::Mode
9927EmulateInstructionARM::CurrentInstrSet ()
9928{
9929 return m_inst_mode;
9930}
9931
9932// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00009933// ReadInstruction() is performed. This function has a side effect of updating
9934// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00009935bool
9936EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
9937{
Johnny Chen558133b2011-02-09 23:59:17 +00009938 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009939 switch (arm_or_thumb)
9940 {
9941 default:
9942 return false;
9943 eModeARM:
9944 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009945 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009946 break;
9947 eModeThumb:
9948 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009949 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009950 break;
9951 }
9952 return true;
9953}
9954
Johnny Chenef21b592011-02-10 01:52:38 +00009955// This function returns TRUE if the processor currently provides support for
9956// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
9957// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
9958bool
9959EmulateInstructionARM::UnalignedSupport()
9960{
9961 return (ArchVersion() >= ARMv7);
9962}
9963
Johnny Chenbf6ad172011-02-11 01:29:53 +00009964// The main addition and subtraction instructions can produce status information
9965// about both unsigned carry and signed overflow conditions. This status
9966// information can be used to synthesize multi-word additions and subtractions.
9967EmulateInstructionARM::AddWithCarryResult
9968EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
9969{
9970 uint32_t result;
9971 uint8_t carry_out;
9972 uint8_t overflow;
9973
9974 uint64_t unsigned_sum = x + y + carry_in;
9975 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
9976
9977 result = UnsignedBits(unsigned_sum, 31, 0);
9978 carry_out = (result == unsigned_sum ? 0 : 1);
9979 overflow = ((int32_t)result == signed_sum ? 0 : 1);
9980
9981 AddWithCarryResult res = { result, carry_out, overflow };
9982 return res;
9983}
9984
Johnny Chen157b9592011-02-18 21:13:05 +00009985uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00009986EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00009987{
Johnny Chene39f22d2011-02-19 01:36:13 +00009988 uint32_t reg_kind, reg_num;
9989 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00009990 {
Johnny Chene39f22d2011-02-19 01:36:13 +00009991 case SP_REG:
9992 reg_kind = eRegisterKindGeneric;
9993 reg_num = LLDB_REGNUM_GENERIC_SP;
9994 break;
9995 case LR_REG:
9996 reg_kind = eRegisterKindGeneric;
9997 reg_num = LLDB_REGNUM_GENERIC_RA;
9998 break;
9999 case PC_REG:
10000 reg_kind = eRegisterKindGeneric;
10001 reg_num = LLDB_REGNUM_GENERIC_PC;
10002 break;
10003 default:
10004 if (0 <= num && num < SP_REG)
10005 {
10006 reg_kind = eRegisterKindDWARF;
10007 reg_num = dwarf_r0 + num;
10008 }
Johnny Chen157b9592011-02-18 21:13:05 +000010009 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010010 {
10011 assert(0 && "Invalid register number");
10012 *success = false;
10013 return ~0u;
10014 }
10015 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010016 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010017
10018 // Read our register.
10019 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10020
10021 // When executing an ARM instruction , PC reads as the address of the current
10022 // instruction plus 8.
10023 // When executing a Thumb instruction , PC reads as the address of the current
10024 // instruction plus 4.
10025 if (num == 15)
10026 {
10027 if (CurrentInstrSet() == eModeARM)
10028 val += 8;
10029 else
10030 val += 4;
10031 }
Johnny Chen157b9592011-02-18 21:13:05 +000010032
10033 return val;
10034}
10035
Johnny Chenca67d1c2011-02-17 01:35:27 +000010036// Write the result to the ARM core register Rd, and optionally update the
10037// condition flags based on the result.
10038//
10039// This helper method tries to encapsulate the following pseudocode from the
10040// ARM Architecture Reference Manual:
10041//
10042// if d == 15 then // Can only occur for encoding A1
10043// ALUWritePC(result); // setflags is always FALSE here
10044// else
10045// R[d] = result;
10046// if setflags then
10047// APSR.N = result<31>;
10048// APSR.Z = IsZeroBit(result);
10049// APSR.C = carry;
10050// // APSR.V unchanged
10051//
10052// In the above case, the API client does not pass in the overflow arg, which
10053// defaults to ~0u.
10054bool
Johnny Chen10530c22011-02-17 22:37:12 +000010055EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10056 const uint32_t result,
10057 const uint32_t Rd,
10058 bool setflags,
10059 const uint32_t carry,
10060 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010061{
10062 if (Rd == 15)
10063 {
10064 if (!ALUWritePC (context, result))
10065 return false;
10066 }
10067 else
10068 {
Johnny Chena695f952011-02-23 21:24:25 +000010069 uint32_t reg_kind, reg_num;
10070 switch (Rd)
10071 {
10072 case SP_REG:
10073 reg_kind = eRegisterKindGeneric;
10074 reg_num = LLDB_REGNUM_GENERIC_SP;
10075 break;
10076 case LR_REG:
10077 reg_kind = eRegisterKindGeneric;
10078 reg_num = LLDB_REGNUM_GENERIC_RA;
10079 break;
10080 default:
10081 reg_kind = eRegisterKindDWARF;
10082 reg_num = dwarf_r0 + Rd;
10083 }
10084 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010085 return false;
10086 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010087 return WriteFlags (context, result, carry, overflow);
10088 }
10089 return true;
10090}
10091
10092// This helper method tries to encapsulate the following pseudocode from the
10093// ARM Architecture Reference Manual:
10094//
10095// APSR.N = result<31>;
10096// APSR.Z = IsZeroBit(result);
10097// APSR.C = carry;
10098// APSR.V = overflow
10099//
10100// Default arguments can be specified for carry and overflow parameters, which means
10101// not to update the respective flags.
10102bool
10103EmulateInstructionARM::WriteFlags (Context &context,
10104 const uint32_t result,
10105 const uint32_t carry,
10106 const uint32_t overflow)
10107{
10108 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010109 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10110 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010111 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010112 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010113 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010114 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +000010115 if (m_new_inst_cpsr != m_inst_cpsr)
10116 {
10117 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10118 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010119 }
10120 return true;
10121}
10122
Greg Clayton64c84432011-01-21 22:02:52 +000010123bool
10124EmulateInstructionARM::EvaluateInstruction ()
10125{
Johnny Chenc315f862011-02-05 00:46:10 +000010126 // Advance the ITSTATE bits to their values for the next instruction.
10127 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
10128 m_it_session.ITAdvance();
10129
Greg Clayton64c84432011-01-21 22:02:52 +000010130 return false;
10131}