blob: 514bafe4e087cd2063e03d2436c5aa4106698a74 [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);
Greg Clayton64c84432011-01-21 22:02:52 +0000283 for (i=0; i<15; ++i)
284 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000285 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000286 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000287 dwarf_reg.num = dwarf_r0 + i;
288 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000289 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000290 if (!success)
291 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000292 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000293 return false;
294 addr += addr_byte_size;
295 }
296 }
297
Johnny Chen7c1bf922011-02-08 23:49:37 +0000298 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000299 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000300 dwarf_reg.num = dwarf_pc;
301 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000302 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000303 if (!success)
304 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000305 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000306 return false;
307 }
308
309 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000310 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000311
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000312 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000313 return false;
314 }
315 return true;
316}
317
Johnny Chenef85e912011-01-31 23:07:40 +0000318// Pop Multiple Registers loads multiple registers from the stack, loading from
319// consecutive memory locations staring at the address in SP, and updates
320// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000321bool
Johnny Chen9f687722011-02-18 00:02:28 +0000322EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000323{
324#if 0
325 // ARM pseudo code...
326 if (ConditionPassed())
327 {
328 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
329 address = SP;
330 for i = 0 to 14
331 if registers<i> == ‘1’ then
332 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
333 if registers<15> == ‘1’ then
334 if UnalignedAllowed then
335 LoadWritePC(MemU[address,4]);
336 else
337 LoadWritePC(MemA[address,4]);
338 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
339 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
340 }
341#endif
342
343 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000344 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000345 if (!success)
346 return false;
347
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000348 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000349 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000350 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000351 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000352 if (!success)
353 return false;
354 uint32_t registers = 0;
355 uint32_t Rt; // the destination register
356 switch (encoding) {
357 case eEncodingT1:
358 registers = Bits32(opcode, 7, 0);
359 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000360 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000361 registers |= (1u << 15);
362 // if BitCount(registers) < 1 then UNPREDICTABLE;
363 if (BitCount(registers) < 1)
364 return false;
365 break;
366 case eEncodingT2:
367 // Ignore bit 13.
368 registers = Bits32(opcode, 15, 0) & ~0x2000;
369 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000370 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000371 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000372 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
373 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
374 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000375 break;
376 case eEncodingT3:
377 Rt = Bits32(opcode, 15, 12);
378 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000379 if (Rt == 13)
380 return false;
381 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000382 return false;
383 registers = (1u << Rt);
384 break;
385 case eEncodingA1:
386 registers = Bits32(opcode, 15, 0);
387 // Instead of return false, let's handle the following case as well,
388 // which amounts to popping one reg from the full descending stacks.
389 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
390
391 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000392 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000393 return false;
394 break;
395 case eEncodingA2:
396 Rt = Bits32(opcode, 15, 12);
397 // if t == 13 then UNPREDICTABLE;
398 if (Rt == dwarf_sp)
399 return false;
400 registers = (1u << Rt);
401 break;
402 default:
403 return false;
404 }
405 addr_t sp_offset = addr_byte_size * BitCount (registers);
406 addr_t addr = sp;
407 uint32_t i, data;
408
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000409 EmulateInstruction::Context context;
410 context.type = EmulateInstruction::eContextPopRegisterOffStack;
411 Register dwarf_reg;
412 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000413 for (i=0; i<15; ++i)
414 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000415 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000416 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000417 dwarf_reg.num = dwarf_r0 + i;
418 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000419 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000420 if (!success)
421 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000422 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000423 return false;
424 addr += addr_byte_size;
425 }
426 }
427
Johnny Chen7c1bf922011-02-08 23:49:37 +0000428 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000429 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000430 dwarf_reg.num = dwarf_pc;
431 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000432 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000433 if (!success)
434 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000435 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000436 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000437 return false;
438 addr += addr_byte_size;
439 }
440
441 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000442 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000443
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000444 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000445 return false;
446 }
447 return true;
448}
449
Johnny Chen5b442b72011-01-27 19:34:30 +0000450// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000451// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000452bool
Johnny Chen9f687722011-02-18 00:02:28 +0000453EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000454{
455#if 0
456 // ARM pseudo code...
457 if (ConditionPassed())
458 {
459 EncodingSpecificOperations();
460 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
461 if d == 15 then
462 ALUWritePC(result); // setflags is always FALSE here
463 else
464 R[d] = result;
465 if setflags then
466 APSR.N = result<31>;
467 APSR.Z = IsZeroBit(result);
468 APSR.C = carry;
469 APSR.V = overflow;
470 }
471#endif
472
473 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000474 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000475 if (!success)
476 return false;
477
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000478 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000479 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000480 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000481 if (!success)
482 return false;
483 uint32_t Rd; // the destination register
484 uint32_t imm32;
485 switch (encoding) {
486 case eEncodingT1:
487 Rd = 7;
488 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
489 break;
490 case eEncodingA1:
491 Rd = Bits32(opcode, 15, 12);
492 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
493 break;
494 default:
495 return false;
496 }
497 addr_t sp_offset = imm32;
498 addr_t addr = sp + sp_offset; // a pointer to the stack area
499
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000500 EmulateInstruction::Context context;
501 context.type = EmulateInstruction::eContextRegisterPlusOffset;
502 Register sp_reg;
503 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
504 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000505
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000506 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000507 return false;
508 }
509 return true;
510}
511
Johnny Chen2ccad832011-01-28 19:57:25 +0000512// Set r7 or ip to the current stack pointer.
513// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000514bool
Johnny Chen9f687722011-02-18 00:02:28 +0000515EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000516{
517#if 0
518 // ARM pseudo code...
519 if (ConditionPassed())
520 {
521 EncodingSpecificOperations();
522 result = R[m];
523 if d == 15 then
524 ALUWritePC(result); // setflags is always FALSE here
525 else
526 R[d] = result;
527 if setflags then
528 APSR.N = result<31>;
529 APSR.Z = IsZeroBit(result);
530 // APSR.C unchanged
531 // APSR.V unchanged
532 }
533#endif
534
535 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000536 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000537 //if (!success)
538 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000539
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000540 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000541 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000542 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000543 if (!success)
544 return false;
545 uint32_t Rd; // the destination register
546 switch (encoding) {
547 case eEncodingT1:
548 Rd = 7;
549 break;
550 case eEncodingA1:
551 Rd = 12;
552 break;
553 default:
554 return false;
555 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000556
557 EmulateInstruction::Context context;
558 context.type = EmulateInstruction::eContextRegisterPlusOffset;
559 Register sp_reg;
560 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
561 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000562
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000563 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000564 return false;
565 }
566 return true;
567}
568
Johnny Chen1c13b622011-01-29 00:11:15 +0000569// Move from high register (r8-r15) to low register (r0-r7).
570// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000571bool
Johnny Chen9f687722011-02-18 00:02:28 +0000572EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000573{
Johnny Chen9f687722011-02-18 00:02:28 +0000574 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000575}
576
577// Move from register to register.
578// MOV (register)
579bool
Johnny Chen9f687722011-02-18 00:02:28 +0000580EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000581{
Johnny Chen1c13b622011-01-29 00:11:15 +0000582#if 0
583 // ARM pseudo code...
584 if (ConditionPassed())
585 {
586 EncodingSpecificOperations();
587 result = R[m];
588 if d == 15 then
589 ALUWritePC(result); // setflags is always FALSE here
590 else
591 R[d] = result;
592 if setflags then
593 APSR.N = result<31>;
594 APSR.Z = IsZeroBit(result);
595 // APSR.C unchanged
596 // APSR.V unchanged
597 }
598#endif
599
600 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000601 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000602 if (!success)
603 return false;
604
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000605 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000606 {
607 uint32_t Rm; // the source register
608 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000609 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000610 switch (encoding) {
611 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000612 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000613 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000614 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000615 if (Rd == 15 && InITBlock() && !LastInITBlock())
616 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000617 break;
618 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000619 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000620 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000621 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000622 if (InITBlock())
623 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000624 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000625 case eEncodingT3:
626 Rd = Bits32(opcode, 11, 8);
627 Rm = Bits32(opcode, 3, 0);
628 setflags = BitIsSet(opcode, 20);
629 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
630 if (setflags && (BadReg(Rd) || BadReg(Rm)))
631 return false;
632 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
633 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
634 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000635 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000636 case eEncodingA1:
637 Rd = Bits32(opcode, 15, 12);
638 Rm = Bits32(opcode, 3, 0);
639 setflags = BitIsSet(opcode, 20);
640 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
641 // TODO: Emulate SUBS PC, LR and related instructions.
642 if (Rd == 15 && setflags)
643 return false;
644 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000645 default:
646 return false;
647 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000648 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000649 if (!success)
650 return false;
651
652 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000653 EmulateInstruction::Context context;
654 context.type = EmulateInstruction::eContextRegisterPlusOffset;
655 Register dwarf_reg;
656 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
657 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000658
Johnny Chen10530c22011-02-17 22:37:12 +0000659 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000660 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000661 }
662 return true;
663}
664
Johnny Chen357c30f2011-02-14 22:04:25 +0000665// Move (immediate) writes an immediate value to the destination register. It
666// can optionally update the condition flags based on the value.
667// MOV (immediate)
668bool
Johnny Chen9f687722011-02-18 00:02:28 +0000669EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000670{
671#if 0
672 // ARM pseudo code...
673 if (ConditionPassed())
674 {
675 EncodingSpecificOperations();
676 result = imm32;
677 if d == 15 then // Can only occur for ARM encoding
678 ALUWritePC(result); // setflags is always FALSE here
679 else
680 R[d] = result;
681 if setflags then
682 APSR.N = result<31>;
683 APSR.Z = IsZeroBit(result);
684 APSR.C = carry;
685 // APSR.V unchanged
686 }
687#endif
688 bool success = false;
689 const uint32_t opcode = OpcodeAsUnsigned (&success);
690 if (!success)
691 return false;
692
693 if (ConditionPassed())
694 {
695 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000696 uint32_t imm32; // the immediate value to be written to Rd
697 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
698 bool setflags;
699 switch (encoding) {
700 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000701 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000702 setflags = !InITBlock();
703 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000704 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000705 break;
706 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000707 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000708 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000709 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000710 if (BadReg(Rd))
711 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000712 break;
713 default:
714 return false;
715 }
716 uint32_t result = imm32;
717
718 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000719 EmulateInstruction::Context context;
720 context.type = EmulateInstruction::eContextImmediate;
721 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000722
Johnny Chen10530c22011-02-17 22:37:12 +0000723 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000724 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000725 }
726 return true;
727}
728
Caroline Tice5c1e2ed2011-03-02 22:43:54 +0000729// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination
730// register. These 32 bits do not depend on whether the source register values are considered to be signed values or
731// unsigned values.
732//
733// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is
734// limited to only a few forms of the instruction.
735bool
736EmulateInstructionARM::EmulateMUL (ARMEncoding encoding)
737{
738#if 0
739 if ConditionPassed() then
740 EncodingSpecificOperations();
741 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
742 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
743 result = operand1 * operand2;
744 R[d] = result<31:0>;
745 if setflags then
746 APSR.N = result<31>;
747 APSR.Z = IsZeroBit(result);
748 if ArchVersion() == 4 then
749 APSR.C = bit UNKNOWN;
750 // else APSR.C unchanged
751 // APSR.V always unchanged
752#endif
753
754 bool success = false;
755 const uint32_t opcode = OpcodeAsUnsigned (&success);
756 if (!success)
757 return false;
758
759 if (ConditionPassed())
760 {
761 uint32_t d;
762 uint32_t n;
763 uint32_t m;
764 bool setflags;
765
766 // EncodingSpecificOperations();
767 switch (encoding)
768 {
769 case eEncodingT1:
770 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
771 d = Bits32 (opcode, 2, 0);
772 n = Bits32 (opcode, 5, 3);
773 m = Bits32 (opcode, 2, 0);
774 setflags = !InITBlock();
775
776 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
777 if ((ArchVersion() < ARMv6) && (d == n))
778 return false;
779
780 break;
781
782 case eEncodingT2:
783 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
784 d = Bits32 (opcode, 11, 8);
785 n = Bits32 (opcode, 19, 16);
786 m = Bits32 (opcode, 3, 0);
787 setflags = false;
788
789 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
790 if (BadReg (d) || BadReg (n) || BadReg (m))
791 return false;
792
793 break;
794
795 case eEncodingA1:
796 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ’1’);
797 d = Bits32 (opcode, 19, 16);
798 n = Bits32 (opcode, 3, 0);
799 m = Bits32 (opcode, 11, 8);
800 setflags = BitIsSet (opcode, 20);
801
802 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
803 if ((d == 15) || (n == 15) || (m == 15))
804 return false;
805
806 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
807 if ((ArchVersion() < ARMv6) && (d == n))
808 return false;
809
810 break;
811
812 default:
813 return false;
814 }
815
816 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
817 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
818 if (!success)
819 return false;
820
821 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
822 uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
823 if (!success)
824 return false;
825
826 // result = operand1 * operand2;
827 uint64_t result = operand1 * operand2;
828
829 // R[d] = result<31:0>;
830 Register op1_reg;
831 Register op2_reg;
832 op1_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
833 op2_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
834
835 EmulateInstruction::Context context;
836 context.type = eContextMultiplication;
837 context.SetRegisterRegisterOperands (op1_reg, op2_reg);
838
839 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
840 return false;
841
842 // if setflags then
843 if (setflags)
844 {
845 // APSR.N = result<31>;
846 // APSR.Z = IsZeroBit(result);
847 m_new_inst_cpsr = m_inst_cpsr;
848 SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
849 SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
850 if (m_new_inst_cpsr != m_inst_cpsr)
851 {
852 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
853 return false;
854 }
855
856 // if ArchVersion() == 4 then
857 // APSR.C = bit UNKNOWN;
858 }
859 }
860 return true;
861}
862
Johnny Chend642a6a2011-02-22 01:01:03 +0000863// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
864// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000865bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000866EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000867{
868#if 0
869 // ARM pseudo code...
870 if (ConditionPassed())
871 {
872 EncodingSpecificOperations();
873 result = NOT(imm32);
874 if d == 15 then // Can only occur for ARM encoding
875 ALUWritePC(result); // setflags is always FALSE here
876 else
877 R[d] = result;
878 if setflags then
879 APSR.N = result<31>;
880 APSR.Z = IsZeroBit(result);
881 APSR.C = carry;
882 // APSR.V unchanged
883 }
884#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000885 bool success = false;
886 const uint32_t opcode = OpcodeAsUnsigned (&success);
887 if (!success)
888 return false;
889
890 if (ConditionPassed())
891 {
892 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000893 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
894 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000895 bool setflags;
896 switch (encoding) {
897 case eEncodingT1:
898 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000899 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000900 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000901 break;
902 case eEncodingA1:
903 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000904 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000905 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
906 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
907 // TODO: Emulate SUBS PC, LR and related instructions.
908 if (Rd == 15 && setflags)
909 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000910 break;
911 default:
912 return false;
913 }
914 uint32_t result = ~imm32;
915
916 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000917 EmulateInstruction::Context context;
918 context.type = EmulateInstruction::eContextImmediate;
919 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000920
Johnny Chen10530c22011-02-17 22:37:12 +0000921 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000922 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000923 }
924 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000925}
926
Johnny Chend642a6a2011-02-22 01:01:03 +0000927// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
928// It can optionally update the condition flags based on the result.
929bool
930EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
931{
932#if 0
933 // ARM pseudo code...
934 if (ConditionPassed())
935 {
936 EncodingSpecificOperations();
937 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
938 result = NOT(shifted);
939 if d == 15 then // Can only occur for ARM encoding
940 ALUWritePC(result); // setflags is always FALSE here
941 else
942 R[d] = result;
943 if setflags then
944 APSR.N = result<31>;
945 APSR.Z = IsZeroBit(result);
946 APSR.C = carry;
947 // APSR.V unchanged
948 }
949#endif
950
951 bool success = false;
952 const uint32_t opcode = OpcodeAsUnsigned (&success);
953 if (!success)
954 return false;
955
956 if (ConditionPassed())
957 {
958 uint32_t Rm; // the source register
959 uint32_t Rd; // the destination register
960 ARM_ShifterType shift_t;
961 uint32_t shift_n; // the shift applied to the value read from Rm
962 bool setflags;
963 uint32_t carry; // the carry bit after the shift operation
964 switch (encoding) {
965 case eEncodingT1:
966 Rd = Bits32(opcode, 2, 0);
967 Rm = Bits32(opcode, 5, 3);
968 setflags = !InITBlock();
969 shift_t = SRType_LSL;
970 shift_n = 0;
971 if (InITBlock())
972 return false;
973 break;
974 case eEncodingT2:
975 Rd = Bits32(opcode, 11, 8);
976 Rm = Bits32(opcode, 3, 0);
977 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000978 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000979 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000980 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000981 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000982 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000983 case eEncodingA1:
984 Rd = Bits32(opcode, 15, 12);
985 Rm = Bits32(opcode, 3, 0);
986 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000987 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000988 break;
989 default:
990 return false;
991 }
992 uint32_t value = ReadCoreReg(Rm, &success);
993 if (!success)
994 return false;
995
996 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
997 uint32_t result = ~shifted;
998
999 // The context specifies that an immediate is to be moved into Rd.
1000 EmulateInstruction::Context context;
1001 context.type = EmulateInstruction::eContextImmediate;
1002 context.SetNoArgs ();
1003
1004 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1005 return false;
1006 }
1007 return true;
1008}
1009
Johnny Chen788e0552011-01-27 22:52:23 +00001010// PC relative immediate load into register, possibly followed by ADD (SP plus register).
1011// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001012bool
Johnny Chenc9de9102011-02-11 19:12:30 +00001013EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +00001014{
1015#if 0
1016 // ARM pseudo code...
1017 if (ConditionPassed())
1018 {
1019 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1020 base = Align(PC,4);
1021 address = if add then (base + imm32) else (base - imm32);
1022 data = MemU[address,4];
1023 if t == 15 then
1024 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
1025 elsif UnalignedSupport() || address<1:0> = ‘00’ then
1026 R[t] = data;
1027 else // Can only apply before ARMv7
1028 if CurrentInstrSet() == InstrSet_ARM then
1029 R[t] = ROR(data, 8*UInt(address<1:0>));
1030 else
1031 R[t] = bits(32) UNKNOWN;
1032 }
1033#endif
1034
1035 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001036 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +00001037 if (!success)
1038 return false;
1039
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001040 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +00001041 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001042 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001043 if (!success)
1044 return false;
Johnny Chen809742e2011-01-28 00:32:27 +00001045
1046 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001047 EmulateInstruction::Context context;
1048 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1049 Register pc_reg;
1050 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
1051 context.SetRegisterPlusOffset (pc_reg, 0);
1052
Johnny Chenc9de9102011-02-11 19:12:30 +00001053 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +00001054 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +00001055 bool add; // +imm32 or -imm32?
1056 addr_t base; // the base address
1057 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +00001058 uint32_t data; // the literal data value from the PC relative load
1059 switch (encoding) {
1060 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +00001061 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +00001062 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +00001063 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +00001064 break;
1065 case eEncodingT2:
1066 Rt = Bits32(opcode, 15, 12);
1067 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1068 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001069 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +00001070 return false;
Johnny Chen788e0552011-01-27 22:52:23 +00001071 break;
1072 default:
1073 return false;
1074 }
Johnny Chenc9de9102011-02-11 19:12:30 +00001075
Johnny Chene39f22d2011-02-19 01:36:13 +00001076 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +00001077 if (add)
1078 address = base + imm32;
1079 else
1080 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +00001081
1082 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001083 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +00001084 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +00001085 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +00001086
1087 if (Rt == 15)
1088 {
1089 if (Bits32(address, 1, 0) == 0)
1090 {
1091 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00001092 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +00001093 return false;
1094 }
1095 else
1096 return false;
1097 }
1098 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
1099 {
1100 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
1101 return false;
1102 }
1103 else // We don't handle ARM for now.
1104 return false;
1105
1106 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +00001107 return false;
1108 }
1109 return true;
1110}
1111
Johnny Chen5b442b72011-01-27 19:34:30 +00001112// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +00001113// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001114bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001115EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001116{
1117#if 0
1118 // ARM pseudo code...
1119 if (ConditionPassed())
1120 {
1121 EncodingSpecificOperations();
1122 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
1123 if d == 15 then // Can only occur for ARM encoding
1124 ALUWritePC(result); // setflags is always FALSE here
1125 else
1126 R[d] = result;
1127 if setflags then
1128 APSR.N = result<31>;
1129 APSR.Z = IsZeroBit(result);
1130 APSR.C = carry;
1131 APSR.V = overflow;
1132 }
1133#endif
1134
1135 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001136 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001137 if (!success)
1138 return false;
1139
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001140 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +00001141 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001142 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001143 if (!success)
1144 return false;
1145 uint32_t imm32; // the immediate operand
1146 switch (encoding) {
1147 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001148 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001149 break;
1150 default:
1151 return false;
1152 }
1153 addr_t sp_offset = imm32;
1154 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1155
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001156 EmulateInstruction::Context context;
1157 context.type = EmulateInstruction::eContextAdjustStackPointer;
1158 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001159
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001160 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001161 return false;
1162 }
1163 return true;
1164}
1165
1166// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001167// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001168bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001169EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001170{
1171#if 0
1172 // ARM pseudo code...
1173 if (ConditionPassed())
1174 {
1175 EncodingSpecificOperations();
1176 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1177 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1178 if d == 15 then
1179 ALUWritePC(result); // setflags is always FALSE here
1180 else
1181 R[d] = result;
1182 if setflags then
1183 APSR.N = result<31>;
1184 APSR.Z = IsZeroBit(result);
1185 APSR.C = carry;
1186 APSR.V = overflow;
1187 }
1188#endif
1189
1190 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001191 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001192 if (!success)
1193 return false;
1194
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001195 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001196 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001197 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001198 if (!success)
1199 return false;
1200 uint32_t Rm; // the second operand
1201 switch (encoding) {
1202 case eEncodingT2:
1203 Rm = Bits32(opcode, 6, 3);
1204 break;
1205 default:
1206 return false;
1207 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001208 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001209 if (!success)
1210 return false;
1211
1212 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1213
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001214 EmulateInstruction::Context context;
1215 context.type = EmulateInstruction::eContextAdjustStackPointer;
1216 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001217
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001218 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001219 return false;
1220 }
1221 return true;
1222}
1223
Johnny Chen9b8d7832011-02-02 01:13:56 +00001224// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1225// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1226// from Thumb to ARM.
1227// BLX (immediate)
1228bool
1229EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1230{
1231#if 0
1232 // ARM pseudo code...
1233 if (ConditionPassed())
1234 {
1235 EncodingSpecificOperations();
1236 if CurrentInstrSet() == InstrSet_ARM then
1237 LR = PC - 4;
1238 else
1239 LR = PC<31:1> : '1';
1240 if targetInstrSet == InstrSet_ARM then
1241 targetAddress = Align(PC,4) + imm32;
1242 else
1243 targetAddress = PC + imm32;
1244 SelectInstrSet(targetInstrSet);
1245 BranchWritePC(targetAddress);
1246 }
1247#endif
1248
1249 bool success = false;
1250 const uint32_t opcode = OpcodeAsUnsigned (&success);
1251 if (!success)
1252 return false;
1253
1254 if (ConditionPassed())
1255 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001256 EmulateInstruction::Context context;
1257 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001258 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001259 if (!success)
1260 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001261 addr_t lr; // next instruction address
1262 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001263 int32_t imm32; // PC-relative offset
1264 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001265 case eEncodingT1:
1266 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001267 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001268 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001269 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001270 uint32_t J1 = Bit32(opcode, 13);
1271 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001272 uint32_t imm11 = Bits32(opcode, 10, 0);
1273 uint32_t I1 = !(J1 ^ S);
1274 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001275 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001276 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001277 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001278 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001279 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001280 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001281 break;
1282 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001283 case eEncodingT2:
1284 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001285 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001286 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001287 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001288 uint32_t J1 = Bit32(opcode, 13);
1289 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001290 uint32_t imm10L = Bits32(opcode, 10, 1);
1291 uint32_t I1 = !(J1 ^ S);
1292 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001293 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001294 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001295 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001296 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001297 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001298 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001299 break;
1300 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001301 case eEncodingA1:
1302 lr = pc + 4; // return address
1303 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001304 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001305 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001306 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001307 case eEncodingA2:
1308 lr = pc + 4; // return address
1309 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001310 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001311 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001312 break;
1313 default:
1314 return false;
1315 }
1316 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1317 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001318 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001319 return false;
1320 }
1321 return true;
1322}
1323
1324// Branch with Link and Exchange (register) calls a subroutine at an address and
1325// instruction set specified by a register.
1326// BLX (register)
1327bool
1328EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1329{
1330#if 0
1331 // ARM pseudo code...
1332 if (ConditionPassed())
1333 {
1334 EncodingSpecificOperations();
1335 target = R[m];
1336 if CurrentInstrSet() == InstrSet_ARM then
1337 next_instr_addr = PC - 4;
1338 LR = next_instr_addr;
1339 else
1340 next_instr_addr = PC - 2;
1341 LR = next_instr_addr<31:1> : ‘1’;
1342 BXWritePC(target);
1343 }
1344#endif
1345
1346 bool success = false;
1347 const uint32_t opcode = OpcodeAsUnsigned (&success);
1348 if (!success)
1349 return false;
1350
1351 if (ConditionPassed())
1352 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001353 EmulateInstruction::Context context;
1354 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001355 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001356 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001357 if (!success)
1358 return false;
1359 uint32_t Rm; // the register with the target address
1360 switch (encoding) {
1361 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001362 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001363 Rm = Bits32(opcode, 6, 3);
1364 // if m == 15 then UNPREDICTABLE;
1365 if (Rm == 15)
1366 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001367 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001368 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001369 break;
1370 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001371 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001372 Rm = Bits32(opcode, 3, 0);
1373 // if m == 15 then UNPREDICTABLE;
1374 if (Rm == 15)
1375 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001376 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001377 default:
1378 return false;
1379 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001380 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001381 if (!success)
1382 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001383 Register dwarf_reg;
1384 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1385 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001386 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1387 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001388 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001389 return false;
1390 }
1391 return true;
1392}
1393
Johnny Chenab3b3512011-02-12 00:10:51 +00001394// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001395bool
1396EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1397{
1398#if 0
1399 // ARM pseudo code...
1400 if (ConditionPassed())
1401 {
1402 EncodingSpecificOperations();
1403 BXWritePC(R[m]);
1404 }
1405#endif
1406
1407 bool success = false;
1408 const uint32_t opcode = OpcodeAsUnsigned (&success);
1409 if (!success)
1410 return false;
1411
1412 if (ConditionPassed())
1413 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001414 EmulateInstruction::Context context;
1415 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001416 uint32_t Rm; // the register with the target address
1417 switch (encoding) {
1418 case eEncodingT1:
1419 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001420 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001421 return false;
1422 break;
1423 case eEncodingA1:
1424 Rm = Bits32(opcode, 3, 0);
1425 break;
1426 default:
1427 return false;
1428 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001429 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001430 if (!success)
1431 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001432
1433 Register dwarf_reg;
1434 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001435 context.SetRegister (dwarf_reg);
1436 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001437 return false;
1438 }
1439 return true;
1440}
1441
Johnny Chen59e6ab72011-02-24 21:01:20 +00001442// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1443// address and instruction set specified by a register as though it were a BX instruction.
1444//
1445// TODO: Emulate Jazelle architecture?
1446// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1447bool
1448EmulateInstructionARM::EmulateBXJRm (ARMEncoding encoding)
1449{
1450#if 0
1451 // ARM pseudo code...
1452 if (ConditionPassed())
1453 {
1454 EncodingSpecificOperations();
1455 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1456 BXWritePC(R[m]);
1457 else
1458 if JazelleAcceptsExecution() then
1459 SwitchToJazelleExecution();
1460 else
1461 SUBARCHITECTURE_DEFINED handler call;
1462 }
1463#endif
1464
1465 bool success = false;
1466 const uint32_t opcode = OpcodeAsUnsigned (&success);
1467 if (!success)
1468 return false;
1469
1470 if (ConditionPassed())
1471 {
1472 EmulateInstruction::Context context;
1473 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1474 uint32_t Rm; // the register with the target address
1475 switch (encoding) {
1476 case eEncodingT1:
1477 Rm = Bits32(opcode, 19, 16);
1478 if (BadReg(Rm))
1479 return false;
1480 if (InITBlock() && !LastInITBlock())
1481 return false;
1482 break;
1483 case eEncodingA1:
1484 Rm = Bits32(opcode, 3, 0);
1485 if (Rm == 15)
1486 return false;
1487 break;
1488 default:
1489 return false;
1490 }
1491 addr_t target = ReadCoreReg (Rm, &success);
1492 if (!success)
1493 return false;
1494
1495 Register dwarf_reg;
1496 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1497 context.SetRegister (dwarf_reg);
1498 if (!BXWritePC(context, target))
1499 return false;
1500 }
1501 return true;
1502}
1503
Johnny Chen0d0148e2011-01-28 02:26:08 +00001504// Set r7 to point to some ip offset.
1505// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001506bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001507EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001508{
1509#if 0
1510 // ARM pseudo code...
1511 if (ConditionPassed())
1512 {
1513 EncodingSpecificOperations();
1514 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1515 if d == 15 then // Can only occur for ARM encoding
1516 ALUWritePC(result); // setflags is always FALSE here
1517 else
1518 R[d] = result;
1519 if setflags then
1520 APSR.N = result<31>;
1521 APSR.Z = IsZeroBit(result);
1522 APSR.C = carry;
1523 APSR.V = overflow;
1524 }
1525#endif
1526
1527 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001528 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001529 if (!success)
1530 return false;
1531
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001532 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001533 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001534 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001535 if (!success)
1536 return false;
1537 uint32_t imm32;
1538 switch (encoding) {
1539 case eEncodingA1:
1540 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1541 break;
1542 default:
1543 return false;
1544 }
1545 addr_t ip_offset = imm32;
1546 addr_t addr = ip - ip_offset; // the adjusted ip value
1547
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001548 EmulateInstruction::Context context;
1549 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1550 Register dwarf_reg;
1551 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1552 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001553
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001554 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001555 return false;
1556 }
1557 return true;
1558}
1559
1560// Set ip to point to some stack offset.
1561// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001562bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001563EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001564{
1565#if 0
1566 // ARM pseudo code...
1567 if (ConditionPassed())
1568 {
1569 EncodingSpecificOperations();
1570 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1571 if d == 15 then // Can only occur for ARM encoding
1572 ALUWritePC(result); // setflags is always FALSE here
1573 else
1574 R[d] = result;
1575 if setflags then
1576 APSR.N = result<31>;
1577 APSR.Z = IsZeroBit(result);
1578 APSR.C = carry;
1579 APSR.V = overflow;
1580 }
1581#endif
1582
1583 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001584 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001585 if (!success)
1586 return false;
1587
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001588 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001589 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001590 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001591 if (!success)
1592 return false;
1593 uint32_t imm32;
1594 switch (encoding) {
1595 case eEncodingA1:
1596 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1597 break;
1598 default:
1599 return false;
1600 }
1601 addr_t sp_offset = imm32;
1602 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1603
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001604 EmulateInstruction::Context context;
1605 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1606 Register dwarf_reg;
1607 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1608 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001609
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001610 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001611 return false;
1612 }
1613 return true;
1614}
1615
Johnny Chenc9e747f2011-02-23 01:55:07 +00001616// This instruction subtracts an immediate value from the SP value, and writes
1617// the result to the destination register.
1618//
1619// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001620bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001621EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001622{
1623#if 0
1624 // ARM pseudo code...
1625 if (ConditionPassed())
1626 {
1627 EncodingSpecificOperations();
1628 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001629 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001630 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001631 else
1632 R[d] = result;
1633 if setflags then
1634 APSR.N = result<31>;
1635 APSR.Z = IsZeroBit(result);
1636 APSR.C = carry;
1637 APSR.V = overflow;
1638 }
1639#endif
1640
1641 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001642 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001643 if (!success)
1644 return false;
1645
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001646 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001647 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001648 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001649 if (!success)
1650 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001651
1652 uint32_t Rd;
1653 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001654 uint32_t imm32;
1655 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001656 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001657 Rd = 13;
1658 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001659 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001660 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001661 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001662 Rd = Bits32(opcode, 11, 8);
1663 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001664 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001665 if (Rd == 15 && setflags)
1666 return EmulateCMPImm(eEncodingT2);
1667 if (Rd == 15 && !setflags)
1668 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001669 break;
1670 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001671 Rd = Bits32(opcode, 11, 8);
1672 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001673 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001674 if (Rd == 15)
1675 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001676 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001677 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001678 Rd = Bits32(opcode, 15, 12);
1679 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001680 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001681 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1682 // TODO: Emulate SUBS PC, LR and related instructions.
1683 if (Rd == 15 && setflags)
1684 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001685 break;
1686 default:
1687 return false;
1688 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001689 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1690
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001691 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001692 if (Rd == 13)
1693 {
1694 context.type = EmulateInstruction::eContextAdjustStackPointer;
1695 context.SetImmediateSigned (-imm32); // the stack pointer offset
1696 }
1697 else
1698 {
1699 context.type = EmulateInstruction::eContextImmediate;
1700 context.SetNoArgs ();
1701 }
1702
1703 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001704 return false;
1705 }
1706 return true;
1707}
1708
Johnny Chen08c25e82011-01-31 18:02:28 +00001709// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001710bool
1711EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001712{
1713#if 0
1714 // ARM pseudo code...
1715 if (ConditionPassed())
1716 {
1717 EncodingSpecificOperations();
1718 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1719 address = if index then offset_addr else R[n];
1720 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1721 if wback then R[n] = offset_addr;
1722 }
1723#endif
1724
1725 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001726 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001727 if (!success)
1728 return false;
1729
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001730 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001731 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001732 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001733 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001734 if (!success)
1735 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001736 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001737 uint32_t imm12;
1738 switch (encoding) {
1739 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001740 Rt = Bits32(opcode, 15, 12);
1741 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001742 break;
1743 default:
1744 return false;
1745 }
1746 addr_t sp_offset = imm12;
1747 addr_t addr = sp - sp_offset;
1748
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001749 EmulateInstruction::Context context;
1750 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1751 Register dwarf_reg;
1752 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001753 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001754 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001755 dwarf_reg.num = dwarf_r0 + Rt;
1756 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001757 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001758 if (!success)
1759 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001760 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001761 return false;
1762 }
1763 else
1764 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001765 dwarf_reg.num = dwarf_pc;
1766 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001767 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001768 if (!success)
1769 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001770 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001771 return false;
1772 }
1773
1774 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001775 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001776
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001777 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001778 return false;
1779 }
1780 return true;
1781}
1782
Johnny Chen08c25e82011-01-31 18:02:28 +00001783// Vector Push stores multiple extension registers to the stack.
1784// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001785bool
1786EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001787{
1788#if 0
1789 // ARM pseudo code...
1790 if (ConditionPassed())
1791 {
1792 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1793 address = SP - imm32;
1794 SP = SP - imm32;
1795 if single_regs then
1796 for r = 0 to regs-1
1797 MemA[address,4] = S[d+r]; address = address+4;
1798 else
1799 for r = 0 to regs-1
1800 // Store as two word-aligned words in the correct order for current endianness.
1801 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1802 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1803 address = address+8;
1804 }
1805#endif
1806
1807 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001808 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001809 if (!success)
1810 return false;
1811
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001812 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001813 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001814 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001815 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001816 if (!success)
1817 return false;
1818 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001819 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001820 uint32_t imm32; // stack offset
1821 uint32_t regs; // number of registers
1822 switch (encoding) {
1823 case eEncodingT1:
1824 case eEncodingA1:
1825 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001826 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001827 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1828 // If UInt(imm8) is odd, see "FSTMX".
1829 regs = Bits32(opcode, 7, 0) / 2;
1830 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1831 if (regs == 0 || regs > 16 || (d + regs) > 32)
1832 return false;
1833 break;
1834 case eEncodingT2:
1835 case eEncodingA2:
1836 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001837 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001838 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1839 regs = Bits32(opcode, 7, 0);
1840 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1841 if (regs == 0 || regs > 16 || (d + regs) > 32)
1842 return false;
1843 break;
1844 default:
1845 return false;
1846 }
1847 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1848 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1849 addr_t sp_offset = imm32;
1850 addr_t addr = sp - sp_offset;
1851 uint32_t i;
1852
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001853 EmulateInstruction::Context context;
1854 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1855 Register dwarf_reg;
1856 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001857 for (i=d; i<regs; ++i)
1858 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001859 dwarf_reg.num = start_reg + i;
1860 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001861 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001862 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001863 if (!success)
1864 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001865 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001866 return false;
1867 addr += reg_byte_size;
1868 }
1869
1870 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001871 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001872
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001873 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001874 return false;
1875 }
1876 return true;
1877}
1878
Johnny Chen587a0a42011-02-01 18:35:28 +00001879// Vector Pop loads multiple extension registers from the stack.
1880// It also updates SP to point just above the loaded data.
1881bool
1882EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1883{
1884#if 0
1885 // ARM pseudo code...
1886 if (ConditionPassed())
1887 {
1888 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1889 address = SP;
1890 SP = SP + imm32;
1891 if single_regs then
1892 for r = 0 to regs-1
1893 S[d+r] = MemA[address,4]; address = address+4;
1894 else
1895 for r = 0 to regs-1
1896 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1897 // Combine the word-aligned words in the correct order for current endianness.
1898 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1899 }
1900#endif
1901
1902 bool success = false;
1903 const uint32_t opcode = OpcodeAsUnsigned (&success);
1904 if (!success)
1905 return false;
1906
1907 if (ConditionPassed())
1908 {
1909 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001910 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001911 if (!success)
1912 return false;
1913 bool single_regs;
1914 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1915 uint32_t imm32; // stack offset
1916 uint32_t regs; // number of registers
1917 switch (encoding) {
1918 case eEncodingT1:
1919 case eEncodingA1:
1920 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001921 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001922 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1923 // If UInt(imm8) is odd, see "FLDMX".
1924 regs = Bits32(opcode, 7, 0) / 2;
1925 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1926 if (regs == 0 || regs > 16 || (d + regs) > 32)
1927 return false;
1928 break;
1929 case eEncodingT2:
1930 case eEncodingA2:
1931 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001932 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001933 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1934 regs = Bits32(opcode, 7, 0);
1935 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1936 if (regs == 0 || regs > 16 || (d + regs) > 32)
1937 return false;
1938 break;
1939 default:
1940 return false;
1941 }
1942 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1943 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1944 addr_t sp_offset = imm32;
1945 addr_t addr = sp;
1946 uint32_t i;
1947 uint64_t data; // uint64_t to accomodate 64-bit registers.
1948
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001949 EmulateInstruction::Context context;
1950 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1951 Register dwarf_reg;
1952 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001953 for (i=d; i<regs; ++i)
1954 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001955 dwarf_reg.num = start_reg + i;
1956 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001957 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001958 if (!success)
1959 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001960 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001961 return false;
1962 addr += reg_byte_size;
1963 }
1964
1965 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001966 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001967
1968 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1969 return false;
1970 }
1971 return true;
1972}
1973
Johnny Chenb77be412011-02-04 00:40:18 +00001974// SVC (previously SWI)
1975bool
1976EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1977{
1978#if 0
1979 // ARM pseudo code...
1980 if (ConditionPassed())
1981 {
1982 EncodingSpecificOperations();
1983 CallSupervisor();
1984 }
1985#endif
1986
1987 bool success = false;
1988 const uint32_t opcode = OpcodeAsUnsigned (&success);
1989 if (!success)
1990 return false;
1991
1992 if (ConditionPassed())
1993 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001994 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001995 addr_t lr; // next instruction address
1996 if (!success)
1997 return false;
1998 uint32_t imm32; // the immediate constant
1999 uint32_t mode; // ARM or Thumb mode
2000 switch (encoding) {
2001 case eEncodingT1:
2002 lr = (pc + 2) | 1u; // return address
2003 imm32 = Bits32(opcode, 7, 0);
2004 mode = eModeThumb;
2005 break;
2006 case eEncodingA1:
2007 lr = pc + 4; // return address
2008 imm32 = Bits32(opcode, 23, 0);
2009 mode = eModeARM;
2010 break;
2011 default:
2012 return false;
2013 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002014
2015 EmulateInstruction::Context context;
2016 context.type = EmulateInstruction::eContextSupervisorCall;
2017 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00002018 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
2019 return false;
2020 }
2021 return true;
2022}
2023
Johnny Chenc315f862011-02-05 00:46:10 +00002024// If Then makes up to four following instructions (the IT block) conditional.
2025bool
2026EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
2027{
2028#if 0
2029 // ARM pseudo code...
2030 EncodingSpecificOperations();
2031 ITSTATE.IT<7:0> = firstcond:mask;
2032#endif
2033
2034 bool success = false;
2035 const uint32_t opcode = OpcodeAsUnsigned (&success);
2036 if (!success)
2037 return false;
2038
2039 m_it_session.InitIT(Bits32(opcode, 7, 0));
2040 return true;
2041}
2042
Johnny Chen3b620b32011-02-07 20:11:47 +00002043// Branch causes a branch to a target address.
2044bool
2045EmulateInstructionARM::EmulateB (ARMEncoding encoding)
2046{
2047#if 0
2048 // ARM pseudo code...
2049 if (ConditionPassed())
2050 {
2051 EncodingSpecificOperations();
2052 BranchWritePC(PC + imm32);
2053 }
2054#endif
2055
2056 bool success = false;
2057 const uint32_t opcode = OpcodeAsUnsigned (&success);
2058 if (!success)
2059 return false;
2060
Johnny Chen9ee056b2011-02-08 00:06:35 +00002061 if (ConditionPassed())
2062 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002063 EmulateInstruction::Context context;
2064 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002065 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002066 if (!success)
2067 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00002068 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00002069 int32_t imm32; // PC-relative offset
2070 switch (encoding) {
2071 case eEncodingT1:
2072 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2073 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00002074 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002075 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002076 break;
2077 case eEncodingT2:
2078 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00002079 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002080 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002081 break;
2082 case eEncodingT3:
2083 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2084 {
Johnny Chenbd599902011-02-10 21:39:01 +00002085 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002086 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002087 uint32_t J1 = Bit32(opcode, 13);
2088 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002089 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00002090 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002091 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00002092 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002093 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002094 break;
2095 }
2096 case eEncodingT4:
2097 {
Johnny Chenbd599902011-02-10 21:39:01 +00002098 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002099 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00002100 uint32_t J1 = Bit32(opcode, 13);
2101 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002102 uint32_t imm11 = Bits32(opcode, 10, 0);
2103 uint32_t I1 = !(J1 ^ S);
2104 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00002105 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002106 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00002107 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002108 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002109 break;
2110 }
2111 case eEncodingA1:
2112 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00002113 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002114 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00002115 break;
2116 default:
2117 return false;
2118 }
2119 if (!BranchWritePC(context, target))
2120 return false;
2121 }
2122 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00002123}
2124
Johnny Chen53ebab72011-02-08 23:21:57 +00002125// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
2126// zero and conditionally branch forward a constant value. They do not affect the condition flags.
2127// CBNZ, CBZ
2128bool
2129EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
2130{
2131#if 0
2132 // ARM pseudo code...
2133 EncodingSpecificOperations();
2134 if nonzero ^ IsZero(R[n]) then
2135 BranchWritePC(PC + imm32);
2136#endif
2137
2138 bool success = false;
2139 const uint32_t opcode = OpcodeAsUnsigned (&success);
2140 if (!success)
2141 return false;
2142
2143 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002144 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002145 if (!success)
2146 return false;
2147
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002148 EmulateInstruction::Context context;
2149 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002150 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002151 if (!success)
2152 return false;
2153
2154 addr_t target; // target address
2155 uint32_t imm32; // PC-relative offset to branch forward
2156 bool nonzero;
2157 switch (encoding) {
2158 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002159 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002160 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002161 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002162 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002163 break;
2164 default:
2165 return false;
2166 }
2167 if (nonzero ^ (reg_val == 0))
2168 if (!BranchWritePC(context, target))
2169 return false;
2170
2171 return true;
2172}
2173
Johnny Chen60299ec2011-02-17 19:34:27 +00002174// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2175// A base register provides a pointer to the table, and a second register supplies an index into the table.
2176// The branch length is twice the value of the byte returned from the table.
2177//
2178// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword 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 halfword returned from the table.
2181// TBB, TBH
2182bool
2183EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
2184{
2185#if 0
2186 // ARM pseudo code...
2187 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2188 if is_tbh then
2189 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2190 else
2191 halfwords = UInt(MemU[R[n]+R[m], 1]);
2192 BranchWritePC(PC + 2*halfwords);
2193#endif
2194
2195 bool success = false;
2196 const uint32_t opcode = OpcodeAsUnsigned (&success);
2197 if (!success)
2198 return false;
2199
2200 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2201 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2202 bool is_tbh; // true if table branch halfword
2203 switch (encoding) {
2204 case eEncodingT1:
2205 Rn = Bits32(opcode, 19, 16);
2206 Rm = Bits32(opcode, 3, 0);
2207 is_tbh = BitIsSet(opcode, 4);
2208 if (Rn == 13 || BadReg(Rm))
2209 return false;
2210 if (InITBlock() && !LastInITBlock())
2211 return false;
2212 break;
2213 default:
2214 return false;
2215 }
2216
2217 // Read the address of the table from the operand register Rn.
2218 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002219 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002220 if (!success)
2221 return false;
2222
2223 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002224 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002225 if (!success)
2226 return false;
2227
2228 // the offsetted table address
2229 addr_t addr = base + (is_tbh ? index*2 : index);
2230
2231 // PC-relative offset to branch forward
2232 EmulateInstruction::Context context;
2233 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002234 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002235 if (!success)
2236 return false;
2237
Johnny Chene39f22d2011-02-19 01:36:13 +00002238 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002239 if (!success)
2240 return false;
2241
2242 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002243 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002244 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2245 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2246
2247 if (!BranchWritePC(context, target))
2248 return false;
2249
2250 return true;
2251}
2252
Caroline Ticedcc11b32011-03-02 23:57:02 +00002253// This instruction adds an immediate value to a register value, and writes the result to the destination register.
2254// It can optionally update the condition flags based on the result.
2255bool
2256EmulateInstructionARM::EmulateADDImmThumb (ARMEncoding encoding)
2257{
2258#if 0
2259 if ConditionPassed() then
2260 EncodingSpecificOperations();
2261 (result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2262 R[d] = result;
2263 if setflags then
2264 APSR.N = result<31>;
2265 APSR.Z = IsZeroBit(result);
2266 APSR.C = carry;
2267 APSR.V = overflow;
2268#endif
2269
2270 bool success = false;
2271 const uint32_t opcode = OpcodeAsUnsigned (&success);
2272 if (!success)
2273 return false;
2274
2275 if (ConditionPassed())
2276 {
2277 uint32_t d;
2278 uint32_t n;
2279 bool setflags;
2280 uint32_t imm32;
2281 uint32_t carry_out;
2282
2283 //EncodingSpecificOperations();
2284 switch (encoding)
2285 {
2286 case eEncodingT1:
2287 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
2288 d = Bits32 (opcode, 2, 0);
2289 n = Bits32 (opcode, 5, 3);
2290 setflags = !InITBlock();
2291 imm32 = Bits32 (opcode, 8,6);
2292
2293 break;
2294
2295 case eEncodingT2:
2296 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
2297 d = Bits32 (opcode, 10, 8);
2298 n = Bits32 (opcode, 10, 8);
2299 setflags = !InITBlock();
2300 imm32 = Bits32 (opcode, 7, 0);
2301
2302 break;
2303
2304 case eEncodingT3:
2305 // if Rd == ’1111’ && S == ’1’ then SEE CMN (immediate);
2306 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2307 // d = UInt(Rd); n = UInt(Rn); setflags = (S == ’1’); imm32 = ThumbExpandImm(i:imm3:imm8);
2308 d = Bits32 (opcode, 11, 8);
2309 n = Bits32 (opcode, 19, 16);
2310 setflags = BitIsSet (opcode, 20);
2311 imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
2312
2313 // if BadReg(d) || n == 15 then UNPREDICTABLE;
2314 if (BadReg (d) || (n == 15))
2315 return false;
2316
2317 break;
2318
2319 case eEncodingT4:
2320 {
2321 // if Rn == ’1111’ then SEE ADR;
2322 // if Rn == ’1101’ then SEE ADD (SP plus immediate);
2323 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
2324 d = Bits32 (opcode, 11, 8);
2325 n = Bits32 (opcode, 19, 16);
2326 setflags = false;
2327 uint32_t i = Bit32 (opcode, 26);
2328 uint32_t imm3 = Bits32 (opcode, 14, 12);
2329 uint32_t imm8 = Bits32 (opcode, 7, 0);
2330 imm32 = (i << 11) | (imm3 << 8) | imm8;
2331
2332 // if BadReg(d) then UNPREDICTABLE;
2333 if (BadReg (d))
2334 return false;
2335
2336 break;
2337 }
2338 default:
2339 return false;
2340 }
2341
2342 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2343 if (!success)
2344 return false;
2345
2346 //(result, carry, overflow) = AddWithCarry(R[n], imm32, ’0’);
2347 AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
2348
2349 Register reg_n;
2350 reg_n.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2351
2352 EmulateInstruction::Context context;
2353 context.type = eContextAddition;
2354 context.SetRegisterPlusOffset (reg_n, imm32);
2355
2356 //R[d] = result;
2357 //if setflags then
2358 //APSR.N = result<31>;
2359 //APSR.Z = IsZeroBit(result);
2360 //APSR.C = carry;
2361 //APSR.V = overflow;
2362 if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
2363 return false;
2364
2365 }
2366 return true;
2367}
2368
Johnny Chen8fa20592011-02-18 01:22:22 +00002369// This instruction adds an immediate value to a register value, and writes the result to the destination
2370// register. It can optionally update the condition flags based on the result.
2371bool
2372EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2373{
2374#if 0
2375 // ARM pseudo code...
2376 if ConditionPassed() then
2377 EncodingSpecificOperations();
2378 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2379 if d == 15 then
2380 ALUWritePC(result); // setflags is always FALSE here
2381 else
2382 R[d] = result;
2383 if setflags then
2384 APSR.N = result<31>;
2385 APSR.Z = IsZeroBit(result);
2386 APSR.C = carry;
2387 APSR.V = overflow;
2388#endif
2389
2390 bool success = false;
2391 const uint32_t opcode = OpcodeAsUnsigned (&success);
2392 if (!success)
2393 return false;
2394
2395 if (ConditionPassed())
2396 {
2397 uint32_t Rd, Rn;
2398 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2399 bool setflags;
2400 switch (encoding)
2401 {
2402 case eEncodingA1:
2403 Rd = Bits32(opcode, 15, 12);
2404 Rn = Bits32(opcode, 19, 16);
2405 setflags = BitIsSet(opcode, 20);
2406 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2407 break;
2408 default:
2409 return false;
2410 }
2411
Johnny Chen8fa20592011-02-18 01:22:22 +00002412 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002413 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002414 if (!success)
2415 return false;
2416
2417 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2418
2419 EmulateInstruction::Context context;
2420 context.type = EmulateInstruction::eContextImmediate;
2421 context.SetNoArgs ();
2422
2423 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2424 return false;
2425 }
2426 return true;
2427}
2428
Johnny Chend761dcf2011-02-17 22:03:29 +00002429// This instruction adds a register value and an optionally-shifted register value, and writes the result
2430// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002431bool
Johnny Chen9f687722011-02-18 00:02:28 +00002432EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002433{
2434#if 0
2435 // ARM pseudo code...
2436 if ConditionPassed() then
2437 EncodingSpecificOperations();
2438 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2439 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2440 if d == 15 then
2441 ALUWritePC(result); // setflags is always FALSE here
2442 else
2443 R[d] = result;
2444 if setflags then
2445 APSR.N = result<31>;
2446 APSR.Z = IsZeroBit(result);
2447 APSR.C = carry;
2448 APSR.V = overflow;
2449#endif
2450
2451 bool success = false;
2452 const uint32_t opcode = OpcodeAsUnsigned (&success);
2453 if (!success)
2454 return false;
2455
2456 if (ConditionPassed())
2457 {
2458 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002459 ARM_ShifterType shift_t;
2460 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002461 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002462 switch (encoding)
2463 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002464 case eEncodingT1:
2465 Rd = Bits32(opcode, 2, 0);
2466 Rn = Bits32(opcode, 5, 3);
2467 Rm = Bits32(opcode, 8, 6);
2468 setflags = !InITBlock();
2469 shift_t = SRType_LSL;
2470 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002471 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002472 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002473 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002474 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002475 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002476 shift_t = SRType_LSL;
2477 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002478 if (Rn == 15 && Rm == 15)
2479 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002480 if (Rd == 15 && InITBlock() && !LastInITBlock())
2481 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002482 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002483 case eEncodingA1:
2484 Rd = Bits32(opcode, 15, 12);
2485 Rn = Bits32(opcode, 19, 16);
2486 Rm = Bits32(opcode, 3, 0);
2487 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002488 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002489 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002490 default:
2491 return false;
2492 }
2493
Johnny Chen26863dc2011-02-09 23:43:29 +00002494 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002495 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002496 if (!success)
2497 return false;
2498
2499 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002500 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002501 if (!success)
2502 return false;
2503
Johnny Chene97c0d52011-02-18 19:32:20 +00002504 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002505 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002506
2507 EmulateInstruction::Context context;
2508 context.type = EmulateInstruction::eContextImmediate;
2509 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002510
Johnny Chen10530c22011-02-17 22:37:12 +00002511 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002512 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002513 }
2514 return true;
2515}
2516
Johnny Chen34075cb2011-02-22 01:56:31 +00002517// Compare Negative (immediate) adds a register value and an immediate value.
2518// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002519bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002520EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2521{
2522#if 0
2523 // ARM pseudo code...
2524 if ConditionPassed() then
2525 EncodingSpecificOperations();
2526 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2527 APSR.N = result<31>;
2528 APSR.Z = IsZeroBit(result);
2529 APSR.C = carry;
2530 APSR.V = overflow;
2531#endif
2532
2533 bool success = false;
2534 const uint32_t opcode = OpcodeAsUnsigned (&success);
2535 if (!success)
2536 return false;
2537
2538 uint32_t Rn; // the first operand
2539 uint32_t imm32; // the immediate value to be compared with
2540 switch (encoding) {
2541 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002542 Rn = Bits32(opcode, 19, 16);
2543 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2544 if (Rn == 15)
2545 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002546 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002547 case eEncodingA1:
2548 Rn = Bits32(opcode, 19, 16);
2549 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2550 break;
2551 default:
2552 return false;
2553 }
2554 // Read the register value from the operand register Rn.
2555 uint32_t reg_val = ReadCoreReg(Rn, &success);
2556 if (!success)
2557 return false;
2558
Johnny Chen078fbc62011-02-22 19:48:22 +00002559 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002560
2561 EmulateInstruction::Context context;
2562 context.type = EmulateInstruction::eContextImmediate;
2563 context.SetNoArgs ();
2564 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2565 return false;
2566
2567 return true;
2568}
2569
2570// Compare Negative (register) adds a register value and an optionally-shifted register value.
2571// It updates the condition flags based on the result, and discards the result.
2572bool
2573EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2574{
2575#if 0
2576 // ARM pseudo code...
2577 if ConditionPassed() then
2578 EncodingSpecificOperations();
2579 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2580 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2581 APSR.N = result<31>;
2582 APSR.Z = IsZeroBit(result);
2583 APSR.C = carry;
2584 APSR.V = overflow;
2585#endif
2586
2587 bool success = false;
2588 const uint32_t opcode = OpcodeAsUnsigned (&success);
2589 if (!success)
2590 return false;
2591
2592 uint32_t Rn; // the first operand
2593 uint32_t Rm; // the second operand
2594 ARM_ShifterType shift_t;
2595 uint32_t shift_n; // the shift applied to the value read from Rm
2596 switch (encoding) {
2597 case eEncodingT1:
2598 Rn = Bits32(opcode, 2, 0);
2599 Rm = Bits32(opcode, 5, 3);
2600 shift_t = SRType_LSL;
2601 shift_n = 0;
2602 break;
2603 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002604 Rn = Bits32(opcode, 19, 16);
2605 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002606 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002607 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2608 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002609 return false;
2610 break;
2611 case eEncodingA1:
2612 Rn = Bits32(opcode, 19, 16);
2613 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002614 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002615 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002616 default:
2617 return false;
2618 }
2619 // Read the register value from register Rn.
2620 uint32_t val1 = ReadCoreReg(Rn, &success);
2621 if (!success)
2622 return false;
2623
2624 // Read the register value from register Rm.
2625 uint32_t val2 = ReadCoreReg(Rm, &success);
2626 if (!success)
2627 return false;
2628
2629 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002630 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002631
2632 EmulateInstruction::Context context;
2633 context.type = EmulateInstruction::eContextImmediate;
2634 context.SetNoArgs();
2635 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2636 return false;
2637
2638 return true;
2639}
2640
2641// Compare (immediate) subtracts an immediate value from a register value.
2642// It updates the condition flags based on the result, and discards the result.
2643bool
2644EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002645{
2646#if 0
2647 // ARM pseudo code...
2648 if ConditionPassed() then
2649 EncodingSpecificOperations();
2650 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2651 APSR.N = result<31>;
2652 APSR.Z = IsZeroBit(result);
2653 APSR.C = carry;
2654 APSR.V = overflow;
2655#endif
2656
2657 bool success = false;
2658 const uint32_t opcode = OpcodeAsUnsigned (&success);
2659 if (!success)
2660 return false;
2661
2662 uint32_t Rn; // the first operand
2663 uint32_t imm32; // the immediate value to be compared with
2664 switch (encoding) {
2665 case eEncodingT1:
2666 Rn = Bits32(opcode, 10, 8);
2667 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002668 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002669 case eEncodingT2:
2670 Rn = Bits32(opcode, 19, 16);
2671 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2672 if (Rn == 15)
2673 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002674 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002675 case eEncodingA1:
2676 Rn = Bits32(opcode, 19, 16);
2677 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002678 break;
2679 default:
2680 return false;
2681 }
2682 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002683 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002684 if (!success)
2685 return false;
2686
Johnny Chen10530c22011-02-17 22:37:12 +00002687 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2688
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002689 EmulateInstruction::Context context;
2690 context.type = EmulateInstruction::eContextImmediate;
2691 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002692 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2693 return false;
2694
Johnny Chend4dc4442011-02-11 02:02:56 +00002695 return true;
2696}
2697
Johnny Chen34075cb2011-02-22 01:56:31 +00002698// Compare (register) subtracts an optionally-shifted register value from a register value.
2699// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002700bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002701EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002702{
2703#if 0
2704 // ARM pseudo code...
2705 if ConditionPassed() then
2706 EncodingSpecificOperations();
2707 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2708 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2709 APSR.N = result<31>;
2710 APSR.Z = IsZeroBit(result);
2711 APSR.C = carry;
2712 APSR.V = overflow;
2713#endif
2714
2715 bool success = false;
2716 const uint32_t opcode = OpcodeAsUnsigned (&success);
2717 if (!success)
2718 return false;
2719
2720 uint32_t Rn; // the first operand
2721 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002722 ARM_ShifterType shift_t;
2723 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002724 switch (encoding) {
2725 case eEncodingT1:
2726 Rn = Bits32(opcode, 2, 0);
2727 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002728 shift_t = SRType_LSL;
2729 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002730 break;
2731 case eEncodingT2:
2732 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2733 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002734 shift_t = SRType_LSL;
2735 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002736 if (Rn < 8 && Rm < 8)
2737 return false;
2738 if (Rn == 15 || Rm == 15)
2739 return false;
2740 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002741 case eEncodingA1:
2742 Rn = Bits32(opcode, 19, 16);
2743 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002744 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002745 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002746 default:
2747 return false;
2748 }
2749 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002750 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002751 if (!success)
2752 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002753
Johnny Chene4a4d302011-02-11 21:53:58 +00002754 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002755 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002756 if (!success)
2757 return false;
2758
Johnny Chen34075cb2011-02-22 01:56:31 +00002759 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2760 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002761
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002762 EmulateInstruction::Context context;
2763 context.type = EmulateInstruction::eContextImmediate;
2764 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002765 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2766 return false;
2767
Johnny Chene4a4d302011-02-11 21:53:58 +00002768 return true;
2769}
2770
Johnny Chen82f16aa2011-02-15 20:10:55 +00002771// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2772// shifting in copies of its sign bit, and writes the result to the destination register. It can
2773// optionally update the condition flags based on the result.
2774bool
2775EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2776{
2777#if 0
2778 // ARM pseudo code...
2779 if ConditionPassed() then
2780 EncodingSpecificOperations();
2781 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2782 if d == 15 then // Can only occur for ARM encoding
2783 ALUWritePC(result); // setflags is always FALSE here
2784 else
2785 R[d] = result;
2786 if setflags then
2787 APSR.N = result<31>;
2788 APSR.Z = IsZeroBit(result);
2789 APSR.C = carry;
2790 // APSR.V unchanged
2791#endif
2792
Johnny Chen41a0a152011-02-16 01:27:54 +00002793 return EmulateShiftImm(encoding, SRType_ASR);
2794}
2795
2796// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2797// shifting in copies of its sign bit, and writes the result to the destination register.
2798// The variable number of bits is read from the bottom byte of a register. It can optionally update
2799// the condition flags based on the result.
2800bool
2801EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2802{
2803#if 0
2804 // ARM pseudo code...
2805 if ConditionPassed() then
2806 EncodingSpecificOperations();
2807 shift_n = UInt(R[m]<7:0>);
2808 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2809 R[d] = result;
2810 if setflags then
2811 APSR.N = result<31>;
2812 APSR.Z = IsZeroBit(result);
2813 APSR.C = carry;
2814 // APSR.V unchanged
2815#endif
2816
2817 return EmulateShiftReg(encoding, SRType_ASR);
2818}
2819
2820// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2821// shifting in zeros, and writes the result to the destination register. It can optionally
2822// update the condition flags based on the result.
2823bool
2824EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2825{
2826#if 0
2827 // ARM pseudo code...
2828 if ConditionPassed() then
2829 EncodingSpecificOperations();
2830 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2831 if d == 15 then // Can only occur for ARM encoding
2832 ALUWritePC(result); // setflags is always FALSE here
2833 else
2834 R[d] = result;
2835 if setflags then
2836 APSR.N = result<31>;
2837 APSR.Z = IsZeroBit(result);
2838 APSR.C = carry;
2839 // APSR.V unchanged
2840#endif
2841
2842 return EmulateShiftImm(encoding, SRType_LSL);
2843}
2844
2845// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2846// shifting in zeros, and writes the result to the destination register. The variable number
2847// of bits is read from the bottom byte of a register. It can optionally update the condition
2848// flags based on the result.
2849bool
2850EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2851{
2852#if 0
2853 // ARM pseudo code...
2854 if ConditionPassed() then
2855 EncodingSpecificOperations();
2856 shift_n = UInt(R[m]<7:0>);
2857 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2858 R[d] = result;
2859 if setflags then
2860 APSR.N = result<31>;
2861 APSR.Z = IsZeroBit(result);
2862 APSR.C = carry;
2863 // APSR.V unchanged
2864#endif
2865
2866 return EmulateShiftReg(encoding, SRType_LSL);
2867}
2868
2869// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2870// shifting in zeros, and writes the result to the destination register. It can optionally
2871// update the condition flags based on the result.
2872bool
2873EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2874{
2875#if 0
2876 // ARM pseudo code...
2877 if ConditionPassed() then
2878 EncodingSpecificOperations();
2879 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2880 if d == 15 then // Can only occur for ARM encoding
2881 ALUWritePC(result); // setflags is always FALSE here
2882 else
2883 R[d] = result;
2884 if setflags then
2885 APSR.N = result<31>;
2886 APSR.Z = IsZeroBit(result);
2887 APSR.C = carry;
2888 // APSR.V unchanged
2889#endif
2890
2891 return EmulateShiftImm(encoding, SRType_LSR);
2892}
2893
2894// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2895// shifting in zeros, and writes the result to the destination register. The variable number
2896// of bits is read from the bottom byte of a register. It can optionally update the condition
2897// flags based on the result.
2898bool
2899EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2900{
2901#if 0
2902 // ARM pseudo code...
2903 if ConditionPassed() then
2904 EncodingSpecificOperations();
2905 shift_n = UInt(R[m]<7:0>);
2906 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2907 R[d] = result;
2908 if setflags then
2909 APSR.N = result<31>;
2910 APSR.Z = IsZeroBit(result);
2911 APSR.C = carry;
2912 // APSR.V unchanged
2913#endif
2914
2915 return EmulateShiftReg(encoding, SRType_LSR);
2916}
2917
Johnny Cheneeab4852011-02-16 22:14:44 +00002918// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2919// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2920// It can optionally update the condition flags based on the result.
2921bool
2922EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2923{
2924#if 0
2925 // ARM pseudo code...
2926 if ConditionPassed() then
2927 EncodingSpecificOperations();
2928 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2929 if d == 15 then // Can only occur for ARM encoding
2930 ALUWritePC(result); // setflags is always FALSE here
2931 else
2932 R[d] = result;
2933 if setflags then
2934 APSR.N = result<31>;
2935 APSR.Z = IsZeroBit(result);
2936 APSR.C = carry;
2937 // APSR.V unchanged
2938#endif
2939
2940 return EmulateShiftImm(encoding, SRType_ROR);
2941}
2942
2943// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2944// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2945// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2946// flags based on the result.
2947bool
2948EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2949{
2950#if 0
2951 // ARM pseudo code...
2952 if ConditionPassed() then
2953 EncodingSpecificOperations();
2954 shift_n = UInt(R[m]<7:0>);
2955 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2956 R[d] = result;
2957 if setflags then
2958 APSR.N = result<31>;
2959 APSR.Z = IsZeroBit(result);
2960 APSR.C = carry;
2961 // APSR.V unchanged
2962#endif
2963
2964 return EmulateShiftReg(encoding, SRType_ROR);
2965}
2966
2967// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2968// with the carry flag shifted into bit [31].
2969//
2970// RRX can optionally update the condition flags based on the result.
2971// In that case, bit [0] is shifted into the carry flag.
2972bool
2973EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2974{
2975#if 0
2976 // ARM pseudo code...
2977 if ConditionPassed() then
2978 EncodingSpecificOperations();
2979 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2980 if d == 15 then // Can only occur for ARM encoding
2981 ALUWritePC(result); // setflags is always FALSE here
2982 else
2983 R[d] = result;
2984 if setflags then
2985 APSR.N = result<31>;
2986 APSR.Z = IsZeroBit(result);
2987 APSR.C = carry;
2988 // APSR.V unchanged
2989#endif
2990
2991 return EmulateShiftImm(encoding, SRType_RRX);
2992}
2993
Johnny Chen41a0a152011-02-16 01:27:54 +00002994bool
2995EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2996{
2997 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2998
Johnny Chen82f16aa2011-02-15 20:10:55 +00002999 bool success = false;
3000 const uint32_t opcode = OpcodeAsUnsigned (&success);
3001 if (!success)
3002 return false;
3003
3004 if (ConditionPassed())
3005 {
Johnny Chene7f89532011-02-15 23:22:46 +00003006 uint32_t Rd; // the destination register
3007 uint32_t Rm; // the first operand register
3008 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00003009 uint32_t carry; // the carry bit after the shift operation
3010 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00003011
3012 // Special case handling!
3013 // A8.6.139 ROR (immediate) -- Encoding T1
3014 if (shift_type == SRType_ROR && encoding == eEncodingT1)
3015 {
3016 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
3017 // have the same decoding of bit fields as the other Thumb2 shift operations.
3018 encoding = eEncodingT2;
3019 }
3020
Johnny Chen82f16aa2011-02-15 20:10:55 +00003021 switch (encoding) {
3022 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00003023 // Due to the above special case handling!
3024 assert(shift_type != SRType_ROR);
3025
Johnny Chen82f16aa2011-02-15 20:10:55 +00003026 Rd = Bits32(opcode, 2, 0);
3027 Rm = Bits32(opcode, 5, 3);
3028 setflags = !InITBlock();
3029 imm5 = Bits32(opcode, 10, 6);
3030 break;
3031 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00003032 // A8.6.141 RRX
3033 assert(shift_type != SRType_RRX);
3034
Johnny Chen82f16aa2011-02-15 20:10:55 +00003035 Rd = Bits32(opcode, 11, 8);
3036 Rm = Bits32(opcode, 3, 0);
3037 setflags = BitIsSet(opcode, 20);
3038 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3039 if (BadReg(Rd) || BadReg(Rm))
3040 return false;
3041 break;
3042 case eEncodingA1:
3043 Rd = Bits32(opcode, 15, 12);
3044 Rm = Bits32(opcode, 3, 0);
3045 setflags = BitIsSet(opcode, 20);
3046 imm5 = Bits32(opcode, 11, 7);
3047 break;
3048 default:
3049 return false;
3050 }
3051
Johnny Cheneeab4852011-02-16 22:14:44 +00003052 // A8.6.139 ROR (immediate)
3053 if (shift_type == SRType_ROR && imm5 == 0)
3054 shift_type = SRType_RRX;
3055
Johnny Chen82f16aa2011-02-15 20:10:55 +00003056 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003057 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003058 if (!success)
3059 return false;
3060
Johnny Cheneeab4852011-02-16 22:14:44 +00003061 // Decode the shift amount if not RRX.
3062 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00003063
Johnny Chene97c0d52011-02-18 19:32:20 +00003064 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00003065
3066 // The context specifies that an immediate is to be moved into Rd.
3067 EmulateInstruction::Context context;
3068 context.type = EmulateInstruction::eContextImmediate;
3069 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00003070
Johnny Chen10530c22011-02-17 22:37:12 +00003071 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00003072 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00003073 }
3074 return true;
3075}
3076
Johnny Chene7f89532011-02-15 23:22:46 +00003077bool
Johnny Chen41a0a152011-02-16 01:27:54 +00003078EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00003079{
Johnny Chen41a0a152011-02-16 01:27:54 +00003080 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00003081
3082 bool success = false;
3083 const uint32_t opcode = OpcodeAsUnsigned (&success);
3084 if (!success)
3085 return false;
3086
3087 if (ConditionPassed())
3088 {
3089 uint32_t Rd; // the destination register
3090 uint32_t Rn; // the first operand register
3091 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
3092 uint32_t carry; // the carry bit after the shift operation
3093 bool setflags;
3094 switch (encoding) {
3095 case eEncodingT1:
3096 Rd = Bits32(opcode, 2, 0);
3097 Rn = Rd;
3098 Rm = Bits32(opcode, 5, 3);
3099 setflags = !InITBlock();
3100 break;
3101 case eEncodingT2:
3102 Rd = Bits32(opcode, 11, 8);
3103 Rn = Bits32(opcode, 19, 16);
3104 Rm = Bits32(opcode, 3, 0);
3105 setflags = BitIsSet(opcode, 20);
3106 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3107 return false;
3108 break;
3109 case eEncodingA1:
3110 Rd = Bits32(opcode, 15, 12);
3111 Rn = Bits32(opcode, 3, 0);
3112 Rm = Bits32(opcode, 11, 8);
3113 setflags = BitIsSet(opcode, 20);
3114 if (Rd == 15 || Rn == 15 || Rm == 15)
3115 return false;
3116 break;
3117 default:
3118 return false;
3119 }
3120
3121 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00003122 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003123 if (!success)
3124 return false;
3125 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00003126 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00003127 if (!success)
3128 return false;
3129
3130 // Get the shift amount.
3131 uint32_t amt = Bits32(val, 7, 0);
3132
Johnny Chene97c0d52011-02-18 19:32:20 +00003133 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00003134
3135 // The context specifies that an immediate is to be moved into Rd.
3136 EmulateInstruction::Context context;
3137 context.type = EmulateInstruction::eContextImmediate;
3138 context.SetNoArgs ();
3139
Johnny Chen10530c22011-02-17 22:37:12 +00003140 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00003141 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00003142 }
3143 return true;
3144}
3145
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003146// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00003147// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003148// can be written back to the base register.
3149bool
3150EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
3151{
3152#if 0
3153 // ARM pseudo code...
3154 if ConditionPassed()
3155 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3156 address = R[n];
3157
3158 for i = 0 to 14
3159 if registers<i> == '1' then
3160 R[i] = MemA[address, 4]; address = address + 4;
3161 if registers<15> == '1' then
3162 LoadWritePC (MemA[address, 4]);
3163
3164 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3165 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3166
3167#endif
3168
3169 bool success = false;
3170 const uint32_t opcode = OpcodeAsUnsigned (&success);
3171 if (!success)
3172 return false;
3173
3174 if (ConditionPassed())
3175 {
3176 uint32_t n;
3177 uint32_t registers = 0;
3178 bool wback;
3179 const uint32_t addr_byte_size = GetAddressByteSize();
3180 switch (encoding)
3181 {
3182 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003183 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003184 n = Bits32 (opcode, 10, 8);
3185 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003186 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003187 wback = BitIsClear (registers, n);
3188 // if BitCount(registers) < 1 then UNPREDICTABLE;
3189 if (BitCount(registers) < 1)
3190 return false;
3191 break;
3192 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003193 // if W == ’1’ && Rn == ’1101’ then SEE POP;
3194 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003195 n = Bits32 (opcode, 19, 16);
3196 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003197 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003198 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003199
3200 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003201 if ((n == 15)
3202 || (BitCount (registers) < 2)
3203 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3204 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003205
3206 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003207 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003208 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003209
3210 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003211 if (wback
3212 && BitIsSet (registers, n))
3213 return false;
3214 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003215
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003216 case eEncodingA1:
3217 n = Bits32 (opcode, 19, 16);
3218 registers = Bits32 (opcode, 15, 0);
3219 wback = BitIsSet (opcode, 21);
3220 if ((n == 15)
3221 || (BitCount (registers) < 1))
3222 return false;
3223 break;
3224 default:
3225 return false;
3226 }
3227
3228 int32_t offset = 0;
3229 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3230 if (!success)
3231 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00003232
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003233 EmulateInstruction::Context context;
3234 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3235 Register dwarf_reg;
3236 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3237 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003238
3239 for (int i = 0; i < 14; ++i)
3240 {
3241 if (BitIsSet (registers, i))
3242 {
Caroline Tice85aab332011-02-08 23:56:10 +00003243 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003244 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003245 if (wback && (n == 13)) // Pop Instruction
3246 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3247
3248 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00003249 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003250 if (!success)
3251 return false;
3252
3253 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3254 return false;
3255
3256 offset += addr_byte_size;
3257 }
3258 }
3259
3260 if (BitIsSet (registers, 15))
3261 {
3262 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003263 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003264 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003265 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003266 if (!success)
3267 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003268 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003269 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003270 return false;
3271 }
3272
3273 if (wback && BitIsClear (registers, n))
3274 {
Caroline Ticefa172202011-02-11 22:49:54 +00003275 // R[n] = R[n] + 4 * BitCount (registers)
3276 int32_t offset = addr_byte_size * BitCount (registers);
3277 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003278 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003279
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003280 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3281 return false;
3282 }
3283 if (wback && BitIsSet (registers, n))
3284 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003285 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003286 }
3287 return true;
3288}
Caroline Tice713c2662011-02-11 17:59:55 +00003289
3290// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3291// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3292// can optionally be written back tot he base registers.
3293bool
3294EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
3295{
3296#if 0
3297 // ARM pseudo code...
3298 if ConditionPassed() then
3299 EncodingSpecificOperations();
3300 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003301
Caroline Tice713c2662011-02-11 17:59:55 +00003302 for i = 0 to 14
3303 if registers<i> == ’1’ then
3304 R[i] = MemA[address,4]; address = address + 4;
3305
3306 if registers<15> == ’1’ then
3307 LoadWritePC(MemA[address,4]);
3308
3309 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3310 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3311#endif
3312
3313 bool success = false;
3314 const uint32_t opcode = OpcodeAsUnsigned (&success);
3315 if (!success)
3316 return false;
3317
3318 if (ConditionPassed())
3319 {
3320 uint32_t n;
3321 uint32_t registers = 0;
3322 bool wback;
3323 const uint32_t addr_byte_size = GetAddressByteSize();
3324
3325 // EncodingSpecificOperations();
3326 switch (encoding)
3327 {
3328 case eEncodingA1:
3329 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3330 n = Bits32 (opcode, 19, 16);
3331 registers = Bits32 (opcode, 15, 0);
3332 wback = BitIsSet (opcode, 21);
3333
3334 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3335 if ((n == 15) || (BitCount (registers) < 1))
3336 return false;
3337
3338 break;
3339
3340 default:
3341 return false;
3342 }
3343 // address = R[n] - 4*BitCount(registers) + 4;
3344
3345 int32_t offset = 0;
3346 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3347
3348 if (!success)
3349 return false;
3350
3351 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3352
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003353 EmulateInstruction::Context context;
3354 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3355 Register dwarf_reg;
3356 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3357 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003358
3359 // for i = 0 to 14
3360 for (int i = 0; i < 14; ++i)
3361 {
3362 // if registers<i> == ’1’ then
3363 if (BitIsSet (registers, i))
3364 {
3365 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003366 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003367 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003368 if (!success)
3369 return false;
3370 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3371 return false;
3372 offset += addr_byte_size;
3373 }
3374 }
3375
3376 // if registers<15> == ’1’ then
3377 // LoadWritePC(MemA[address,4]);
3378 if (BitIsSet (registers, 15))
3379 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003380 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003381 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003382 if (!success)
3383 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003384 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003385 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003386 return false;
3387 }
3388
3389 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3390 if (wback && BitIsClear (registers, n))
3391 {
Caroline Tice713c2662011-02-11 17:59:55 +00003392 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3393 if (!success)
3394 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003395
3396 offset = (addr_byte_size * BitCount (registers)) * -1;
3397 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003398 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003399 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003400 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3401 return false;
3402 }
3403
3404 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3405 if (wback && BitIsSet (registers, n))
3406 return WriteBits32Unknown (n);
3407 }
3408 return true;
3409}
3410
3411// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3412// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3413// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003414bool
3415EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3416{
3417#if 0
3418 // ARM pseudo code...
3419 if ConditionPassed() then
3420 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3421 address = R[n] - 4*BitCount(registers);
3422
3423 for i = 0 to 14
3424 if registers<i> == ’1’ then
3425 R[i] = MemA[address,4]; address = address + 4;
3426 if registers<15> == ’1’ then
3427 LoadWritePC(MemA[address,4]);
3428
3429 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3430 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3431#endif
3432
3433 bool success = false;
3434 const uint32_t opcode = OpcodeAsUnsigned (&success);
3435 if (!success)
3436 return false;
3437
3438 if (ConditionPassed())
3439 {
3440 uint32_t n;
3441 uint32_t registers = 0;
3442 bool wback;
3443 const uint32_t addr_byte_size = GetAddressByteSize();
3444 switch (encoding)
3445 {
3446 case eEncodingT1:
3447 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3448 n = Bits32 (opcode, 19, 16);
3449 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003450 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003451 wback = BitIsSet (opcode, 21);
3452
3453 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3454 if ((n == 15)
3455 || (BitCount (registers) < 2)
3456 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3457 return false;
3458
3459 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003460 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003461 return false;
3462
3463 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3464 if (wback && BitIsSet (registers, n))
3465 return false;
3466
3467 break;
3468
3469 case eEncodingA1:
3470 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3471 n = Bits32 (opcode, 19, 16);
3472 registers = Bits32 (opcode, 15, 0);
3473 wback = BitIsSet (opcode, 21);
3474
3475 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3476 if ((n == 15) || (BitCount (registers) < 1))
3477 return false;
3478
3479 break;
3480
3481 default:
3482 return false;
3483 }
3484
Caroline Tice713c2662011-02-11 17:59:55 +00003485 // address = R[n] - 4*BitCount(registers);
3486
Caroline Tice0b29e242011-02-08 23:16:02 +00003487 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003488 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3489
3490 if (!success)
3491 return false;
3492
3493 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003494 EmulateInstruction::Context context;
3495 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3496 Register dwarf_reg;
3497 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3498 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003499
3500 for (int i = 0; i < 14; ++i)
3501 {
3502 if (BitIsSet (registers, i))
3503 {
3504 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003505 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003506 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003507 if (!success)
3508 return false;
3509
3510 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3511 return false;
3512
3513 offset += addr_byte_size;
3514 }
3515 }
3516
3517 // if registers<15> == ’1’ then
3518 // LoadWritePC(MemA[address,4]);
3519 if (BitIsSet (registers, 15))
3520 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003521 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003522 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003523 if (!success)
3524 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003525 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003526 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003527 return false;
3528 }
3529
3530 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3531 if (wback && BitIsClear (registers, n))
3532 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003533 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3534 if (!success)
3535 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003536
3537 offset = (addr_byte_size * BitCount (registers)) * -1;
3538 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003539 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003540 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003541 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3542 return false;
3543 }
3544
3545 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3546 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003547 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003548 }
3549 return true;
3550}
Caroline Tice85aab332011-02-08 23:56:10 +00003551
Caroline Tice713c2662011-02-11 17:59:55 +00003552// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3553// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3554// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003555bool
3556EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3557{
3558#if 0
3559 if ConditionPassed() then
3560 EncodingSpecificOperations();
3561 address = R[n] + 4;
3562
3563 for i = 0 to 14
3564 if registers<i> == ’1’ then
3565 R[i] = MemA[address,4]; address = address + 4;
3566 if registers<15> == ’1’ then
3567 LoadWritePC(MemA[address,4]);
3568
3569 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3570 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3571#endif
3572
3573 bool success = false;
3574 const uint32_t opcode = OpcodeAsUnsigned (&success);
3575 if (!success)
3576 return false;
3577
3578 if (ConditionPassed())
3579 {
3580 uint32_t n;
3581 uint32_t registers = 0;
3582 bool wback;
3583 const uint32_t addr_byte_size = GetAddressByteSize();
3584 switch (encoding)
3585 {
3586 case eEncodingA1:
3587 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3588 n = Bits32 (opcode, 19, 16);
3589 registers = Bits32 (opcode, 15, 0);
3590 wback = BitIsSet (opcode, 21);
3591
3592 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3593 if ((n == 15) || (BitCount (registers) < 1))
3594 return false;
3595
3596 break;
3597 default:
3598 return false;
3599 }
3600 // address = R[n] + 4;
3601
3602 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003603 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3604
3605 if (!success)
3606 return false;
3607
3608 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003609
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003610 EmulateInstruction::Context context;
3611 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3612 Register dwarf_reg;
3613 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3614 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003615
3616 for (int i = 0; i < 14; ++i)
3617 {
3618 if (BitIsSet (registers, i))
3619 {
3620 // R[i] = MemA[address,4]; address = address + 4;
3621
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003622 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003623 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003624 if (!success)
3625 return false;
3626
3627 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3628 return false;
3629
3630 offset += addr_byte_size;
3631 }
3632 }
3633
3634 // if registers<15> == ’1’ then
3635 // LoadWritePC(MemA[address,4]);
3636 if (BitIsSet (registers, 15))
3637 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003638 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003639 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003640 if (!success)
3641 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003642 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003643 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003644 return false;
3645 }
3646
3647 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3648 if (wback && BitIsClear (registers, n))
3649 {
Caroline Tice85aab332011-02-08 23:56:10 +00003650 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3651 if (!success)
3652 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003653
3654 offset = addr_byte_size * BitCount (registers);
3655 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003656 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003657 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003658 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3659 return false;
3660 }
3661
3662 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3663 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003664 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003665 }
3666 return true;
3667}
Caroline Tice0b29e242011-02-08 23:16:02 +00003668
Johnny Chenef21b592011-02-10 01:52:38 +00003669// Load Register (immediate) calculates an address from a base register value and
3670// an immediate offset, loads a word from memory, and writes to a register.
3671// LDR (immediate, Thumb)
3672bool
3673EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3674{
3675#if 0
3676 // ARM pseudo code...
3677 if (ConditionPassed())
3678 {
3679 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3680 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3681 address = if index then offset_addr else R[n];
3682 data = MemU[address,4];
3683 if wback then R[n] = offset_addr;
3684 if t == 15 then
3685 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3686 elsif UnalignedSupport() || address<1:0> = '00' then
3687 R[t] = data;
3688 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3689 }
3690#endif
3691
3692 bool success = false;
3693 const uint32_t opcode = OpcodeAsUnsigned (&success);
3694 if (!success)
3695 return false;
3696
3697 if (ConditionPassed())
3698 {
3699 uint32_t Rt; // the destination register
3700 uint32_t Rn; // the base register
3701 uint32_t imm32; // the immediate offset used to form the address
3702 addr_t offset_addr; // the offset address
3703 addr_t address; // the calculated address
3704 uint32_t data; // the literal data value from memory load
3705 bool add, index, wback;
3706 switch (encoding) {
3707 case eEncodingT1:
3708 Rt = Bits32(opcode, 5, 3);
3709 Rn = Bits32(opcode, 2, 0);
3710 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3711 // index = TRUE; add = TRUE; wback = FALSE
3712 add = true;
3713 index = true;
3714 wback = false;
3715 break;
3716 default:
3717 return false;
3718 }
3719 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3720 if (!success)
3721 return false;
3722 if (add)
3723 offset_addr = base + imm32;
3724 else
3725 offset_addr = base - imm32;
3726
3727 address = (index ? offset_addr : base);
3728
3729 if (wback)
3730 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003731 EmulateInstruction::Context ctx;
3732 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3733 Register dwarf_reg;
3734 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3735 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3736
Johnny Chenef21b592011-02-10 01:52:38 +00003737 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3738 return false;
3739 }
3740
3741 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003742 EmulateInstruction::Context context;
3743 context.type = EmulateInstruction::eContextImmediate;
3744 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003745
3746 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003747 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003748 if (!success)
3749 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003750
3751 if (Rt == 15)
3752 {
3753 if (Bits32(address, 1, 0) == 0)
3754 {
Johnny Chen668b4512011-02-15 21:08:58 +00003755 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003756 return false;
3757 }
3758 else
3759 return false;
3760 }
3761 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3762 {
3763 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3764 return false;
3765 }
3766 else
3767 return false;
3768 }
3769 return true;
3770}
3771
Caroline Ticeaf556562011-02-15 18:42:15 +00003772// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3773// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3774// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003775bool
3776EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3777{
3778#if 0
3779 if ConditionPassed() then
3780 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3781 address = R[n];
3782
3783 for i = 0 to 14
3784 if registers<i> == ’1’ then
3785 if i == n && wback && i != LowestSetBit(registers) then
3786 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3787 else
3788 MemA[address,4] = R[i];
3789 address = address + 4;
3790
3791 if registers<15> == ’1’ then // Only possible for encoding A1
3792 MemA[address,4] = PCStoreValue();
3793 if wback then R[n] = R[n] + 4*BitCount(registers);
3794#endif
3795
3796 bool success = false;
3797 const uint32_t opcode = OpcodeAsUnsigned (&success);
3798 if (!success)
3799 return false;
3800
3801 if (ConditionPassed ())
3802 {
3803 uint32_t n;
3804 uint32_t registers = 0;
3805 bool wback;
3806 const uint32_t addr_byte_size = GetAddressByteSize();
3807
3808 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3809 switch (encoding)
3810 {
3811 case eEncodingT1:
3812 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3813 n = Bits32 (opcode, 10, 8);
3814 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003815 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003816 wback = true;
3817
3818 // if BitCount(registers) < 1 then UNPREDICTABLE;
3819 if (BitCount (registers) < 1)
3820 return false;
3821
3822 break;
3823
3824 case eEncodingT2:
3825 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3826 n = Bits32 (opcode, 19, 16);
3827 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003828 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003829 wback = BitIsSet (opcode, 21);
3830
3831 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3832 if ((n == 15) || (BitCount (registers) < 2))
3833 return false;
3834
3835 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3836 if (wback && BitIsSet (registers, n))
3837 return false;
3838
3839 break;
3840
3841 case eEncodingA1:
3842 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3843 n = Bits32 (opcode, 19, 16);
3844 registers = Bits32 (opcode, 15, 0);
3845 wback = BitIsSet (opcode, 21);
3846
3847 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3848 if ((n == 15) || (BitCount (registers) < 1))
3849 return false;
3850
3851 break;
3852
3853 default:
3854 return false;
3855 }
3856
3857 // address = R[n];
3858 int32_t offset = 0;
3859 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3860 if (!success)
3861 return false;
3862
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003863 EmulateInstruction::Context context;
3864 context.type = EmulateInstruction::eContextRegisterStore;
3865 Register base_reg;
3866 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003867
3868 // for i = 0 to 14
3869 for (int i = 0; i < 14; ++i)
3870 {
3871 int lowest_set_bit = 14;
3872 // if registers<i> == ’1’ then
3873 if (BitIsSet (registers, i))
3874 {
3875 if (i < lowest_set_bit)
3876 lowest_set_bit = i;
3877 // if i == n && wback && i != LowestSetBit(registers) then
3878 if ((i == n) && wback && (i != lowest_set_bit))
3879 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3880 WriteBits32UnknownToMemory (address + offset);
3881 else
3882 {
3883 // MemA[address,4] = R[i];
3884 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3885 if (!success)
3886 return false;
3887
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003888 Register data_reg;
3889 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3890 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003891 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003892 return false;
3893 }
3894
3895 // address = address + 4;
3896 offset += addr_byte_size;
3897 }
3898 }
3899
3900 // if registers<15> == ’1’ then // Only possible for encoding A1
3901 // MemA[address,4] = PCStoreValue();
3902 if (BitIsSet (registers, 15))
3903 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003904 Register pc_reg;
3905 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3906 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003907 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3908 if (!success)
3909 return false;
3910
Caroline Ticecc96eb52011-02-17 19:20:40 +00003911 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003912 return false;
3913 }
3914
3915 // if wback then R[n] = R[n] + 4*BitCount(registers);
3916 if (wback)
3917 {
3918 offset = addr_byte_size * BitCount (registers);
3919 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003920 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003921 addr_t data = address + offset;
3922 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3923 return false;
3924 }
3925 }
3926 return true;
3927}
3928
Caroline Ticeaf556562011-02-15 18:42:15 +00003929// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3930// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3931// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003932bool
3933EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3934{
3935#if 0
3936 if ConditionPassed() then
3937 EncodingSpecificOperations();
3938 address = R[n] - 4*BitCount(registers) + 4;
3939
3940 for i = 0 to 14
3941 if registers<i> == ’1’ then
3942 if i == n && wback && i != LowestSetBit(registers) then
3943 MemA[address,4] = bits(32) UNKNOWN;
3944 else
3945 MemA[address,4] = R[i];
3946 address = address + 4;
3947
3948 if registers<15> == ’1’ then
3949 MemA[address,4] = PCStoreValue();
3950
3951 if wback then R[n] = R[n] - 4*BitCount(registers);
3952#endif
3953
3954 bool success = false;
3955 const uint32_t opcode = OpcodeAsUnsigned (&success);
3956 if (!success)
3957 return false;
3958
3959 if (ConditionPassed ())
3960 {
3961 uint32_t n;
3962 uint32_t registers = 0;
3963 bool wback;
3964 const uint32_t addr_byte_size = GetAddressByteSize();
3965
3966 // EncodingSpecificOperations();
3967 switch (encoding)
3968 {
3969 case eEncodingA1:
3970 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3971 n = Bits32 (opcode, 19, 16);
3972 registers = Bits32 (opcode, 15, 0);
3973 wback = BitIsSet (opcode, 21);
3974
3975 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3976 if ((n == 15) || (BitCount (registers) < 1))
3977 return false;
3978 break;
3979 default:
3980 return false;
3981 }
3982
3983 // address = R[n] - 4*BitCount(registers) + 4;
3984 int32_t offset = 0;
3985 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3986 if (!success)
3987 return false;
3988
3989 address = address - (addr_byte_size * BitCount (registers)) + 4;
3990
3991 EmulateInstruction::Context context;
3992 context.type = EmulateInstruction::eContextRegisterStore;
3993 Register base_reg;
3994 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3995
3996 // for i = 0 to 14
3997 for (int i = 0; i < 14; ++i)
3998 {
3999 int lowest_bit_set = 14;
4000 // if registers<i> == ’1’ then
4001 if (BitIsSet (registers, i))
4002 {
4003 if (i < lowest_bit_set)
4004 lowest_bit_set = i;
4005 //if i == n && wback && i != LowestSetBit(registers) then
4006 if ((i == n) && wback && (i != lowest_bit_set))
4007 // MemA[address,4] = bits(32) UNKNOWN;
4008 WriteBits32UnknownToMemory (address + offset);
4009 else
4010 {
4011 // MemA[address,4] = R[i];
4012 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4013 if (!success)
4014 return false;
4015
4016 Register data_reg;
4017 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4018 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004019 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004020 return false;
4021 }
4022
4023 // address = address + 4;
4024 offset += addr_byte_size;
4025 }
4026 }
4027
4028 // if registers<15> == ’1’ then
4029 // MemA[address,4] = PCStoreValue();
4030 if (BitIsSet (registers, 15))
4031 {
4032 Register pc_reg;
4033 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4034 context.SetRegisterPlusOffset (pc_reg, 8);
4035 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4036 if (!success)
4037 return false;
4038
Caroline Ticecc96eb52011-02-17 19:20:40 +00004039 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00004040 return false;
4041 }
4042
4043 // if wback then R[n] = R[n] - 4*BitCount(registers);
4044 if (wback)
4045 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004046 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00004047 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4048 context.SetImmediateSigned (offset);
4049 addr_t data = address + offset;
4050 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4051 return false;
4052 }
4053 }
4054 return true;
4055}
4056
Caroline Ticeaf556562011-02-15 18:42:15 +00004057// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
4058// from a base register. The consecutive memory locations end just below this address, and the address of the first of
4059// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004060bool
4061EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
4062{
4063#if 0
4064 if ConditionPassed() then
4065 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4066 address = R[n] - 4*BitCount(registers);
4067
4068 for i = 0 to 14
4069 if registers<i> == ’1’ then
4070 if i == n && wback && i != LowestSetBit(registers) then
4071 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4072 else
4073 MemA[address,4] = R[i];
4074 address = address + 4;
4075
4076 if registers<15> == ’1’ then // Only possible for encoding A1
4077 MemA[address,4] = PCStoreValue();
4078
4079 if wback then R[n] = R[n] - 4*BitCount(registers);
4080#endif
4081
4082
4083 bool success = false;
4084 const uint32_t opcode = OpcodeAsUnsigned (&success);
4085 if (!success)
4086 return false;
4087
4088 if (ConditionPassed ())
4089 {
4090 uint32_t n;
4091 uint32_t registers = 0;
4092 bool wback;
4093 const uint32_t addr_byte_size = GetAddressByteSize();
4094
4095 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4096 switch (encoding)
4097 {
4098 case eEncodingT1:
4099 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
4100 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
4101 {
4102 // See PUSH
4103 }
4104 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
4105 n = Bits32 (opcode, 19, 16);
4106 registers = Bits32 (opcode, 15, 0);
4107 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4108 wback = BitIsSet (opcode, 21);
4109 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4110 if ((n == 15) || BitCount (registers) < 2)
4111 return false;
4112 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
4113 if (wback && BitIsSet (registers, n))
4114 return false;
4115 break;
4116
4117 case eEncodingA1:
4118 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
4119 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
4120 {
4121 // See Push
4122 }
4123 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4124 n = Bits32 (opcode, 19, 16);
4125 registers = Bits32 (opcode, 15, 0);
4126 wback = BitIsSet (opcode, 21);
4127 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4128 if ((n == 15) || BitCount (registers) < 1)
4129 return false;
4130 break;
4131
4132 default:
4133 return false;
4134 }
4135
4136 // address = R[n] - 4*BitCount(registers);
4137
4138 int32_t offset = 0;
4139 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4140 if (!success)
4141 return false;
4142
4143 address = address - (addr_byte_size * BitCount (registers));
4144
4145 EmulateInstruction::Context context;
4146 context.type = EmulateInstruction::eContextRegisterStore;
4147 Register base_reg;
4148 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4149
4150 // for i = 0 to 14
4151 for (int i = 0; i < 14; ++i)
4152 {
4153 uint32_t lowest_set_bit = 14;
4154 // if registers<i> == ’1’ then
4155 if (BitIsSet (registers, i))
4156 {
4157 if (i < lowest_set_bit)
4158 lowest_set_bit = i;
4159 // if i == n && wback && i != LowestSetBit(registers) then
4160 if ((i == n) && wback && (i != lowest_set_bit))
4161 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4162 WriteBits32UnknownToMemory (address + offset);
4163 else
4164 {
4165 // MemA[address,4] = R[i];
4166 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4167 if (!success)
4168 return false;
4169
4170 Register data_reg;
4171 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4172 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004173 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004174 return false;
4175 }
4176
4177 // address = address + 4;
4178 offset += addr_byte_size;
4179 }
4180 }
4181
4182 // if registers<15> == ’1’ then // Only possible for encoding A1
4183 // MemA[address,4] = PCStoreValue();
4184 if (BitIsSet (registers, 15))
4185 {
4186 Register pc_reg;
4187 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4188 context.SetRegisterPlusOffset (pc_reg, 8);
4189 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4190 if (!success)
4191 return false;
4192
Caroline Ticecc96eb52011-02-17 19:20:40 +00004193 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004194 return false;
4195 }
4196
4197 // if wback then R[n] = R[n] - 4*BitCount(registers);
4198 if (wback)
4199 {
Caroline Ticeaf556562011-02-15 18:42:15 +00004200 offset = (addr_byte_size * BitCount (registers)) * -1;
4201 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4202 context.SetImmediateSigned (offset);
4203 addr_t data = address + offset;
4204 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4205 return false;
4206 }
4207 }
4208 return true;
4209}
4210
4211// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
4212// from a base register. The consecutive memory locations start just above this address, and the address of the last
4213// of those locations can optionally be written back to the base register.
4214bool
4215EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
4216{
4217#if 0
4218 if ConditionPassed() then
4219 EncodingSpecificOperations();
4220 address = R[n] + 4;
4221
4222 for i = 0 to 14
4223 if registers<i> == ’1’ then
4224 if i == n && wback && i != LowestSetBit(registers) then
4225 MemA[address,4] = bits(32) UNKNOWN;
4226 else
4227 MemA[address,4] = R[i];
4228 address = address + 4;
4229
4230 if registers<15> == ’1’ then
4231 MemA[address,4] = PCStoreValue();
4232
4233 if wback then R[n] = R[n] + 4*BitCount(registers);
4234#endif
4235
4236 bool success = false;
4237 const uint32_t opcode = OpcodeAsUnsigned (&success);
4238 if (!success)
4239 return false;
4240
4241 if (ConditionPassed())
4242 {
4243 uint32_t n;
4244 uint32_t registers = 0;
4245 bool wback;
4246 const uint32_t addr_byte_size = GetAddressByteSize();
4247
4248 // EncodingSpecificOperations();
4249 switch (encoding)
4250 {
4251 case eEncodingA1:
4252 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4253 n = Bits32 (opcode, 19, 16);
4254 registers = Bits32 (opcode, 15, 0);
4255 wback = BitIsSet (opcode, 21);
4256
4257 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4258 if ((n == 15) && (BitCount (registers) < 1))
4259 return false;
4260 break;
4261 default:
4262 return false;
4263 }
4264 // address = R[n] + 4;
4265
4266 int32_t offset = 0;
4267 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4268 if (!success)
4269 return false;
4270
4271 address = address + addr_byte_size;
4272
4273 EmulateInstruction::Context context;
4274 context.type = EmulateInstruction::eContextRegisterStore;
4275 Register base_reg;
4276 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4277
4278 uint32_t lowest_set_bit = 14;
4279 // for i = 0 to 14
4280 for (int i = 0; i < 14; ++i)
4281 {
4282 // if registers<i> == ’1’ then
4283 if (BitIsSet (registers, i))
4284 {
4285 if (i < lowest_set_bit)
4286 lowest_set_bit = i;
4287 // if i == n && wback && i != LowestSetBit(registers) then
4288 if ((i == n) && wback && (i != lowest_set_bit))
4289 // MemA[address,4] = bits(32) UNKNOWN;
4290 WriteBits32UnknownToMemory (address + offset);
4291 // else
4292 else
4293 {
4294 // MemA[address,4] = R[i];
4295 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4296 if (!success)
4297 return false;
4298
4299 Register data_reg;
4300 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4301 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004302 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004303 return false;
4304 }
4305
4306 // address = address + 4;
4307 offset += addr_byte_size;
4308 }
4309 }
4310
4311 // if registers<15> == ’1’ then
4312 // MemA[address,4] = PCStoreValue();
4313 if (BitIsSet (registers, 15))
4314 {
4315 Register pc_reg;
4316 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4317 context.SetRegisterPlusOffset (pc_reg, 8);
4318 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4319 if (!success)
4320 return false;
4321
Caroline Ticecc96eb52011-02-17 19:20:40 +00004322 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004323 return false;
4324 }
4325
4326 // if wback then R[n] = R[n] + 4*BitCount(registers);
4327 if (wback)
4328 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004329 offset = addr_byte_size * BitCount (registers);
4330 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4331 context.SetImmediateSigned (offset);
4332 addr_t data = address + offset;
4333 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4334 return false;
4335 }
4336 }
4337 return true;
4338}
Caroline Tice7fac8572011-02-15 22:53:54 +00004339
4340// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4341// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4342bool
4343EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4344{
4345#if 0
4346 if ConditionPassed() then
4347 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4348 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4349 address = if index then offset_addr else R[n];
4350 if UnalignedSupport() || address<1:0> == ’00’ then
4351 MemU[address,4] = R[t];
4352 else // Can only occur before ARMv7
4353 MemU[address,4] = bits(32) UNKNOWN;
4354 if wback then R[n] = offset_addr;
4355#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004356
Caroline Tice7fac8572011-02-15 22:53:54 +00004357 bool success = false;
4358 const uint32_t opcode = OpcodeAsUnsigned (&success);
4359 if (!success)
4360 return false;
4361
4362 if (ConditionPassed())
4363 {
4364 const uint32_t addr_byte_size = GetAddressByteSize();
4365
4366 uint32_t t;
4367 uint32_t n;
4368 uint32_t imm32;
4369 bool index;
4370 bool add;
4371 bool wback;
4372 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4373 switch (encoding)
4374 {
4375 case eEncodingT1:
4376 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4377 t = Bits32 (opcode, 2, 0);
4378 n = Bits32 (opcode, 5, 3);
4379 imm32 = Bits32 (opcode, 10, 6) << 2;
4380
4381 // index = TRUE; add = TRUE; wback = FALSE;
4382 index = true;
4383 add = false;
4384 wback = false;
4385 break;
4386
4387 case eEncodingT2:
4388 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4389 t = Bits32 (opcode, 10, 8);
4390 n = 13;
4391 imm32 = Bits32 (opcode, 7, 0) << 2;
4392
4393 // index = TRUE; add = TRUE; wback = FALSE;
4394 index = true;
4395 add = true;
4396 wback = false;
4397 break;
4398
4399 case eEncodingT3:
4400 // if Rn == ’1111’ then UNDEFINED;
4401 if (Bits32 (opcode, 19, 16) == 15)
4402 return false;
4403
4404 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4405 t = Bits32 (opcode, 15, 12);
4406 n = Bits32 (opcode, 19, 16);
4407 imm32 = Bits32 (opcode, 11, 0);
4408
4409 // index = TRUE; add = TRUE; wback = FALSE;
4410 index = true;
4411 add = true;
4412 wback = false;
4413
4414 // if t == 15 then UNPREDICTABLE;
4415 if (t == 15)
4416 return false;
4417 break;
4418
4419 case eEncodingT4:
4420 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4421 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4422 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4423 if ((Bits32 (opcode, 19, 16) == 15)
4424 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4425 return false;
4426
4427 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4428 t = Bits32 (opcode, 15, 12);
4429 n = Bits32 (opcode, 19, 16);
4430 imm32 = Bits32 (opcode, 7, 0);
4431
4432 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4433 index = BitIsSet (opcode, 10);
4434 add = BitIsSet (opcode, 9);
4435 wback = BitIsSet (opcode, 8);
4436
4437 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4438 if ((t == 15) || (wback && (n == t)))
4439 return false;
4440 break;
4441
4442 default:
4443 return false;
4444 }
4445
4446 addr_t offset_addr;
4447 addr_t address;
4448
4449 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4450 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4451 if (!success)
4452 return false;
4453
4454 if (add)
4455 offset_addr = base_address + imm32;
4456 else
4457 offset_addr = base_address - imm32;
4458
4459 // address = if index then offset_addr else R[n];
4460 if (index)
4461 address = offset_addr;
4462 else
4463 address = base_address;
4464
4465 EmulateInstruction::Context context;
4466 context.type = eContextRegisterStore;
4467 Register base_reg;
4468 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4469
4470 // if UnalignedSupport() || address<1:0> == ’00’ then
4471 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4472 {
4473 // MemU[address,4] = R[t];
4474 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4475 if (!success)
4476 return false;
4477
4478 Register data_reg;
4479 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4480 int32_t offset = address - base_address;
4481 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004482 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004483 return false;
4484 }
4485 else
4486 {
4487 // MemU[address,4] = bits(32) UNKNOWN;
4488 WriteBits32UnknownToMemory (address);
4489 }
4490
4491 // if wback then R[n] = offset_addr;
4492 if (wback)
4493 {
4494 context.type = eContextRegisterLoad;
4495 context.SetAddress (offset_addr);
4496 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4497 return false;
4498 }
4499 }
4500 return true;
4501}
Caroline Ticeaf556562011-02-15 18:42:15 +00004502
Caroline Tice3fd63e92011-02-16 00:33:43 +00004503// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4504// word from a register to memory. The offset register value can optionally be shifted.
4505bool
4506EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4507{
4508#if 0
4509 if ConditionPassed() then
4510 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4511 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4512 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4513 address = if index then offset_addr else R[n];
4514 if t == 15 then // Only possible for encoding A1
4515 data = PCStoreValue();
4516 else
4517 data = R[t];
4518 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4519 MemU[address,4] = data;
4520 else // Can only occur before ARMv7
4521 MemU[address,4] = bits(32) UNKNOWN;
4522 if wback then R[n] = offset_addr;
4523#endif
4524
4525 bool success = false;
4526 const uint32_t opcode = OpcodeAsUnsigned (&success);
4527 if (!success)
4528 return false;
4529
4530 if (ConditionPassed())
4531 {
4532 const uint32_t addr_byte_size = GetAddressByteSize();
4533
4534 uint32_t t;
4535 uint32_t n;
4536 uint32_t m;
4537 ARM_ShifterType shift_t;
4538 uint32_t shift_n;
4539 bool index;
4540 bool add;
4541 bool wback;
4542
4543 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4544 switch (encoding)
4545 {
4546 case eEncodingT1:
4547 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4548 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4549 t = Bits32 (opcode, 2, 0);
4550 n = Bits32 (opcode, 5, 3);
4551 m = Bits32 (opcode, 8, 6);
4552
4553 // index = TRUE; add = TRUE; wback = FALSE;
4554 index = true;
4555 add = true;
4556 wback = false;
4557
4558 // (shift_t, shift_n) = (SRType_LSL, 0);
4559 shift_t = SRType_LSL;
4560 shift_n = 0;
4561 break;
4562
4563 case eEncodingT2:
4564 // if Rn == ’1111’ then UNDEFINED;
4565 if (Bits32 (opcode, 19, 16) == 15)
4566 return false;
4567
4568 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4569 t = Bits32 (opcode, 15, 12);
4570 n = Bits32 (opcode, 19, 16);
4571 m = Bits32 (opcode, 3, 0);
4572
4573 // index = TRUE; add = TRUE; wback = FALSE;
4574 index = true;
4575 add = true;
4576 wback = false;
4577
4578 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4579 shift_t = SRType_LSL;
4580 shift_n = Bits32 (opcode, 5, 4);
4581
4582 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4583 if ((t == 15) || (BadReg (m)))
4584 return false;
4585 break;
4586
4587 case eEncodingA1:
4588 {
4589 // if P == ’0’ && W == ’1’ then SEE STRT;
4590 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4591 t = Bits32 (opcode, 15, 12);
4592 n = Bits32 (opcode, 19, 16);
4593 m = Bits32 (opcode, 3, 0);
4594
4595 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4596 index = BitIsSet (opcode, 24);
4597 add = BitIsSet (opcode, 23);
4598 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4599
4600 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4601 uint32_t typ = Bits32 (opcode, 6, 5);
4602 uint32_t imm5 = Bits32 (opcode, 11, 7);
4603 shift_n = DecodeImmShift(typ, imm5, shift_t);
4604
4605 // if m == 15 then UNPREDICTABLE;
4606 if (m == 15)
4607 return false;
4608
4609 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4610 if (wback && ((n == 15) || (n == t)))
4611 return false;
4612
4613 break;
4614 }
4615 default:
4616 return false;
4617 }
4618
4619 addr_t offset_addr;
4620 addr_t address;
4621 int32_t offset = 0;
4622
4623 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4624 if (!success)
4625 return false;
4626
4627 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4628 if (!success)
4629 return false;
4630
4631 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004632 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004633
4634 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4635 if (add)
4636 offset_addr = base_address + offset;
4637 else
4638 offset_addr = base_address - offset;
4639
4640 // address = if index then offset_addr else R[n];
4641 if (index)
4642 address = offset_addr;
4643 else
4644 address = base_address;
4645
4646 uint32_t data;
4647 // if t == 15 then // Only possible for encoding A1
4648 if (t == 15)
4649 // data = PCStoreValue();
4650 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4651 else
4652 // data = R[t];
4653 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4654
4655 if (!success)
4656 return false;
4657
4658 EmulateInstruction::Context context;
4659 context.type = eContextRegisterStore;
4660
4661 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4662 if (UnalignedSupport ()
4663 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4664 || CurrentInstrSet() == eModeARM)
4665 {
4666 // MemU[address,4] = data;
4667
4668 Register base_reg;
4669 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4670
4671 Register data_reg;
4672 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4673
4674 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004675 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004676 return false;
4677
4678 }
4679 else
4680 // MemU[address,4] = bits(32) UNKNOWN;
4681 WriteBits32UnknownToMemory (address);
4682
4683 // if wback then R[n] = offset_addr;
4684 if (wback)
4685 {
4686 context.type = eContextRegisterLoad;
4687 context.SetAddress (offset_addr);
4688 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4689 return false;
4690 }
4691
4692 }
4693 return true;
4694}
Caroline Tice73a29de2011-02-16 20:22:22 +00004695
4696bool
4697EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4698{
4699#if 0
4700 if ConditionPassed() then
4701 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4702 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4703 address = if index then offset_addr else R[n];
4704 MemU[address,1] = R[t]<7:0>;
4705 if wback then R[n] = offset_addr;
4706#endif
4707
4708
4709 bool success = false;
4710 const uint32_t opcode = OpcodeAsUnsigned (&success);
4711 if (!success)
4712 return false;
4713
4714 if (ConditionPassed ())
4715 {
4716 uint32_t t;
4717 uint32_t n;
4718 uint32_t imm32;
4719 bool index;
4720 bool add;
4721 bool wback;
4722 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4723 switch (encoding)
4724 {
4725 case eEncodingT1:
4726 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4727 t = Bits32 (opcode, 2, 0);
4728 n = Bits32 (opcode, 5, 3);
4729 imm32 = Bits32 (opcode, 10, 6);
4730
4731 // index = TRUE; add = TRUE; wback = FALSE;
4732 index = true;
4733 add = true;
4734 wback = false;
4735 break;
4736
4737 case eEncodingT2:
4738 // if Rn == ’1111’ then UNDEFINED;
4739 if (Bits32 (opcode, 19, 16) == 15)
4740 return false;
4741
4742 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4743 t = Bits32 (opcode, 15, 12);
4744 n = Bits32 (opcode, 19, 16);
4745 imm32 = Bits32 (opcode, 11, 0);
4746
4747 // index = TRUE; add = TRUE; wback = FALSE;
4748 index = true;
4749 add = true;
4750 wback = false;
4751
4752 // if BadReg(t) then UNPREDICTABLE;
4753 if (BadReg (t))
4754 return false;
4755 break;
4756
4757 case eEncodingT3:
4758 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4759 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4760 if (Bits32 (opcode, 19, 16) == 15)
4761 return false;
4762
4763 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4764 t = Bits32 (opcode, 15, 12);
4765 n = Bits32 (opcode, 19, 16);
4766 imm32 = Bits32 (opcode, 7, 0);
4767
4768 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4769 index = BitIsSet (opcode, 10);
4770 add = BitIsSet (opcode, 9);
4771 wback = BitIsSet (opcode, 8);
4772
4773 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4774 if ((BadReg (t)) || (wback && (n == t)))
4775 return false;
4776 break;
4777
4778 default:
4779 return false;
4780 }
4781
4782 addr_t offset_addr;
4783 addr_t address;
4784 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4785 if (!success)
4786 return false;
4787
4788 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4789 if (add)
4790 offset_addr = base_address + imm32;
4791 else
4792 offset_addr = base_address - imm32;
4793
4794 // address = if index then offset_addr else R[n];
4795 if (index)
4796 address = offset_addr;
4797 else
4798 address = base_address;
4799
Caroline Ticecc96eb52011-02-17 19:20:40 +00004800 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004801 Register base_reg;
4802 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4803
4804 Register data_reg;
4805 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4806
4807 EmulateInstruction::Context context;
4808 context.type = eContextRegisterStore;
4809 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4810
4811 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4812 if (!success)
4813 return false;
4814
4815 data = Bits32 (data, 7, 0);
4816
Caroline Ticecc96eb52011-02-17 19:20:40 +00004817 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004818 return false;
4819
4820 // if wback then R[n] = offset_addr;
4821 if (wback)
4822 {
4823 context.type = eContextRegisterLoad;
4824 context.SetAddress (offset_addr);
4825 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4826 return false;
4827 }
4828
4829 }
4830
4831 return true;
4832}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004833
Johnny Chen157b9592011-02-18 21:13:05 +00004834// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4835// and writes the result to the destination register. It can optionally update the condition flags
4836// based on the result.
4837bool
4838EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4839{
4840#if 0
4841 // ARM pseudo code...
4842 if ConditionPassed() then
4843 EncodingSpecificOperations();
4844 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4845 if d == 15 then // Can only occur for ARM encoding
4846 ALUWritePC(result); // setflags is always FALSE here
4847 else
4848 R[d] = result;
4849 if setflags then
4850 APSR.N = result<31>;
4851 APSR.Z = IsZeroBit(result);
4852 APSR.C = carry;
4853 APSR.V = overflow;
4854#endif
4855
4856 bool success = false;
4857 const uint32_t opcode = OpcodeAsUnsigned (&success);
4858 if (!success)
4859 return false;
4860
4861 if (ConditionPassed())
4862 {
4863 uint32_t Rd, Rn;
4864 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4865 bool setflags;
4866 switch (encoding)
4867 {
4868 case eEncodingT1:
4869 Rd = Bits32(opcode, 11, 8);
4870 Rn = Bits32(opcode, 19, 16);
4871 setflags = BitIsSet(opcode, 20);
4872 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4873 if (BadReg(Rd) || BadReg(Rn))
4874 return false;
4875 break;
4876 case eEncodingA1:
4877 Rd = Bits32(opcode, 15, 12);
4878 Rn = Bits32(opcode, 19, 16);
4879 setflags = BitIsSet(opcode, 20);
4880 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4881 // TODO: Emulate SUBS PC, LR and related instructions.
4882 if (Rd == 15 && setflags)
4883 return false;
4884 break;
4885 default:
4886 return false;
4887 }
4888
4889 // Read the first operand.
4890 int32_t val1 = ReadCoreReg(Rn, &success);
4891 if (!success)
4892 return false;
4893
4894 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4895
4896 EmulateInstruction::Context context;
4897 context.type = EmulateInstruction::eContextImmediate;
4898 context.SetNoArgs ();
4899
4900 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4901 return false;
4902 }
4903 return true;
4904}
4905
4906// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4907// register value, and writes the result to the destination register. It can optionally update the
4908// condition flags based on the result.
4909bool
4910EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4911{
4912#if 0
4913 // ARM pseudo code...
4914 if ConditionPassed() then
4915 EncodingSpecificOperations();
4916 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4917 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4918 if d == 15 then // Can only occur for ARM encoding
4919 ALUWritePC(result); // setflags is always FALSE here
4920 else
4921 R[d] = result;
4922 if setflags then
4923 APSR.N = result<31>;
4924 APSR.Z = IsZeroBit(result);
4925 APSR.C = carry;
4926 APSR.V = overflow;
4927#endif
4928
4929 bool success = false;
4930 const uint32_t opcode = OpcodeAsUnsigned (&success);
4931 if (!success)
4932 return false;
4933
4934 if (ConditionPassed())
4935 {
4936 uint32_t Rd, Rn, Rm;
4937 ARM_ShifterType shift_t;
4938 uint32_t shift_n; // the shift applied to the value read from Rm
4939 bool setflags;
4940 switch (encoding)
4941 {
4942 case eEncodingT1:
4943 Rd = Rn = Bits32(opcode, 2, 0);
4944 Rm = Bits32(opcode, 5, 3);
4945 setflags = !InITBlock();
4946 shift_t = SRType_LSL;
4947 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004948 break;
Johnny Chen157b9592011-02-18 21:13:05 +00004949 case eEncodingT2:
4950 Rd = Bits32(opcode, 11, 8);
4951 Rn = Bits32(opcode, 19, 16);
4952 Rm = Bits32(opcode, 3, 0);
4953 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004954 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004955 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4956 return false;
4957 break;
4958 case eEncodingA1:
4959 Rd = Bits32(opcode, 15, 12);
4960 Rn = Bits32(opcode, 19, 16);
4961 Rm = Bits32(opcode, 3, 0);
4962 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004963 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004964 // TODO: Emulate SUBS PC, LR and related instructions.
4965 if (Rd == 15 && setflags)
4966 return false;
4967 break;
4968 default:
4969 return false;
4970 }
4971
4972 // Read the first operand.
4973 int32_t val1 = ReadCoreReg(Rn, &success);
4974 if (!success)
4975 return false;
4976
4977 // Read the second operand.
4978 int32_t val2 = ReadCoreReg(Rm, &success);
4979 if (!success)
4980 return false;
4981
4982 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4983 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4984
4985 EmulateInstruction::Context context;
4986 context.type = EmulateInstruction::eContextImmediate;
4987 context.SetNoArgs ();
4988
4989 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4990 return false;
4991 }
4992 return true;
4993}
4994
Johnny Chena695f952011-02-23 21:24:25 +00004995// This instruction adds an immediate value to the PC value to form a PC-relative address,
4996// and writes the result to the destination register.
4997bool
4998EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
4999{
5000#if 0
5001 // ARM pseudo code...
5002 if ConditionPassed() then
5003 EncodingSpecificOperations();
5004 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5005 if d == 15 then // Can only occur for ARM encodings
5006 ALUWritePC(result);
5007 else
5008 R[d] = result;
5009#endif
5010
5011 bool success = false;
5012 const uint32_t opcode = OpcodeAsUnsigned (&success);
5013 if (!success)
5014 return false;
5015
5016 if (ConditionPassed())
5017 {
5018 uint32_t Rd;
5019 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5020 bool add;
5021 switch (encoding)
5022 {
5023 case eEncodingT1:
5024 Rd = Bits32(opcode, 10, 8);
5025 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5026 break;
5027 case eEncodingT2:
5028 case eEncodingT3:
5029 Rd = Bits32(opcode, 11, 8);
5030 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5031 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5032 if (BadReg(Rd))
5033 return false;
5034 break;
5035 case eEncodingA1:
5036 case eEncodingA2:
5037 Rd = Bits32(opcode, 15, 12);
5038 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5039 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5040 break;
5041 default:
5042 return false;
5043 }
5044
5045 // Read the PC value.
5046 uint32_t pc = ReadCoreReg(PC_REG, &success);
5047 if (!success)
5048 return false;
5049
5050 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5051
5052 EmulateInstruction::Context context;
5053 context.type = EmulateInstruction::eContextImmediate;
5054 context.SetNoArgs ();
5055
5056 if (!WriteCoreReg(context, result, Rd))
5057 return false;
5058 }
5059 return true;
5060}
5061
Johnny Chene97c0d52011-02-18 19:32:20 +00005062// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
5063// to the destination register. It can optionally update the condition flags based on the result.
5064bool
5065EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
5066{
5067#if 0
5068 // ARM pseudo code...
5069 if ConditionPassed() then
5070 EncodingSpecificOperations();
5071 result = R[n] AND imm32;
5072 if d == 15 then // Can only occur for ARM encoding
5073 ALUWritePC(result); // setflags is always FALSE here
5074 else
5075 R[d] = result;
5076 if setflags then
5077 APSR.N = result<31>;
5078 APSR.Z = IsZeroBit(result);
5079 APSR.C = carry;
5080 // APSR.V unchanged
5081#endif
5082
5083 bool success = false;
5084 const uint32_t opcode = OpcodeAsUnsigned (&success);
5085 if (!success)
5086 return false;
5087
5088 if (ConditionPassed())
5089 {
5090 uint32_t Rd, Rn;
5091 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
5092 bool setflags;
5093 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5094 switch (encoding)
5095 {
5096 case eEncodingT1:
5097 Rd = Bits32(opcode, 11, 8);
5098 Rn = Bits32(opcode, 19, 16);
5099 setflags = BitIsSet(opcode, 20);
5100 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00005101 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00005102 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005103 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00005104 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
5105 return false;
5106 break;
5107 case eEncodingA1:
5108 Rd = Bits32(opcode, 15, 12);
5109 Rn = Bits32(opcode, 19, 16);
5110 setflags = BitIsSet(opcode, 20);
5111 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5112 // TODO: Emulate SUBS PC, LR and related instructions.
5113 if (Rd == 15 && setflags)
5114 return false;
5115 break;
5116 default:
5117 return false;
5118 }
5119
Johnny Chene97c0d52011-02-18 19:32:20 +00005120 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005121 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005122 if (!success)
5123 return false;
5124
5125 uint32_t result = val1 & imm32;
5126
5127 EmulateInstruction::Context context;
5128 context.type = EmulateInstruction::eContextImmediate;
5129 context.SetNoArgs ();
5130
5131 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5132 return false;
5133 }
5134 return true;
5135}
5136
5137// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
5138// and writes the result to the destination register. It can optionally update the condition flags
5139// based on the result.
5140bool
5141EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
5142{
5143#if 0
5144 // ARM pseudo code...
5145 if ConditionPassed() then
5146 EncodingSpecificOperations();
5147 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5148 result = R[n] AND shifted;
5149 if d == 15 then // Can only occur for ARM encoding
5150 ALUWritePC(result); // setflags is always FALSE here
5151 else
5152 R[d] = result;
5153 if setflags then
5154 APSR.N = result<31>;
5155 APSR.Z = IsZeroBit(result);
5156 APSR.C = carry;
5157 // APSR.V unchanged
5158#endif
5159
5160 bool success = false;
5161 const uint32_t opcode = OpcodeAsUnsigned (&success);
5162 if (!success)
5163 return false;
5164
5165 if (ConditionPassed())
5166 {
5167 uint32_t Rd, Rn, Rm;
5168 ARM_ShifterType shift_t;
5169 uint32_t shift_n; // the shift applied to the value read from Rm
5170 bool setflags;
5171 uint32_t carry;
5172 switch (encoding)
5173 {
5174 case eEncodingT1:
5175 Rd = Rn = Bits32(opcode, 2, 0);
5176 Rm = Bits32(opcode, 5, 3);
5177 setflags = !InITBlock();
5178 shift_t = SRType_LSL;
5179 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00005180 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00005181 case eEncodingT2:
5182 Rd = Bits32(opcode, 11, 8);
5183 Rn = Bits32(opcode, 19, 16);
5184 Rm = Bits32(opcode, 3, 0);
5185 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005186 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00005187 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00005188 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00005189 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00005190 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
5191 return false;
5192 break;
5193 case eEncodingA1:
5194 Rd = Bits32(opcode, 15, 12);
5195 Rn = Bits32(opcode, 19, 16);
5196 Rm = Bits32(opcode, 3, 0);
5197 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00005198 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00005199 // TODO: Emulate SUBS PC, LR and related instructions.
5200 if (Rd == 15 && setflags)
5201 return false;
5202 break;
5203 default:
5204 return false;
5205 }
5206
Johnny Chene97c0d52011-02-18 19:32:20 +00005207 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005208 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005209 if (!success)
5210 return false;
5211
5212 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00005213 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00005214 if (!success)
5215 return false;
5216
5217 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5218 uint32_t result = val1 & shifted;
5219
5220 EmulateInstruction::Context context;
5221 context.type = EmulateInstruction::eContextImmediate;
5222 context.SetNoArgs ();
5223
5224 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5225 return false;
5226 }
5227 return true;
5228}
5229
Johnny Chenb9f02cf2011-02-24 01:15:17 +00005230// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
5231// immediate value, and writes the result to the destination register. It can optionally update the
5232// condition flags based on the result.
5233bool
5234EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
5235{
5236#if 0
5237 // ARM pseudo code...
5238 if ConditionPassed() then
5239 EncodingSpecificOperations();
5240 result = R[n] AND NOT(imm32);
5241 if d == 15 then // Can only occur for ARM encoding
5242 ALUWritePC(result); // setflags is always FALSE here
5243 else
5244 R[d] = result;
5245 if setflags then
5246 APSR.N = result<31>;
5247 APSR.Z = IsZeroBit(result);
5248 APSR.C = carry;
5249 // APSR.V unchanged
5250#endif
5251
5252 bool success = false;
5253 const uint32_t opcode = OpcodeAsUnsigned (&success);
5254 if (!success)
5255 return false;
5256
5257 if (ConditionPassed())
5258 {
5259 uint32_t Rd, Rn;
5260 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5261 bool setflags;
5262 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5263 switch (encoding)
5264 {
5265 case eEncodingT1:
5266 Rd = Bits32(opcode, 11, 8);
5267 Rn = Bits32(opcode, 19, 16);
5268 setflags = BitIsSet(opcode, 20);
5269 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5270 if (BadReg(Rd) || BadReg(Rn))
5271 return false;
5272 break;
5273 case eEncodingA1:
5274 Rd = Bits32(opcode, 15, 12);
5275 Rn = Bits32(opcode, 19, 16);
5276 setflags = BitIsSet(opcode, 20);
5277 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5278 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5279 // TODO: Emulate SUBS PC, LR and related instructions.
5280 if (Rd == 15 && setflags)
5281 return false;
5282 break;
5283 default:
5284 return false;
5285 }
5286
5287 // Read the first operand.
5288 uint32_t val1 = ReadCoreReg(Rn, &success);
5289 if (!success)
5290 return false;
5291
5292 uint32_t result = val1 & ~imm32;
5293
5294 EmulateInstruction::Context context;
5295 context.type = EmulateInstruction::eContextImmediate;
5296 context.SetNoArgs ();
5297
5298 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5299 return false;
5300 }
5301 return true;
5302}
5303
5304// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5305// optionally-shifted register value, and writes the result to the destination register.
5306// It can optionally update the condition flags based on the result.
5307bool
5308EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5309{
5310#if 0
5311 // ARM pseudo code...
5312 if ConditionPassed() then
5313 EncodingSpecificOperations();
5314 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5315 result = R[n] AND NOT(shifted);
5316 if d == 15 then // Can only occur for ARM encoding
5317 ALUWritePC(result); // setflags is always FALSE here
5318 else
5319 R[d] = result;
5320 if setflags then
5321 APSR.N = result<31>;
5322 APSR.Z = IsZeroBit(result);
5323 APSR.C = carry;
5324 // APSR.V unchanged
5325#endif
5326
5327 bool success = false;
5328 const uint32_t opcode = OpcodeAsUnsigned (&success);
5329 if (!success)
5330 return false;
5331
5332 if (ConditionPassed())
5333 {
5334 uint32_t Rd, Rn, Rm;
5335 ARM_ShifterType shift_t;
5336 uint32_t shift_n; // the shift applied to the value read from Rm
5337 bool setflags;
5338 uint32_t carry;
5339 switch (encoding)
5340 {
5341 case eEncodingT1:
5342 Rd = Rn = Bits32(opcode, 2, 0);
5343 Rm = Bits32(opcode, 5, 3);
5344 setflags = !InITBlock();
5345 shift_t = SRType_LSL;
5346 shift_n = 0;
5347 break;
5348 case eEncodingT2:
5349 Rd = Bits32(opcode, 11, 8);
5350 Rn = Bits32(opcode, 19, 16);
5351 Rm = Bits32(opcode, 3, 0);
5352 setflags = BitIsSet(opcode, 20);
5353 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5354 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5355 return false;
5356 break;
5357 case eEncodingA1:
5358 Rd = Bits32(opcode, 15, 12);
5359 Rn = Bits32(opcode, 19, 16);
5360 Rm = Bits32(opcode, 3, 0);
5361 setflags = BitIsSet(opcode, 20);
5362 shift_n = DecodeImmShiftARM(opcode, shift_t);
5363 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5364 // TODO: Emulate SUBS PC, LR and related instructions.
5365 if (Rd == 15 && setflags)
5366 return false;
5367 break;
5368 default:
5369 return false;
5370 }
5371
5372 // Read the first operand.
5373 uint32_t val1 = ReadCoreReg(Rn, &success);
5374 if (!success)
5375 return false;
5376
5377 // Read the second operand.
5378 uint32_t val2 = ReadCoreReg(Rm, &success);
5379 if (!success)
5380 return false;
5381
5382 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5383 uint32_t result = val1 & ~shifted;
5384
5385 EmulateInstruction::Context context;
5386 context.type = EmulateInstruction::eContextImmediate;
5387 context.SetNoArgs ();
5388
5389 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5390 return false;
5391 }
5392 return true;
5393}
5394
Caroline Tice4d729c52011-02-18 00:55:53 +00005395// 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 +00005396// 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 +00005397bool
5398EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5399{
5400#if 0
5401 if ConditionPassed() then
5402 EncodingSpecificOperations();
5403 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5404 address = if index then offset_addr else R[n];
5405 data = MemU[address,4];
5406 if wback then R[n] = offset_addr;
5407 if t == 15 then
5408 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5409 elsif UnalignedSupport() || address<1:0> = ’00’ then
5410 R[t] = data;
5411 else // Can only apply before ARMv7
5412 R[t] = ROR(data, 8*UInt(address<1:0>));
5413#endif
5414
5415 bool success = false;
5416 const uint32_t opcode = OpcodeAsUnsigned (&success);
5417 if (!success)
5418 return false;
5419
5420 if (ConditionPassed ())
5421 {
5422 const uint32_t addr_byte_size = GetAddressByteSize();
5423
5424 uint32_t t;
5425 uint32_t n;
5426 uint32_t imm32;
5427 bool index;
5428 bool add;
5429 bool wback;
5430
5431 switch (encoding)
5432 {
5433 case eEncodingA1:
5434 // if Rn == ’1111’ then SEE LDR (literal);
5435 // if P == ’0’ && W == ’1’ then SEE LDRT;
5436 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5437 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5438 t = Bits32 (opcode, 15, 12);
5439 n = Bits32 (opcode, 19, 16);
5440 imm32 = Bits32 (opcode, 11, 0);
5441
5442 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5443 index = BitIsSet (opcode, 24);
5444 add = BitIsSet (opcode, 23);
5445 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5446
5447 // if wback && n == t then UNPREDICTABLE;
5448 if (wback && (n == t))
5449 return false;
5450
5451 break;
5452
5453 default:
5454 return false;
5455 }
5456
5457 addr_t address;
5458 addr_t offset_addr;
5459 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5460 if (!success)
5461 return false;
5462
5463 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5464 if (add)
5465 offset_addr = base_address + imm32;
5466 else
5467 offset_addr = base_address - imm32;
5468
5469 // address = if index then offset_addr else R[n];
5470 if (index)
5471 address = offset_addr;
5472 else
5473 address = base_address;
5474
5475 // data = MemU[address,4];
5476
5477 Register base_reg;
5478 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5479
5480 EmulateInstruction::Context context;
5481 context.type = eContextRegisterLoad;
5482 context.SetRegisterPlusOffset (base_reg, address - base_address);
5483
5484 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5485 if (!success)
5486 return false;
5487
5488 // if wback then R[n] = offset_addr;
5489 if (wback)
5490 {
5491 context.type = eContextAdjustBaseRegister;
5492 context.SetAddress (offset_addr);
5493 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5494 return false;
5495 }
5496
5497 // if t == 15 then
5498 if (t == 15)
5499 {
5500 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5501 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5502 {
5503 // LoadWritePC (data);
5504 context.type = eContextRegisterLoad;
5505 context.SetRegisterPlusOffset (base_reg, address - base_address);
5506 LoadWritePC (context, data);
5507 }
5508 else
5509 return false;
5510 }
5511 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5512 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5513 {
5514 // R[t] = data;
5515 context.type = eContextRegisterLoad;
5516 context.SetRegisterPlusOffset (base_reg, address - base_address);
5517 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5518 return false;
5519 }
5520 // else // Can only apply before ARMv7
5521 else
5522 {
5523 // R[t] = ROR(data, 8*UInt(address<1:0>));
5524 data = ROR (data, Bits32 (address, 1, 0));
5525 context.type = eContextRegisterLoad;
5526 context.SetImmediate (data);
5527 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5528 return false;
5529 }
5530
5531 }
5532 return true;
5533}
5534
Caroline Ticefe479112011-02-18 18:52:37 +00005535// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5536// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5537bool
5538EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5539{
5540#if 0
5541 if ConditionPassed() then
5542 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5543 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5544 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5545 address = if index then offset_addr else R[n];
5546 data = MemU[address,4];
5547 if wback then R[n] = offset_addr;
5548 if t == 15 then
5549 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5550 elsif UnalignedSupport() || address<1:0> = ’00’ then
5551 R[t] = data;
5552 else // Can only apply before ARMv7
5553 if CurrentInstrSet() == InstrSet_ARM then
5554 R[t] = ROR(data, 8*UInt(address<1:0>));
5555 else
5556 R[t] = bits(32) UNKNOWN;
5557#endif
5558
5559 bool success = false;
5560 const uint32_t opcode = OpcodeAsUnsigned (&success);
5561 if (!success)
5562 return false;
5563
5564 if (ConditionPassed ())
5565 {
5566 const uint32_t addr_byte_size = GetAddressByteSize();
5567
5568 uint32_t t;
5569 uint32_t n;
5570 uint32_t m;
5571 bool index;
5572 bool add;
5573 bool wback;
5574 ARM_ShifterType shift_t;
5575 uint32_t shift_n;
5576
5577 switch (encoding)
5578 {
5579 case eEncodingT1:
5580 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5581 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5582 t = Bits32 (opcode, 2, 0);
5583 n = Bits32 (opcode, 5, 3);
5584 m = Bits32 (opcode, 8, 6);
5585
5586 // index = TRUE; add = TRUE; wback = FALSE;
5587 index = true;
5588 add = true;
5589 wback = false;
5590
5591 // (shift_t, shift_n) = (SRType_LSL, 0);
5592 shift_t = SRType_LSL;
5593 shift_n = 0;
5594
5595 break;
5596
5597 case eEncodingT2:
5598 // if Rn == ’1111’ then SEE LDR (literal);
5599 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5600 t = Bits32 (opcode, 15, 12);
5601 n = Bits32 (opcode, 19, 16);
5602 m = Bits32 (opcode, 3, 0);
5603
5604 // index = TRUE; add = TRUE; wback = FALSE;
5605 index = true;
5606 add = true;
5607 wback = false;
5608
5609 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5610 shift_t = SRType_LSL;
5611 shift_n = Bits32 (opcode, 5, 4);
5612
5613 // if BadReg(m) then UNPREDICTABLE;
5614 if (BadReg (m))
5615 return false;
5616
5617 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5618 if ((t == 15) && InITBlock() && !LastInITBlock())
5619 return false;
5620
5621 break;
5622
5623 case eEncodingA1:
5624 {
5625 // if P == ’0’ && W == ’1’ then SEE LDRT;
5626 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5627 t = Bits32 (opcode, 15, 12);
5628 n = Bits32 (opcode, 19, 16);
5629 m = Bits32 (opcode, 3, 0);
5630
5631 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5632 index = BitIsSet (opcode, 24);
5633 add = BitIsSet (opcode, 23);
5634 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5635
5636 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5637 uint32_t type = Bits32 (opcode, 6, 5);
5638 uint32_t imm5 = Bits32 (opcode, 11, 7);
5639 shift_n = DecodeImmShift (type, imm5, shift_t);
5640
5641 // if m == 15 then UNPREDICTABLE;
5642 if (m == 15)
5643 return false;
5644
5645 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5646 if (wback && ((n == 15) || (n == t)))
5647 return false;
5648 }
5649 break;
5650
5651
5652 default:
5653 return false;
5654 }
5655
5656 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5657 if (!success)
5658 return false;
5659
5660 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5661 if (!success)
5662 return false;
5663
5664 addr_t offset_addr;
5665 addr_t address;
5666
5667 // 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 +00005668 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005669
5670 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5671 if (add)
5672 offset_addr = Rn + offset;
5673 else
5674 offset_addr = Rn - offset;
5675
5676 // address = if index then offset_addr else R[n];
5677 if (index)
5678 address = offset_addr;
5679 else
5680 address = Rn;
5681
5682 // data = MemU[address,4];
5683 Register base_reg;
5684 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5685
5686 EmulateInstruction::Context context;
5687 context.type = eContextRegisterLoad;
5688 context.SetRegisterPlusOffset (base_reg, address - Rn);
5689
5690 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5691 if (!success)
5692 return false;
5693
5694 // if wback then R[n] = offset_addr;
5695 if (wback)
5696 {
5697 context.type = eContextAdjustBaseRegister;
5698 context.SetAddress (offset_addr);
5699 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5700 return false;
5701 }
5702
5703 // if t == 15 then
5704 if (t == 15)
5705 {
5706 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5707 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5708 {
5709 context.type = eContextRegisterLoad;
5710 context.SetRegisterPlusOffset (base_reg, address - Rn);
5711 LoadWritePC (context, data);
5712 }
5713 else
5714 return false;
5715 }
5716 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5717 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5718 {
5719 // R[t] = data;
5720 context.type = eContextRegisterLoad;
5721 context.SetRegisterPlusOffset (base_reg, address - Rn);
5722 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5723 return false;
5724 }
5725 else // Can only apply before ARMv7
5726 {
5727 // if CurrentInstrSet() == InstrSet_ARM then
5728 if (CurrentInstrSet () == eModeARM)
5729 {
5730 // R[t] = ROR(data, 8*UInt(address<1:0>));
5731 data = ROR (data, Bits32 (address, 1, 0));
5732 context.type = eContextRegisterLoad;
5733 context.SetImmediate (data);
5734 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5735 return false;
5736 }
5737 else
5738 {
5739 // R[t] = bits(32) UNKNOWN;
5740 WriteBits32Unknown (t);
5741 }
5742 }
5743 }
5744 return true;
5745}
Caroline Tice21b604b2011-02-18 21:06:04 +00005746
5747// LDRB (immediate, Thumb)
5748bool
5749EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5750{
5751#if 0
5752 if ConditionPassed() then
5753 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5754 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5755 address = if index then offset_addr else R[n];
5756 R[t] = ZeroExtend(MemU[address,1], 32);
5757 if wback then R[n] = offset_addr;
5758#endif
5759
5760 bool success = false;
5761 const uint32_t opcode = OpcodeAsUnsigned (&success);
5762 if (!success)
5763 return false;
5764
5765 if (ConditionPassed ())
5766 {
5767 uint32_t t;
5768 uint32_t n;
5769 uint32_t imm32;
5770 bool index;
5771 bool add;
5772 bool wback;
5773
5774 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5775 switch (encoding)
5776 {
5777 case eEncodingT1:
5778 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5779 t = Bits32 (opcode, 2, 0);
5780 n = Bits32 (opcode, 5, 3);
5781 imm32 = Bits32 (opcode, 10, 6);
5782
5783 // index = TRUE; add = TRUE; wback = FALSE;
5784 index = true;
5785 add = true;
5786 wback= false;
5787
5788 break;
5789
5790 case eEncodingT2:
5791 // if Rt == ’1111’ then SEE PLD;
5792 // if Rn == ’1111’ then SEE LDRB (literal);
5793 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5794 t = Bits32 (opcode, 15, 12);
5795 n = Bits32 (opcode, 19, 16);
5796 imm32 = Bits32 (opcode, 11, 0);
5797
5798 // index = TRUE; add = TRUE; wback = FALSE;
5799 index = true;
5800 add = true;
5801 wback = false;
5802
5803 // if t == 13 then UNPREDICTABLE;
5804 if (t == 13)
5805 return false;
5806
5807 break;
5808
5809 case eEncodingT3:
5810 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5811 // if Rn == ’1111’ then SEE LDRB (literal);
5812 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5813 // if P == ’0’ && W == ’0’ then UNDEFINED;
5814 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5815 return false;
5816
5817 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5818 t = Bits32 (opcode, 15, 12);
5819 n = Bits32 (opcode, 19, 16);
5820 imm32 = Bits32 (opcode, 7, 0);
5821
5822 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5823 index = BitIsSet (opcode, 10);
5824 add = BitIsSet (opcode, 9);
5825 wback = BitIsSet (opcode, 8);
5826
5827 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5828 if (BadReg (t) || (wback && (n == t)))
5829 return false;
5830
5831 break;
5832
5833 default:
5834 return false;
5835 }
5836
5837 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5838 if (!success)
5839 return false;
5840
5841 addr_t address;
5842 addr_t offset_addr;
5843
5844 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5845 if (add)
5846 offset_addr = Rn + imm32;
5847 else
5848 offset_addr = Rn - imm32;
5849
5850 // address = if index then offset_addr else R[n];
5851 if (index)
5852 address = offset_addr;
5853 else
5854 address = Rn;
5855
5856 // R[t] = ZeroExtend(MemU[address,1], 32);
5857 Register base_reg;
5858 Register data_reg;
5859 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5860 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5861
5862 EmulateInstruction::Context context;
5863 context.type = eContextRegisterLoad;
5864 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5865
5866 uint64_t data = MemURead (context, address, 1, 0, &success);
5867 if (!success)
5868 return false;
5869
5870 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5871 return false;
5872
5873 // if wback then R[n] = offset_addr;
5874 if (wback)
5875 {
5876 context.type = eContextAdjustBaseRegister;
5877 context.SetAddress (offset_addr);
5878 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5879 return false;
5880 }
5881 }
5882 return true;
5883}
Caroline Ticef55261f2011-02-18 22:24:22 +00005884
5885// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5886// zero-extends it to form a 32-bit word and writes it to a register.
5887bool
5888EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5889{
5890#if 0
5891 if ConditionPassed() then
5892 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5893 base = Align(PC,4);
5894 address = if add then (base + imm32) else (base - imm32);
5895 R[t] = ZeroExtend(MemU[address,1], 32);
5896#endif
5897
5898 bool success = false;
5899 const uint32_t opcode = OpcodeAsUnsigned (&success);
5900 if (!success)
5901 return false;
5902
5903 if (ConditionPassed ())
5904 {
5905 uint32_t t;
5906 uint32_t imm32;
5907 bool add;
5908 switch (encoding)
5909 {
5910 case eEncodingT1:
5911 // if Rt == ’1111’ then SEE PLD;
5912 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5913 t = Bits32 (opcode, 15, 12);
5914 imm32 = Bits32 (opcode, 11, 0);
5915 add = BitIsSet (opcode, 23);
5916
5917 // if t == 13 then UNPREDICTABLE;
5918 if (t == 13)
5919 return false;
5920
5921 break;
5922
5923 case eEncodingA1:
5924 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5925 t = Bits32 (opcode, 15, 12);
5926 imm32 = Bits32 (opcode, 11, 0);
5927 add = BitIsSet (opcode, 23);
5928
5929 // if t == 15 then UNPREDICTABLE;
5930 if (t == 15)
5931 return false;
5932 break;
5933
5934 default:
5935 return false;
5936 }
5937
5938 // base = Align(PC,4);
5939 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5940 if (!success)
5941 return false;
5942
5943 uint32_t base = AlignPC (pc_val);
5944
5945 addr_t address;
5946 // address = if add then (base + imm32) else (base - imm32);
5947 if (add)
5948 address = base + imm32;
5949 else
5950 address = base - imm32;
5951
5952 // R[t] = ZeroExtend(MemU[address,1], 32);
5953 EmulateInstruction::Context context;
5954 context.type = eContextRelativeBranchImmediate;
5955 context.SetImmediate (address - base);
5956
5957 uint64_t data = MemURead (context, address, 1, 0, &success);
5958 if (!success)
5959 return false;
5960
5961 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5962 return false;
5963 }
5964 return true;
5965}
Caroline Tice30fec122011-02-18 23:52:21 +00005966
5967// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5968// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5969// optionally be shifted.
5970bool
5971EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5972{
5973#if 0
5974 if ConditionPassed() then
5975 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5976 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5977 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5978 address = if index then offset_addr else R[n];
5979 R[t] = ZeroExtend(MemU[address,1],32);
5980 if wback then R[n] = offset_addr;
5981#endif
5982
5983 bool success = false;
5984 const uint32_t opcode = OpcodeAsUnsigned (&success);
5985 if (!success)
5986 return false;
5987
5988 if (ConditionPassed ())
5989 {
5990 uint32_t t;
5991 uint32_t n;
5992 uint32_t m;
5993 bool index;
5994 bool add;
5995 bool wback;
5996 ARM_ShifterType shift_t;
5997 uint32_t shift_n;
5998
5999 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6000 switch (encoding)
6001 {
6002 case eEncodingT1:
6003 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6004 t = Bits32 (opcode, 2, 0);
6005 n = Bits32 (opcode, 5, 3);
6006 m = Bits32 (opcode, 8, 6);
6007
6008 // index = TRUE; add = TRUE; wback = FALSE;
6009 index = true;
6010 add = true;
6011 wback = false;
6012
6013 // (shift_t, shift_n) = (SRType_LSL, 0);
6014 shift_t = SRType_LSL;
6015 shift_n = 0;
6016 break;
6017
6018 case eEncodingT2:
6019 // if Rt == ’1111’ then SEE PLD;
6020 // if Rn == ’1111’ then SEE LDRB (literal);
6021 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6022 t = Bits32 (opcode, 15, 12);
6023 n = Bits32 (opcode, 19, 16);
6024 m = Bits32 (opcode, 3, 0);
6025
6026 // index = TRUE; add = TRUE; wback = FALSE;
6027 index = true;
6028 add = true;
6029 wback = false;
6030
6031 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6032 shift_t = SRType_LSL;
6033 shift_n = Bits32 (opcode, 5, 4);
6034
6035 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6036 if ((t == 13) || BadReg (m))
6037 return false;
6038 break;
6039
6040 case eEncodingA1:
6041 {
6042 // if P == ’0’ && W == ’1’ then SEE LDRBT;
6043 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6044 t = Bits32 (opcode, 15, 12);
6045 n = Bits32 (opcode, 19, 16);
6046 m = Bits32 (opcode, 3, 0);
6047
6048 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6049 index = BitIsSet (opcode, 24);
6050 add = BitIsSet (opcode, 23);
6051 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6052
6053 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6054 uint32_t type = Bits32 (opcode, 6, 5);
6055 uint32_t imm5 = Bits32 (opcode, 11, 7);
6056 shift_n = DecodeImmShift (type, imm5, shift_t);
6057
6058 // if t == 15 || m == 15 then UNPREDICTABLE;
6059 if ((t == 15) || (m == 15))
6060 return false;
6061
6062 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6063 if (wback && ((n == 15) || (n == t)))
6064 return false;
6065 }
6066 break;
6067
6068 default:
6069 return false;
6070 }
6071
6072 addr_t offset_addr;
6073 addr_t address;
6074
6075 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6076 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6077 if (!success)
6078 return false;
6079
6080 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6081
6082 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6083 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6084 if (!success)
6085 return false;
6086
6087 if (add)
6088 offset_addr = Rn + offset;
6089 else
6090 offset_addr = Rn - offset;
6091
6092 // address = if index then offset_addr else R[n];
6093 if (index)
6094 address = offset_addr;
6095 else
6096 address = Rn;
6097
6098 // R[t] = ZeroExtend(MemU[address,1],32);
6099 Register base_reg;
6100 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6101
6102 EmulateInstruction::Context context;
6103 context.type = eContextRegisterLoad;
6104 context.SetRegisterPlusOffset (base_reg, address - Rn);
6105
6106 uint64_t data = MemURead (context, address, 1, 0, &success);
6107 if (!success)
6108 return false;
6109
6110 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6111 return false;
6112
6113 // if wback then R[n] = offset_addr;
6114 if (wback)
6115 {
6116 context.type = eContextAdjustBaseRegister;
6117 context.SetAddress (offset_addr);
6118 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6119 return false;
6120 }
6121 }
6122 return true;
6123}
Caroline Tice0491b3b2011-02-28 22:39:58 +00006124
6125// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
6126// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
6127// post-indexed, or pre-indexed addressing.
6128bool
6129EmulateInstructionARM::EmulateLDRHImmediate (ARMEncoding encoding)
6130{
6131#if 0
6132 if ConditionPassed() then
6133 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6134 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6135 address = if index then offset_addr else R[n];
6136 data = MemU[address,2];
6137 if wback then R[n] = offset_addr;
6138 if UnalignedSupport() || address<0> = ’0’ then
6139 R[t] = ZeroExtend(data, 32);
6140 else // Can only apply before ARMv7
6141 R[t] = bits(32) UNKNOWN;
6142#endif
6143
6144
6145 bool success = false;
6146 const uint32_t opcode = OpcodeAsUnsigned (&success);
6147 if (!success)
6148 return false;
6149
6150 if (ConditionPassed())
6151 {
6152 uint32_t t;
6153 uint32_t n;
6154 uint32_t imm32;
6155 bool index;
6156 bool add;
6157 bool wback;
6158
6159 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6160 switch (encoding)
6161 {
6162 case eEncodingT1:
6163 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
6164 t = Bits32 (opcode, 2, 0);
6165 n = Bits32 (opcode, 5, 3);
6166 imm32 = Bits32 (opcode, 10, 6) << 1;
6167
6168 // index = TRUE; add = TRUE; wback = FALSE;
6169 index = true;
6170 add = true;
6171 wback = false;
6172
6173 break;
6174
6175 case eEncodingT2:
6176 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6177 // if Rn == ’1111’ then SEE LDRH (literal);
6178 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6179 t = Bits32 (opcode, 15, 12);
6180 n = Bits32 (opcode, 19, 16);
6181 imm32 = Bits32 (opcode, 11, 0);
6182
6183 // index = TRUE; add = TRUE; wback = FALSE;
6184 index = true;
6185 add = true;
6186 wback = false;
6187
6188 // if t == 13 then UNPREDICTABLE;
6189 if (t == 13)
6190 return false;
6191 break;
6192
6193 case eEncodingT3:
6194 // if Rn == ’1111’ then SEE LDRH (literal);
6195 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6196 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
6197 // if P == ’0’ && W == ’0’ then UNDEFINED;
6198 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6199 return false;
6200
6201 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6202 t = Bits32 (opcode, 15, 12);
6203 n = Bits32 (opcode, 19, 16);
6204 imm32 = Bits32 (opcode, 7, 0);
6205
6206 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6207 index = BitIsSet (opcode, 10);
6208 add = BitIsSet (opcode, 9);
6209 wback = BitIsSet (opcode, 8);
6210
6211 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6212 if (BadReg (t) || (wback && (n == t)))
6213 return false;
6214 break;
6215
6216 default:
6217 return false;
6218 }
6219
6220 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6221 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6222 if (!success)
6223 return false;
6224
6225 addr_t offset_addr;
6226 addr_t address;
6227
6228 if (add)
6229 offset_addr = Rn + imm32;
6230 else
6231 offset_addr = Rn - imm32;
6232
6233 // address = if index then offset_addr else R[n];
6234 if (index)
6235 address = offset_addr;
6236 else
6237 address = Rn;
6238
6239 // data = MemU[address,2];
6240 Register base_reg;
6241 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6242
6243 EmulateInstruction::Context context;
6244 context.type = eContextRegisterLoad;
6245 context.SetRegisterPlusOffset (base_reg, address - Rn);
6246
6247 uint64_t data = MemURead (context, address, 2, 0, &success);
6248 if (!success)
6249 return false;
6250
6251 // if wback then R[n] = offset_addr;
6252 if (wback)
6253 {
6254 context.type = eContextAdjustBaseRegister;
6255 context.SetAddress (offset_addr);
6256 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6257 return false;
6258 }
6259
6260 // if UnalignedSupport() || address<0> = ’0’ then
6261 if (UnalignedSupport () || BitIsClear (address, 0))
6262 {
6263 // R[t] = ZeroExtend(data, 32);
6264 context.type = eContextRegisterLoad;
6265 context.SetRegisterPlusOffset (base_reg, address - Rn);
6266 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6267 return false;
6268 }
6269 else // Can only apply before ARMv7
6270 {
6271 // R[t] = bits(32) UNKNOWN;
6272 WriteBits32Unknown (t);
6273 }
6274 }
6275 return true;
6276}
Caroline Ticefe479112011-02-18 18:52:37 +00006277
Caroline Tice952b5382011-02-28 23:15:24 +00006278// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6279// zero-extends it to form a 32-bit word, and writes it to a register.
6280bool
6281EmulateInstructionARM::EmulateLDRHLiteral (ARMEncoding encoding)
6282{
6283#if 0
6284 if ConditionPassed() then
6285 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6286 base = Align(PC,4);
6287 address = if add then (base + imm32) else (base - imm32);
6288 data = MemU[address,2];
6289 if UnalignedSupport() || address<0> = ’0’ then
6290 R[t] = ZeroExtend(data, 32);
6291 else // Can only apply before ARMv7
6292 R[t] = bits(32) UNKNOWN;
6293#endif
Caroline Tice0e6bc952011-03-01 18:00:42 +00006294
Caroline Tice952b5382011-02-28 23:15:24 +00006295 bool success = false;
6296 const uint32_t opcode = OpcodeAsUnsigned (&success);
6297 if (!success)
6298 return false;
6299
6300 if (ConditionPassed())
6301 {
6302 uint32_t t;
6303 uint32_t imm32;
6304 bool add;
6305
6306 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6307 switch (encoding)
6308 {
6309 case eEncodingT1:
6310 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6311 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6312 t = Bits32 (opcode, 15, 12);
6313 imm32 = Bits32 (opcode, 11, 0);
6314 add = BitIsSet (opcode, 23);
6315
6316 // if t == 13 then UNPREDICTABLE;
6317 if (t == 13)
6318 return false;
6319
6320 break;
6321
6322 case eEncodingA1:
6323 {
6324 uint32_t imm4H = Bits32 (opcode, 11, 8);
6325 uint32_t imm4L = Bits32 (opcode, 3, 0);
6326
6327 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6328 t = Bits32 (opcode, 15, 12);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006329 imm32 = (imm4H << 4) | imm4L;
Caroline Tice952b5382011-02-28 23:15:24 +00006330 add = BitIsSet (opcode, 23);
6331
6332 // if t == 15 then UNPREDICTABLE;
6333 if (t == 15)
6334 return false;
6335 break;
6336 }
6337
6338 default:
6339 return false;
6340 }
6341
6342 // base = Align(PC,4);
6343 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
6344 if (!success)
6345 return false;
6346
6347 addr_t base = AlignPC (pc_value);
6348 addr_t address;
6349
6350 // address = if add then (base + imm32) else (base - imm32);
6351 if (add)
6352 address = base + imm32;
6353 else
6354 address = base - imm32;
6355
6356 // data = MemU[address,2];
6357 Register base_reg;
6358 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6359
6360 EmulateInstruction::Context context;
6361 context.type = eContextRegisterLoad;
6362 context.SetRegisterPlusOffset (base_reg, address - base);
6363
6364 uint64_t data = MemURead (context, address, 2, 0, &success);
6365 if (!success)
6366 return false;
6367
6368
6369 // if UnalignedSupport() || address<0> = ’0’ then
6370 if (UnalignedSupport () || BitIsClear (address, 0))
6371 {
6372 // R[t] = ZeroExtend(data, 32);
6373 context.type = eContextRegisterLoad;
6374 context.SetRegisterPlusOffset (base_reg, address - base);
6375 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6376 return false;
6377
6378 }
6379 else // Can only apply before ARMv7
6380 {
6381 // R[t] = bits(32) UNKNOWN;
6382 WriteBits32Unknown (t);
6383 }
6384 }
6385 return true;
6386}
6387
Caroline Tice0e6bc952011-03-01 18:00:42 +00006388// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6389// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6390// be shifted left by 0, 1, 2, or 3 bits.
6391bool
6392EmulateInstructionARM::EmulateLDRHRegister (ARMEncoding encoding)
6393{
6394#if 0
6395 if ConditionPassed() then
6396 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6397 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6398 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6399 address = if index then offset_addr else R[n];
6400 data = MemU[address,2];
6401 if wback then R[n] = offset_addr;
6402 if UnalignedSupport() || address<0> = ’0’ then
6403 R[t] = ZeroExtend(data, 32);
6404 else // Can only apply before ARMv7
6405 R[t] = bits(32) UNKNOWN;
6406#endif
6407
6408 bool success = false;
6409 const uint32_t opcode = OpcodeAsUnsigned (&success);
6410 if (!success)
6411 return false;
6412
6413 if (ConditionPassed())
6414 {
6415 uint32_t t;
6416 uint32_t n;
6417 uint32_t m;
6418 bool index;
6419 bool add;
6420 bool wback;
6421 ARM_ShifterType shift_t;
6422 uint32_t shift_n;
6423
6424 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6425 switch (encoding)
6426 {
6427 case eEncodingT1:
6428 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6429 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6430 t = Bits32 (opcode, 2, 0);
6431 n = Bits32 (opcode, 5, 3);
6432 m = Bits32 (opcode, 8, 6);
6433
6434 // index = TRUE; add = TRUE; wback = FALSE;
6435 index = true;
6436 add = true;
6437 wback = false;
6438
6439 // (shift_t, shift_n) = (SRType_LSL, 0);
6440 shift_t = SRType_LSL;
6441 shift_n = 0;
6442
6443 break;
6444
6445 case eEncodingT2:
6446 // if Rn == ’1111’ then SEE LDRH (literal);
6447 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6448 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6449 t = Bits32 (opcode, 15, 12);
6450 n = Bits32 (opcode, 19, 16);
6451 m = Bits32 (opcode, 3, 0);
6452
6453 // index = TRUE; add = TRUE; wback = FALSE;
6454 index = true;
6455 add = true;
6456 wback = false;
6457
6458 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6459 shift_t = SRType_LSL;
6460 shift_n = Bits32 (opcode, 5, 4);
6461
6462 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6463 if ((t == 13) || BadReg (m))
6464 return false;
6465 break;
6466
6467 case eEncodingA1:
6468 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6469 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6470 t = Bits32 (opcode, 15, 12);
6471 n = Bits32 (opcode, 19, 16);
6472 m = Bits32 (opcode, 3, 0);
6473
6474 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6475 index = BitIsSet (opcode, 24);
6476 add = BitIsSet (opcode, 23);
6477 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6478
6479 // (shift_t, shift_n) = (SRType_LSL, 0);
6480 shift_t = SRType_LSL;
6481 shift_n = 0;
6482
6483 // if t == 15 || m == 15 then UNPREDICTABLE;
6484 if ((t == 15) || (m == 15))
6485 return false;
6486
6487 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6488 if (wback && ((n == 15) || (n == t)))
6489 return false;
6490
6491 break;
6492
6493 default:
6494 return false;
6495 }
6496
6497 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6498
6499 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6500 if (!success)
6501 return false;
6502
6503 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6504
6505 addr_t offset_addr;
6506 addr_t address;
6507
6508 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6509 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6510 if (!success)
6511 return false;
6512
6513 if (add)
6514 offset_addr = Rn + offset;
6515 else
6516 offset_addr = Rn - offset;
6517
6518 // address = if index then offset_addr else R[n];
6519 if (index)
6520 address = offset_addr;
6521 else
6522 address = Rn;
6523
6524 // data = MemU[address,2];
6525 Register base_reg;
6526 Register offset_reg;
6527 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6528 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6529
6530 EmulateInstruction::Context context;
6531 context.type = eContextRegisterLoad;
6532 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6533 uint64_t data = MemURead (context, address, 2, 0, &success);
6534 if (!success)
6535 return false;
6536
6537 // if wback then R[n] = offset_addr;
6538 if (wback)
6539 {
6540 context.type = eContextAdjustBaseRegister;
6541 context.SetAddress (offset_addr);
6542 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6543 return false;
6544 }
6545
6546 // if UnalignedSupport() || address<0> = ’0’ then
6547 if (UnalignedSupport() || BitIsClear (address, 0))
6548 {
6549 // R[t] = ZeroExtend(data, 32);
6550 context.type = eContextRegisterLoad;
6551 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6552 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6553 return false;
6554 }
6555 else // Can only apply before ARMv7
6556 {
6557 // R[t] = bits(32) UNKNOWN;
6558 WriteBits32Unknown (t);
6559 }
6560 }
6561 return true;
6562}
6563
Caroline Ticea5e28af2011-03-01 21:53:03 +00006564// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6565// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6566// or pre-indexed addressing.
6567bool
6568EmulateInstructionARM::EmulateLDRSBImmediate (ARMEncoding encoding)
6569{
6570#if 0
6571 if ConditionPassed() then
6572 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6573 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6574 address = if index then offset_addr else R[n];
6575 R[t] = SignExtend(MemU[address,1], 32);
6576 if wback then R[n] = offset_addr;
6577#endif
6578
6579 bool success = false;
6580 const uint32_t opcode = OpcodeAsUnsigned (&success);
6581 if (!success)
6582 return false;
6583
6584 if (ConditionPassed ())
6585 {
6586 uint32_t t;
6587 uint32_t n;
6588 uint32_t imm32;
6589 bool index;
6590 bool add;
6591 bool wback;
6592
6593 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6594 switch (encoding)
6595 {
6596 case eEncodingT1:
6597 // if Rt == ’1111’ then SEE PLI;
6598 // if Rn == ’1111’ then SEE LDRSB (literal);
6599 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6600 t = Bits32 (opcode, 15, 12);
6601 n = Bits32 (opcode, 19, 16);
6602 imm32 = Bits32 (opcode, 11, 0);
6603
6604 // index = TRUE; add = TRUE; wback = FALSE;
6605 index = true;
6606 add = true;
6607 wback = false;
6608
6609 // if t == 13 then UNPREDICTABLE;
6610 if (t == 13)
6611 return false;
6612
6613 break;
6614
6615 case eEncodingT2:
6616 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6617 // if Rn == ’1111’ then SEE LDRSB (literal);
6618 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6619 // if P == ’0’ && W == ’0’ then UNDEFINED;
6620 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6621 return false;
6622
6623 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6624 t = Bits32 (opcode, 15, 12);
6625 n = Bits32 (opcode, 19, 16);
6626 imm32 = Bits32 (opcode, 7, 0);
6627
6628 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6629 index = BitIsSet (opcode, 10);
6630 add = BitIsSet (opcode, 9);
6631 wback = BitIsSet (opcode, 8);
6632
6633 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6634 if (BadReg (t) || (wback && (n == t)))
6635 return false;
6636
6637 break;
6638
6639 case eEncodingA1:
6640 {
6641 // if Rn == ’1111’ then SEE LDRSB (literal);
6642 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6643 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6644 t = Bits32 (opcode, 15, 12);
6645 n = Bits32 (opcode, 19, 16);
6646
6647 uint32_t imm4H = Bits32 (opcode, 11, 8);
6648 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006649 imm32 = (imm4H << 4) | imm4L;
Caroline Ticea5e28af2011-03-01 21:53:03 +00006650
6651 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6652 index = BitIsSet (opcode, 24);
6653 add = BitIsSet (opcode, 23);
6654 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6655
6656 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6657 if ((t == 15) || (wback && (n == t)))
6658 return false;
6659
6660 break;
6661 }
6662
6663 default:
6664 return false;
6665 }
6666
6667 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6668 if (!success)
6669 return false;
6670
6671 addr_t offset_addr;
6672 addr_t address;
6673
6674 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6675 if (add)
6676 offset_addr = Rn + imm32;
6677 else
6678 offset_addr = Rn - imm32;
6679
6680 // address = if index then offset_addr else R[n];
6681 if (index)
6682 address = offset_addr;
6683 else
6684 address = Rn;
6685
6686 // R[t] = SignExtend(MemU[address,1], 32);
6687 Register base_reg;
6688 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6689
6690 EmulateInstruction::Context context;
6691 context.type = eContextRegisterLoad;
6692 context.SetRegisterPlusOffset (base_reg, address - Rn);
6693
6694 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6695 if (!success)
6696 return false;
6697
6698 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6699 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6700 return false;
6701
6702 // if wback then R[n] = offset_addr;
6703 if (wback)
6704 {
6705 context.type = eContextAdjustBaseRegister;
6706 context.SetAddress (offset_addr);
6707 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6708 return false;
6709 }
6710 }
6711
6712 return true;
6713}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006714
Caroline Tice5f593912011-03-01 22:25:17 +00006715// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6716// sign-extends it to form a 32-bit word, and writes tit to a register.
6717bool
6718EmulateInstructionARM::EmulateLDRSBLiteral (ARMEncoding encoding)
6719{
6720#if 0
6721 if ConditionPassed() then
6722 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6723 base = Align(PC,4);
6724 address = if add then (base + imm32) else (base - imm32);
6725 R[t] = SignExtend(MemU[address,1], 32);
6726#endif
6727
6728 bool success = false;
6729 const uint32_t opcode = OpcodeAsUnsigned (&success);
6730 if (!success)
6731 return false;
6732
6733 if (ConditionPassed ())
6734 {
6735 uint32_t t;
6736 uint32_t imm32;
6737 bool add;
6738
6739 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6740 switch (encoding)
6741 {
6742 case eEncodingT1:
6743 // if Rt == ’1111’ then SEE PLI;
6744 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6745 t = Bits32 (opcode, 15, 12);
6746 imm32 = Bits32 (opcode, 11, 0);
6747 add = BitIsSet (opcode, 23);
6748
6749 // if t == 13 then UNPREDICTABLE;
6750 if (t == 13)
6751 return false;
6752
6753 break;
6754
6755 case eEncodingA1:
6756 {
6757 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6758 t = Bits32 (opcode, 15, 12);
6759 uint32_t imm4H = Bits32 (opcode, 11, 8);
6760 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00006761 imm32 = (imm4H << 4) | imm4L;
Caroline Tice5f593912011-03-01 22:25:17 +00006762 add = BitIsSet (opcode, 23);
6763
6764 // if t == 15 then UNPREDICTABLE;
6765 if (t == 15)
6766 return false;
6767
6768 break;
6769 }
6770
6771 default:
6772 return false;
6773 }
6774
6775 // base = Align(PC,4);
6776 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS,
6777 &success);
6778 if (!success)
6779 return false;
6780 uint64_t base = AlignPC (pc_value);
6781
6782 // address = if add then (base + imm32) else (base - imm32);
6783 addr_t address;
6784 if (add)
6785 address = base + imm32;
6786 else
6787 address = base - imm32;
6788
6789 // R[t] = SignExtend(MemU[address,1], 32);
6790 Register base_reg;
6791 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6792
6793 EmulateInstruction::Context context;
6794 context.type = eContextRegisterLoad;
6795 context.SetRegisterPlusOffset (base_reg, address - base);
6796
6797 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6798 if (!success)
6799 return false;
6800
6801 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6802 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6803 return false;
6804 }
6805 return true;
6806}
6807
Caroline Tice672f3112011-03-01 23:55:59 +00006808// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6809// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6810// shifted left by 0, 1, 2, or 3 bits.
6811bool
6812EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
6813{
6814#if 0
6815 if ConditionPassed() then
6816 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6817 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6818 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6819 address = if index then offset_addr else R[n];
6820 R[t] = SignExtend(MemU[address,1], 32);
6821 if wback then R[n] = offset_addr;
6822#endif
6823
6824 bool success = false;
6825 const uint32_t opcode = OpcodeAsUnsigned (&success);
6826 if (!success)
6827 return false;
6828
6829 if (ConditionPassed ())
6830 {
6831 uint32_t t;
6832 uint32_t n;
6833 uint32_t m;
6834 bool index;
6835 bool add;
6836 bool wback;
6837 ARM_ShifterType shift_t;
6838 uint32_t shift_n;
6839
6840 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6841 switch (encoding)
6842 {
6843 case eEncodingT1:
6844 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6845 t = Bits32 (opcode, 2, 0);
6846 n = Bits32 (opcode, 5, 3);
6847 m = Bits32 (opcode, 8, 6);
6848
6849 // index = TRUE; add = TRUE; wback = FALSE;
6850 index = true;
6851 add = true;
6852 wback = false;
6853
6854 // (shift_t, shift_n) = (SRType_LSL, 0);
6855 shift_t = SRType_LSL;
6856 shift_n = 0;
6857
6858 break;
6859
6860 case eEncodingT2:
6861 // if Rt == ’1111’ then SEE PLI;
6862 // if Rn == ’1111’ then SEE LDRSB (literal);
6863 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6864 t = Bits32 (opcode, 15, 12);
6865 n = Bits32 (opcode, 19, 16);
6866 m = Bits32 (opcode, 3, 0);
6867
6868 // index = TRUE; add = TRUE; wback = FALSE;
6869 index = true;
6870 add = true;
6871 wback = false;
6872
6873 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6874 shift_t = SRType_LSL;
6875 shift_n = Bits32 (opcode, 5, 4);
6876
6877 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6878 if ((t == 13) || BadReg (m))
6879 return false;
6880 break;
6881
6882 case eEncodingA1:
6883 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6884 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6885 t = Bits32 (opcode, 15, 12);
6886 n = Bits32 (opcode, 19, 16);
6887 m = Bits32 (opcode, 3, 0);
6888
6889 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6890 index = BitIsSet (opcode, 24);
6891 add = BitIsSet (opcode, 23);
6892 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
6893
6894 // (shift_t, shift_n) = (SRType_LSL, 0);
6895 shift_t = SRType_LSL;
6896 shift_n = 0;
6897
6898 // if t == 15 || m == 15 then UNPREDICTABLE;
6899 if ((t == 15) || (m == 15))
6900 return false;
6901
6902 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6903 if (wback && ((n == 15) || (n == t)))
6904 return false;
6905 break;
6906
6907 default:
6908 return false;
6909 }
6910
6911 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6912 if (!success)
6913 return false;
6914
6915 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6916 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6917
6918 addr_t offset_addr;
6919 addr_t address;
6920
6921 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6922 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6923 if (!success)
6924 return false;
6925
6926 if (add)
6927 offset_addr = Rn + offset;
6928 else
6929 offset_addr = Rn - offset;
6930
6931 // address = if index then offset_addr else R[n];
6932 if (index)
6933 address = offset_addr;
6934 else
6935 address = Rn;
6936
6937 // R[t] = SignExtend(MemU[address,1], 32);
6938 Register base_reg;
6939 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6940 Register offset_reg;
6941 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6942
6943 EmulateInstruction::Context context;
6944 context.type = eContextRegisterLoad;
6945 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6946
6947 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6948 if (!success)
6949 return false;
6950
6951 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6952 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6953 return false;
6954
6955 // if wback then R[n] = offset_addr;
6956 if (wback)
6957 {
6958 context.type = eContextAdjustBaseRegister;
6959 context.SetAddress (offset_addr);
6960 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6961 return false;
6962 }
6963 }
6964 return true;
6965}
6966
Caroline Tice78fb5632011-03-02 00:39:42 +00006967// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
6968// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
6969// pre-indexed addressing.
6970bool
6971EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
6972{
6973#if 0
6974 if ConditionPassed() then
6975 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6976 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6977 address = if index then offset_addr else R[n];
6978 data = MemU[address,2];
6979 if wback then R[n] = offset_addr;
6980 if UnalignedSupport() || address<0> = ’0’ then
6981 R[t] = SignExtend(data, 32);
6982 else // Can only apply before ARMv7
6983 R[t] = bits(32) UNKNOWN;
6984#endif
6985
6986 bool success = false;
6987 const uint32_t opcode = OpcodeAsUnsigned (&success);
6988 if (!success)
6989 return false;
6990
6991 if (ConditionPassed())
6992 {
6993 uint32_t t;
6994 uint32_t n;
6995 uint32_t imm32;
6996 bool index;
6997 bool add;
6998 bool wback;
6999
7000 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7001 switch (encoding)
7002 {
7003 case eEncodingT1:
7004 // if Rn == ’1111’ then SEE LDRSH (literal);
7005 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7006 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7007 t = Bits32 (opcode, 15, 12);
7008 n = Bits32 (opcode, 19, 16);
7009 imm32 = Bits32 (opcode, 11, 0);
7010
7011 // index = TRUE; add = TRUE; wback = FALSE;
7012 index = true;
7013 add = true;
7014 wback = false;
7015
7016 // if t == 13 then UNPREDICTABLE;
7017 if (t == 13)
7018 return false;
7019
7020 break;
7021
7022 case eEncodingT2:
7023 // if Rn == ’1111’ then SEE LDRSH (literal);
7024 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
7025 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
7026 // if P == ’0’ && W == ’0’ then UNDEFINED;
7027 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
7028 return false;
7029
7030 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7031 t = Bits32 (opcode, 15, 12);
7032 n = Bits32 (opcode, 19, 16);
7033 imm32 = Bits32 (opcode, 7, 0);
7034
7035 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
7036 index = BitIsSet (opcode, 10);
7037 add = BitIsSet (opcode, 9);
7038 wback = BitIsSet (opcode, 8);
7039
7040 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7041 if (BadReg (t) || (wback && (n == t)))
7042 return false;
7043
7044 break;
7045
7046 case eEncodingA1:
7047 {
7048 // if Rn == ’1111’ then SEE LDRSH (literal);
7049 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7050 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7051 t = Bits32 (opcode, 15, 12);
7052 n = Bits32 (opcode, 19, 16);
7053 uint32_t imm4H = Bits32 (opcode, 11,8);
7054 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007055 imm32 = (imm4H << 4) | imm4L;
Caroline Tice78fb5632011-03-02 00:39:42 +00007056
7057 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7058 index = BitIsSet (opcode, 24);
7059 add = BitIsSet (opcode, 23);
7060 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7061
7062 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7063 if ((t == 15) || (wback && (n == t)))
7064 return false;
7065
7066 break;
7067 }
7068
7069 default:
7070 return false;
7071 }
7072
7073 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7074 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7075 if (!success)
7076 return false;
7077
7078 addr_t offset_addr;
7079 if (add)
7080 offset_addr = Rn + imm32;
7081 else
7082 offset_addr = Rn - imm32;
7083
7084 // address = if index then offset_addr else R[n];
7085 addr_t address;
7086 if (index)
7087 address = offset_addr;
7088 else
7089 address = Rn;
7090
7091 // data = MemU[address,2];
7092 Register base_reg;
7093 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7094
7095 EmulateInstruction::Context context;
7096 context.type = eContextRegisterLoad;
7097 context.SetRegisterPlusOffset (base_reg, address - Rn);
7098
7099 uint64_t data = MemURead (context, address, 2, 0, &success);
7100 if (!success)
7101 return false;
7102
7103 // if wback then R[n] = offset_addr;
7104 if (wback)
7105 {
7106 context.type = eContextAdjustBaseRegister;
7107 context.SetAddress (offset_addr);
7108 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7109 return false;
7110 }
7111
7112 // if UnalignedSupport() || address<0> = ’0’ then
7113 if (UnalignedSupport() || BitIsClear (address, 0))
7114 {
7115 // R[t] = SignExtend(data, 32);
7116 int64_t signed_data = llvm::SignExtend64<16>(data);
7117 context.type = eContextRegisterLoad;
7118 context.SetRegisterPlusOffset (base_reg, address - Rn);
7119 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7120 return false;
7121 }
7122 else // Can only apply before ARMv7
7123 {
7124 // R[t] = bits(32) UNKNOWN;
7125 WriteBits32Unknown (t);
7126 }
7127 }
7128 return true;
7129}
7130
Caroline Ticed2fac092011-03-02 19:45:34 +00007131// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
7132// sign-extends it to from a 32-bit word, and writes it to a register.
7133bool
7134EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
7135{
7136#if 0
7137 if ConditionPassed() then
7138 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7139 base = Align(PC,4);
7140 address = if add then (base + imm32) else (base - imm32);
7141 data = MemU[address,2];
7142 if UnalignedSupport() || address<0> = ’0’ then
7143 R[t] = SignExtend(data, 32);
7144 else // Can only apply before ARMv7
7145 R[t] = bits(32) UNKNOWN;
7146#endif
7147
7148 bool success = false;
7149 const uint32_t opcode = OpcodeAsUnsigned (&success);
7150 if (!success)
7151 return false;
7152
7153 if (ConditionPassed())
7154 {
7155 uint32_t t;
7156 uint32_t imm32;
7157 bool add;
7158
7159 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7160 switch (encoding)
7161 {
7162 case eEncodingT1:
7163 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7164 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
7165 t = Bits32 (opcode, 15, 12);
7166 imm32 = Bits32 (opcode, 11, 0);
7167 add = BitIsSet (opcode, 23);
7168
7169 // if t == 13 then UNPREDICTABLE;
7170 if (t == 13)
7171 return false;
7172
7173 break;
7174
7175 case eEncodingA1:
7176 {
7177 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
7178 t = Bits32 (opcode, 15, 12);
7179 uint32_t imm4H = Bits32 (opcode, 11, 8);
7180 uint32_t imm4L = Bits32 (opcode, 3, 0);
Caroline Tice40b1a6c2011-03-03 00:07:02 +00007181 imm32 = (imm4H << 4) | imm4L;
Caroline Ticed2fac092011-03-02 19:45:34 +00007182 add = BitIsSet (opcode, 23);
7183
7184 // if t == 15 then UNPREDICTABLE;
7185 if (t == 15)
7186 return false;
7187
7188 break;
7189 }
7190 default:
7191 return false;
7192 }
7193
7194 // base = Align(PC,4);
7195 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
7196 if (!success)
7197 return false;
7198
7199 uint64_t base = AlignPC (pc_value);
7200
7201 addr_t address;
7202 // address = if add then (base + imm32) else (base - imm32);
7203 if (add)
7204 address = base + imm32;
7205 else
7206 address = base - imm32;
7207
7208 // data = MemU[address,2];
7209 Register base_reg;
7210 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7211
7212 EmulateInstruction::Context context;
7213 context.type = eContextRegisterLoad;
7214 context.SetRegisterPlusOffset (base_reg, imm32);
7215
7216 uint64_t data = MemURead (context, address, 2, 0, &success);
7217 if (!success)
7218 return false;
7219
7220 // if UnalignedSupport() || address<0> = ’0’ then
7221 if (UnalignedSupport() || BitIsClear (address, 0))
7222 {
7223 // R[t] = SignExtend(data, 32);
7224 int64_t signed_data = llvm::SignExtend64<16>(data);
7225 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7226 return false;
7227 }
7228 else // Can only apply before ARMv7
7229 {
7230 // R[t] = bits(32) UNKNOWN;
7231 WriteBits32Unknown (t);
7232 }
7233 }
7234 return true;
7235}
7236
Caroline Tice291a3e92011-03-02 21:13:44 +00007237// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
7238// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
7239// shifted left by 0, 1, 2, or 3 bits.
7240bool
7241EmulateInstructionARM::EmulateLDRSHRegister (ARMEncoding encoding)
7242{
7243#if 0
7244 if ConditionPassed() then
7245 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7246 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7247 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7248 address = if index then offset_addr else R[n];
7249 data = MemU[address,2];
7250 if wback then R[n] = offset_addr;
7251 if UnalignedSupport() || address<0> = ’0’ then
7252 R[t] = SignExtend(data, 32);
7253 else // Can only apply before ARMv7
7254 R[t] = bits(32) UNKNOWN;
7255#endif
7256
7257 bool success = false;
7258 const uint32_t opcode = OpcodeAsUnsigned (&success);
7259 if (!success)
7260 return false;
7261
7262 if (ConditionPassed())
7263 {
7264 uint32_t t;
7265 uint32_t n;
7266 uint32_t m;
7267 bool index;
7268 bool add;
7269 bool wback;
7270 ARM_ShifterType shift_t;
7271 uint32_t shift_n;
7272
7273 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7274 switch (encoding)
7275 {
7276 case eEncodingT1:
7277 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
7278 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7279 t = Bits32 (opcode, 2, 0);
7280 n = Bits32 (opcode, 5, 3);
7281 m = Bits32 (opcode, 8, 6);
7282
7283 // index = TRUE; add = TRUE; wback = FALSE;
7284 index = true;
7285 add = true;
7286 wback = false;
7287
7288 // (shift_t, shift_n) = (SRType_LSL, 0);
7289 shift_t = SRType_LSL;
7290 shift_n = 0;
7291
7292 break;
7293
7294 case eEncodingT2:
7295 // if Rn == ’1111’ then SEE LDRSH (literal);
7296 // if Rt == ’1111’ then SEE "Unallocated memory hints";
7297 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7298 t = Bits32 (opcode, 15, 12);
7299 n = Bits32 (opcode, 19, 16);
7300 m = Bits32 (opcode, 3, 0);
7301
7302 // index = TRUE; add = TRUE; wback = FALSE;
7303 index = true;
7304 add = true;
7305 wback = false;
7306
7307 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7308 shift_t = SRType_LSL;
7309 shift_n = Bits32 (opcode, 5, 4);
7310
7311 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7312 if ((t == 13) || BadReg (m))
7313 return false;
7314
7315 break;
7316
7317 case eEncodingA1:
7318 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
7319 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7320 t = Bits32 (opcode, 15, 12);
7321 n = Bits32 (opcode, 19, 16);
7322 m = Bits32 (opcode, 3, 0);
7323
7324 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
7325 index = BitIsSet (opcode, 24);
7326 add = BitIsSet (opcode, 23);
7327 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
7328
7329 // (shift_t, shift_n) = (SRType_LSL, 0);
7330 shift_t = SRType_LSL;
7331 shift_n = 0;
7332
7333 // if t == 15 || m == 15 then UNPREDICTABLE;
7334 if ((t == 15) || (m == 15))
7335 return false;
7336
7337 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7338 if (wback && ((n == 15) || (n == t)))
7339 return false;
7340
7341 break;
7342
7343 default:
7344 break;
7345 }
7346
7347 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7348 if (!success)
7349 return false;
7350
7351 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7352 if (!success)
7353 return false;
7354
7355 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7356 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
7357
7358 addr_t offset_addr;
7359 addr_t address;
7360
7361 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7362 if (add)
7363 offset_addr = Rn + offset;
7364 else
7365 offset_addr = Rn - offset;
7366
7367 // address = if index then offset_addr else R[n];
7368 if (index)
7369 address = offset_addr;
7370 else
7371 address = Rn;
7372
7373 // data = MemU[address,2];
7374 Register base_reg;
7375 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7376
7377 Register offset_reg;
7378 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7379
7380 EmulateInstruction::Context context;
7381 context.type = eContextRegisterLoad;
7382 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7383
7384 uint64_t data = MemURead (context, address, 2, 0, &success);
7385 if (!success)
7386 return false;
7387
7388 // if wback then R[n] = offset_addr;
7389 if (wback)
7390 {
7391 context.type = eContextAdjustBaseRegister;
7392 context.SetAddress (offset_addr);
7393 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
7394 return false;
7395 }
7396
7397 // if UnalignedSupport() || address<0> = ’0’ then
7398 if (UnalignedSupport() || BitIsClear (address, 0))
7399 {
7400 // R[t] = SignExtend(data, 32);
7401 context.type = eContextRegisterLoad;
7402 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
7403
7404 int64_t signed_data = llvm::SignExtend64<16>(data);
7405 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
7406 return false;
7407 }
7408 else // Can only apply before ARMv7
7409 {
7410 // R[t] = bits(32) UNKNOWN;
7411 WriteBits32Unknown (t);
7412 }
7413 }
7414 return true;
7415}
Caroline Tice6bf65162011-03-03 17:42:58 +00007416
7417// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7418// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7419bool
7420EmulateInstructionARM::EmulateSXTB (ARMEncoding encoding)
7421{
7422#if 0
7423 if ConditionPassed() then
7424 EncodingSpecificOperations();
7425 rotated = ROR(R[m], rotation);
7426 R[d] = SignExtend(rotated<7:0>, 32);
7427#endif
7428
7429 bool success = false;
7430 const uint32_t opcode = OpcodeAsUnsigned (&success);
7431 if (!success)
7432 return false;
7433
7434 if (ConditionPassed())
7435 {
7436 uint32_t d;
7437 uint32_t m;
7438 uint32_t rotation;
7439
7440 // EncodingSpecificOperations();
7441 switch (encoding)
7442 {
7443 case eEncodingT1:
7444 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7445 d = Bits32 (opcode, 2, 0);
7446 m = Bits32 (opcode, 5, 3);
7447 rotation = 0;
7448
7449 break;
7450
7451 case eEncodingT2:
7452 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7453 d = Bits32 (opcode, 11, 8);
7454 m = Bits32 (opcode, 3, 0);
7455 rotation = Bits32 (opcode, 5, 4) << 3;
7456
7457 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7458 if (BadReg (d) || BadReg (m))
7459 return false;
7460
7461 break;
7462
7463 case eEncodingA1:
7464 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7465 d = Bits32 (opcode, 15, 12);
7466 m = Bits32 (opcode, 3, 0);
7467 rotation = Bits32 (opcode, 11, 10) << 3;
7468
7469 // if d == 15 || m == 15 then UNPREDICTABLE;
7470 if ((d == 15) || (m == 15))
7471 return false;
7472
7473 break;
7474
7475 default:
7476 return false;
7477 }
7478
Caroline Tice868198b2011-03-03 18:04:49 +00007479 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7480 if (!success)
7481 return false;
Caroline Tice6bf65162011-03-03 17:42:58 +00007482
7483 // rotated = ROR(R[m], rotation);
7484 uint64_t rotated = ROR (Rm, rotation);
7485
7486 // R[d] = SignExtend(rotated<7:0>, 32);
7487 uint64_t data = llvm::SignExtend64<8>(rotated);
7488
7489 Register source_reg;
7490 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7491
7492 EmulateInstruction::Context context;
7493 context.type = eContextRegisterLoad;
7494 context.SetRegister (source_reg);
7495
7496 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, data))
7497 return false;
7498 }
7499 return true;
7500}
Caroline Tice291a3e92011-03-02 21:13:44 +00007501
Caroline Tice868198b2011-03-03 18:04:49 +00007502// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
7503// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7504bool
7505EmulateInstructionARM::EmulateSXTH (ARMEncoding encoding)
7506{
7507#if 0
7508 if ConditionPassed() then
7509 EncodingSpecificOperations();
7510 rotated = ROR(R[m], rotation);
7511 R[d] = SignExtend(rotated<15:0>, 32);
7512#endif
7513
7514 bool success = false;
7515 const uint32_t opcode = OpcodeAsUnsigned (&success);
7516 if (!success)
7517 return false;
7518
7519 if (ConditionPassed())
7520 {
7521 uint32_t d;
7522 uint32_t m;
7523 uint32_t rotation;
7524
7525 // EncodingSpecificOperations();
7526 switch (encoding)
7527 {
7528 case eEncodingT1:
7529 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7530 d = Bits32 (opcode, 2, 0);
7531 m = Bits32 (opcode, 5, 3);
7532 rotation = 0;
7533
7534 break;
7535
7536 case eEncodingT2:
7537 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7538 d = Bits32 (opcode, 11, 8);
7539 m = Bits32 (opcode, 3, 0);
7540 rotation = Bits32 (opcode, 5, 4) << 3;
7541
7542 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7543 if (BadReg (d) || BadReg (m))
7544 return false;
7545
7546 break;
7547
7548 case eEncodingA1:
7549 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7550 d = Bits32 (opcode, 15, 12);
7551 m = Bits32 (opcode, 3, 0);
7552 rotation = Bits32 (opcode, 11, 10) << 3;
7553
7554 // if d == 15 || m == 15 then UNPREDICTABLE;
7555 if ((d == 15) || (m == 15))
7556 return false;
7557
7558 break;
7559
7560 default:
7561 return false;
7562 }
7563
7564 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7565 if (!success)
7566 return false;
7567
7568 // rotated = ROR(R[m], rotation);
7569 uint64_t rotated = ROR (Rm, rotation);
7570
7571 // R[d] = SignExtend(rotated<15:0>, 32);
7572 Register source_reg;
7573 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7574
7575 EmulateInstruction::Context context;
7576 context.type = eContextRegisterLoad;
7577 context.SetRegister (source_reg);
7578
7579 uint64_t data = llvm::SignExtend64<16> (rotated);
7580 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, data))
7581 return false;
7582 }
7583
7584 return true;
7585}
7586
Johnny Chen2115b412011-02-21 23:42:44 +00007587// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
7588// and writes the result to the destination register. It can optionally update the condition flags based on
7589// the result.
7590bool
7591EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
7592{
7593#if 0
7594 // ARM pseudo code...
7595 if ConditionPassed() then
7596 EncodingSpecificOperations();
7597 result = R[n] EOR imm32;
7598 if d == 15 then // Can only occur for ARM encoding
7599 ALUWritePC(result); // setflags is always FALSE here
7600 else
7601 R[d] = result;
7602 if setflags then
7603 APSR.N = result<31>;
7604 APSR.Z = IsZeroBit(result);
7605 APSR.C = carry;
7606 // APSR.V unchanged
7607#endif
7608
7609 bool success = false;
7610 const uint32_t opcode = OpcodeAsUnsigned (&success);
7611 if (!success)
7612 return false;
7613
7614 if (ConditionPassed())
7615 {
7616 uint32_t Rd, Rn;
7617 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7618 bool setflags;
7619 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7620 switch (encoding)
7621 {
7622 case eEncodingT1:
7623 Rd = Bits32(opcode, 11, 8);
7624 Rn = Bits32(opcode, 19, 16);
7625 setflags = BitIsSet(opcode, 20);
7626 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7627 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
7628 if (Rd == 15 && setflags)
7629 return EmulateTEQImm(eEncodingT1);
7630 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
7631 return false;
7632 break;
7633 case eEncodingA1:
7634 Rd = Bits32(opcode, 15, 12);
7635 Rn = Bits32(opcode, 19, 16);
7636 setflags = BitIsSet(opcode, 20);
7637 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7638 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7639 // TODO: Emulate SUBS PC, LR and related instructions.
7640 if (Rd == 15 && setflags)
7641 return false;
7642 break;
7643 default:
7644 return false;
7645 }
7646
7647 // Read the first operand.
7648 uint32_t val1 = ReadCoreReg(Rn, &success);
7649 if (!success)
7650 return false;
7651
7652 uint32_t result = val1 ^ imm32;
7653
7654 EmulateInstruction::Context context;
7655 context.type = EmulateInstruction::eContextImmediate;
7656 context.SetNoArgs ();
7657
7658 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7659 return false;
7660 }
7661 return true;
7662}
7663
7664// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
7665// optionally-shifted register value, and writes the result to the destination register.
7666// It can optionally update the condition flags based on the result.
7667bool
7668EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
7669{
7670#if 0
7671 // ARM pseudo code...
7672 if ConditionPassed() then
7673 EncodingSpecificOperations();
7674 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7675 result = R[n] EOR shifted;
7676 if d == 15 then // Can only occur for ARM encoding
7677 ALUWritePC(result); // setflags is always FALSE here
7678 else
7679 R[d] = result;
7680 if setflags then
7681 APSR.N = result<31>;
7682 APSR.Z = IsZeroBit(result);
7683 APSR.C = carry;
7684 // APSR.V unchanged
7685#endif
7686
7687 bool success = false;
7688 const uint32_t opcode = OpcodeAsUnsigned (&success);
7689 if (!success)
7690 return false;
7691
7692 if (ConditionPassed())
7693 {
7694 uint32_t Rd, Rn, Rm;
7695 ARM_ShifterType shift_t;
7696 uint32_t shift_n; // the shift applied to the value read from Rm
7697 bool setflags;
7698 uint32_t carry;
7699 switch (encoding)
7700 {
7701 case eEncodingT1:
7702 Rd = Rn = Bits32(opcode, 2, 0);
7703 Rm = Bits32(opcode, 5, 3);
7704 setflags = !InITBlock();
7705 shift_t = SRType_LSL;
7706 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007707 break;
Johnny Chen2115b412011-02-21 23:42:44 +00007708 case eEncodingT2:
7709 Rd = Bits32(opcode, 11, 8);
7710 Rn = Bits32(opcode, 19, 16);
7711 Rm = Bits32(opcode, 3, 0);
7712 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007713 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7714 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00007715 if (Rd == 15 && setflags)
7716 return EmulateTEQReg(eEncodingT1);
7717 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
7718 return false;
7719 break;
7720 case eEncodingA1:
7721 Rd = Bits32(opcode, 15, 12);
7722 Rn = Bits32(opcode, 19, 16);
7723 Rm = Bits32(opcode, 3, 0);
7724 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007725 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00007726 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7727 // TODO: Emulate SUBS PC, LR and related instructions.
7728 if (Rd == 15 && setflags)
7729 return false;
7730 break;
7731 default:
7732 return false;
7733 }
7734
7735 // Read the first operand.
7736 uint32_t val1 = ReadCoreReg(Rn, &success);
7737 if (!success)
7738 return false;
7739
7740 // Read the second operand.
7741 uint32_t val2 = ReadCoreReg(Rm, &success);
7742 if (!success)
7743 return false;
7744
7745 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
7746 uint32_t result = val1 ^ shifted;
7747
7748 EmulateInstruction::Context context;
7749 context.type = EmulateInstruction::eContextImmediate;
7750 context.SetNoArgs ();
7751
7752 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7753 return false;
7754 }
7755 return true;
7756}
7757
Johnny Chen7c5234d2011-02-18 23:41:11 +00007758// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
7759// writes the result to the destination register. It can optionally update the condition flags based
7760// on the result.
7761bool
7762EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
7763{
7764#if 0
7765 // ARM pseudo code...
7766 if ConditionPassed() then
7767 EncodingSpecificOperations();
7768 result = R[n] OR imm32;
7769 if d == 15 then // Can only occur for ARM encoding
7770 ALUWritePC(result); // setflags is always FALSE here
7771 else
7772 R[d] = result;
7773 if setflags then
7774 APSR.N = result<31>;
7775 APSR.Z = IsZeroBit(result);
7776 APSR.C = carry;
7777 // APSR.V unchanged
7778#endif
7779
7780 bool success = false;
7781 const uint32_t opcode = OpcodeAsUnsigned (&success);
7782 if (!success)
7783 return false;
7784
7785 if (ConditionPassed())
7786 {
7787 uint32_t Rd, Rn;
7788 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7789 bool setflags;
7790 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7791 switch (encoding)
7792 {
7793 case eEncodingT1:
7794 Rd = Bits32(opcode, 11, 8);
7795 Rn = Bits32(opcode, 19, 16);
7796 setflags = BitIsSet(opcode, 20);
7797 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7798 // if Rn == ‘1111’ then SEE MOV (immediate);
7799 if (Rn == 15)
7800 return EmulateMOVRdImm(eEncodingT2);
7801 if (BadReg(Rd) || Rn == 13)
7802 return false;
7803 break;
7804 case eEncodingA1:
7805 Rd = Bits32(opcode, 15, 12);
7806 Rn = Bits32(opcode, 19, 16);
7807 setflags = BitIsSet(opcode, 20);
7808 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7809 // TODO: Emulate SUBS PC, LR and related instructions.
7810 if (Rd == 15 && setflags)
7811 return false;
7812 break;
7813 default:
7814 return false;
7815 }
7816
7817 // Read the first operand.
7818 uint32_t val1 = ReadCoreReg(Rn, &success);
7819 if (!success)
7820 return false;
7821
7822 uint32_t result = val1 | imm32;
7823
7824 EmulateInstruction::Context context;
7825 context.type = EmulateInstruction::eContextImmediate;
7826 context.SetNoArgs ();
7827
7828 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7829 return false;
7830 }
7831 return true;
7832}
7833
7834// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
7835// value, and writes the result to the destination register. It can optionally update the condition flags based
7836// on the result.
7837bool
7838EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
7839{
7840#if 0
7841 // ARM pseudo code...
7842 if ConditionPassed() then
7843 EncodingSpecificOperations();
7844 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7845 result = R[n] OR shifted;
7846 if d == 15 then // Can only occur for ARM encoding
7847 ALUWritePC(result); // setflags is always FALSE here
7848 else
7849 R[d] = result;
7850 if setflags then
7851 APSR.N = result<31>;
7852 APSR.Z = IsZeroBit(result);
7853 APSR.C = carry;
7854 // APSR.V unchanged
7855#endif
7856
7857 bool success = false;
7858 const uint32_t opcode = OpcodeAsUnsigned (&success);
7859 if (!success)
7860 return false;
7861
7862 if (ConditionPassed())
7863 {
7864 uint32_t Rd, Rn, Rm;
7865 ARM_ShifterType shift_t;
7866 uint32_t shift_n; // the shift applied to the value read from Rm
7867 bool setflags;
7868 uint32_t carry;
7869 switch (encoding)
7870 {
7871 case eEncodingT1:
7872 Rd = Rn = Bits32(opcode, 2, 0);
7873 Rm = Bits32(opcode, 5, 3);
7874 setflags = !InITBlock();
7875 shift_t = SRType_LSL;
7876 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007877 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00007878 case eEncodingT2:
7879 Rd = Bits32(opcode, 11, 8);
7880 Rn = Bits32(opcode, 19, 16);
7881 Rm = Bits32(opcode, 3, 0);
7882 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007883 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7884 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00007885 if (Rn == 15)
7886 return EmulateMOVRdRm(eEncodingT3);
7887 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
7888 return false;
7889 break;
7890 case eEncodingA1:
7891 Rd = Bits32(opcode, 15, 12);
7892 Rn = Bits32(opcode, 19, 16);
7893 Rm = Bits32(opcode, 3, 0);
7894 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007895 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00007896 // TODO: Emulate SUBS PC, LR and related instructions.
7897 if (Rd == 15 && setflags)
7898 return false;
7899 break;
7900 default:
7901 return false;
7902 }
7903
7904 // Read the first operand.
7905 uint32_t val1 = ReadCoreReg(Rn, &success);
7906 if (!success)
7907 return false;
7908
7909 // Read the second operand.
7910 uint32_t val2 = ReadCoreReg(Rm, &success);
7911 if (!success)
7912 return false;
7913
7914 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00007915 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00007916
7917 EmulateInstruction::Context context;
7918 context.type = EmulateInstruction::eContextImmediate;
7919 context.SetNoArgs ();
7920
7921 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7922 return false;
7923 }
7924 return true;
7925}
7926
Johnny Chened32e7c2011-02-22 23:42:58 +00007927// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
7928// the destination register. It can optionally update the condition flags based on the result.
7929bool
7930EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
7931{
7932#if 0
7933 // ARM pseudo code...
7934 if ConditionPassed() then
7935 EncodingSpecificOperations();
7936 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
7937 if d == 15 then // Can only occur for ARM encoding
7938 ALUWritePC(result); // setflags is always FALSE here
7939 else
7940 R[d] = result;
7941 if setflags then
7942 APSR.N = result<31>;
7943 APSR.Z = IsZeroBit(result);
7944 APSR.C = carry;
7945 APSR.V = overflow;
7946#endif
7947
7948 bool success = false;
7949 const uint32_t opcode = OpcodeAsUnsigned (&success);
7950 if (!success)
7951 return false;
7952
7953 uint32_t Rd; // the destination register
7954 uint32_t Rn; // the first operand
7955 bool setflags;
7956 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
7957 switch (encoding) {
7958 case eEncodingT1:
7959 Rd = Bits32(opcode, 2, 0);
7960 Rn = Bits32(opcode, 5, 3);
7961 setflags = !InITBlock();
7962 imm32 = 0;
7963 break;
7964 case eEncodingT2:
7965 Rd = Bits32(opcode, 11, 8);
7966 Rn = Bits32(opcode, 19, 16);
7967 setflags = BitIsSet(opcode, 20);
7968 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
7969 if (BadReg(Rd) || BadReg(Rn))
7970 return false;
7971 break;
7972 case eEncodingA1:
7973 Rd = Bits32(opcode, 15, 12);
7974 Rn = Bits32(opcode, 19, 16);
7975 setflags = BitIsSet(opcode, 20);
7976 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7977 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7978 // TODO: Emulate SUBS PC, LR and related instructions.
7979 if (Rd == 15 && setflags)
7980 return false;
7981 break;
7982 default:
7983 return false;
7984 }
7985 // Read the register value from the operand register Rn.
7986 uint32_t reg_val = ReadCoreReg(Rn, &success);
7987 if (!success)
7988 return false;
7989
7990 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
7991
7992 EmulateInstruction::Context context;
7993 context.type = EmulateInstruction::eContextImmediate;
7994 context.SetNoArgs ();
7995
7996 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7997 return false;
7998
7999 return true;
8000}
8001
8002// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8003// result to the destination register. It can optionally update the condition flags based on the result.
8004bool
8005EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
8006{
8007#if 0
8008 // ARM pseudo code...
8009 if ConditionPassed() then
8010 EncodingSpecificOperations();
8011 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8012 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8013 if d == 15 then // Can only occur for ARM encoding
8014 ALUWritePC(result); // setflags is always FALSE here
8015 else
8016 R[d] = result;
8017 if setflags then
8018 APSR.N = result<31>;
8019 APSR.Z = IsZeroBit(result);
8020 APSR.C = carry;
8021 APSR.V = overflow;
8022#endif
8023
8024 bool success = false;
8025 const uint32_t opcode = OpcodeAsUnsigned (&success);
8026 if (!success)
8027 return false;
8028
8029 uint32_t Rd; // the destination register
8030 uint32_t Rn; // the first operand
8031 uint32_t Rm; // the second operand
8032 bool setflags;
8033 ARM_ShifterType shift_t;
8034 uint32_t shift_n; // the shift applied to the value read from Rm
8035 switch (encoding) {
8036 case eEncodingT1:
8037 Rd = Bits32(opcode, 11, 8);
8038 Rn = Bits32(opcode, 19, 16);
8039 Rm = Bits32(opcode, 3, 0);
8040 setflags = BitIsSet(opcode, 20);
8041 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8042 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8043 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8044 return false;
8045 break;
8046 case eEncodingA1:
8047 Rd = Bits32(opcode, 15, 12);
8048 Rn = Bits32(opcode, 19, 16);
8049 Rm = Bits32(opcode, 3, 0);
8050 setflags = BitIsSet(opcode, 20);
8051 shift_n = DecodeImmShiftARM(opcode, shift_t);
8052 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8053 // TODO: Emulate SUBS PC, LR and related instructions.
8054 if (Rd == 15 && setflags)
8055 return false;
8056 break;
8057 default:
8058 return false;
8059 }
8060 // Read the register value from register Rn.
8061 uint32_t val1 = ReadCoreReg(Rn, &success);
8062 if (!success)
8063 return false;
8064
8065 // Read the register value from register Rm.
8066 uint32_t val2 = ReadCoreReg(Rm, &success);
8067 if (!success)
8068 return false;
8069
8070 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8071 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8072
8073 EmulateInstruction::Context context;
8074 context.type = EmulateInstruction::eContextImmediate;
8075 context.SetNoArgs();
8076 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8077 return false;
8078
8079 return true;
8080}
8081
Johnny Chen90e607b2011-02-23 00:07:09 +00008082// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8083// an immediate value, and writes the result to the destination register. It can optionally update the condition
8084// flags based on the result.
8085bool
8086EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
8087{
8088#if 0
8089 // ARM pseudo code...
8090 if ConditionPassed() then
8091 EncodingSpecificOperations();
8092 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8093 if d == 15 then
8094 ALUWritePC(result); // setflags is always FALSE here
8095 else
8096 R[d] = result;
8097 if setflags then
8098 APSR.N = result<31>;
8099 APSR.Z = IsZeroBit(result);
8100 APSR.C = carry;
8101 APSR.V = overflow;
8102#endif
8103
8104 bool success = false;
8105 const uint32_t opcode = OpcodeAsUnsigned (&success);
8106 if (!success)
8107 return false;
8108
8109 uint32_t Rd; // the destination register
8110 uint32_t Rn; // the first operand
8111 bool setflags;
8112 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8113 switch (encoding) {
8114 case eEncodingA1:
8115 Rd = Bits32(opcode, 15, 12);
8116 Rn = Bits32(opcode, 19, 16);
8117 setflags = BitIsSet(opcode, 20);
8118 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8119 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8120 // TODO: Emulate SUBS PC, LR and related instructions.
8121 if (Rd == 15 && setflags)
8122 return false;
8123 break;
8124 default:
8125 return false;
8126 }
8127 // Read the register value from the operand register Rn.
8128 uint32_t reg_val = ReadCoreReg(Rn, &success);
8129 if (!success)
8130 return false;
8131
8132 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8133
8134 EmulateInstruction::Context context;
8135 context.type = EmulateInstruction::eContextImmediate;
8136 context.SetNoArgs ();
8137
8138 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8139 return false;
8140
8141 return true;
8142}
8143
8144// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8145// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8146// condition flags based on the result.
8147bool
8148EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
8149{
8150#if 0
8151 // ARM pseudo code...
8152 if ConditionPassed() then
8153 EncodingSpecificOperations();
8154 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8155 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8156 if d == 15 then
8157 ALUWritePC(result); // setflags is always FALSE here
8158 else
8159 R[d] = result;
8160 if setflags then
8161 APSR.N = result<31>;
8162 APSR.Z = IsZeroBit(result);
8163 APSR.C = carry;
8164 APSR.V = overflow;
8165#endif
8166
8167 bool success = false;
8168 const uint32_t opcode = OpcodeAsUnsigned (&success);
8169 if (!success)
8170 return false;
8171
8172 uint32_t Rd; // the destination register
8173 uint32_t Rn; // the first operand
8174 uint32_t Rm; // the second operand
8175 bool setflags;
8176 ARM_ShifterType shift_t;
8177 uint32_t shift_n; // the shift applied to the value read from Rm
8178 switch (encoding) {
8179 case eEncodingA1:
8180 Rd = Bits32(opcode, 15, 12);
8181 Rn = Bits32(opcode, 19, 16);
8182 Rm = Bits32(opcode, 3, 0);
8183 setflags = BitIsSet(opcode, 20);
8184 shift_n = DecodeImmShiftARM(opcode, shift_t);
8185 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8186 // TODO: Emulate SUBS PC, LR and related instructions.
8187 if (Rd == 15 && setflags)
8188 return false;
8189 break;
8190 default:
8191 return false;
8192 }
8193 // Read the register value from register Rn.
8194 uint32_t val1 = ReadCoreReg(Rn, &success);
8195 if (!success)
8196 return false;
8197
8198 // Read the register value from register Rm.
8199 uint32_t val2 = ReadCoreReg(Rm, &success);
8200 if (!success)
8201 return false;
8202
8203 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8204 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8205
8206 EmulateInstruction::Context context;
8207 context.type = EmulateInstruction::eContextImmediate;
8208 context.SetNoArgs();
8209 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8210 return false;
8211
8212 return true;
8213}
8214
Johnny Chen9b381772011-02-23 01:01:21 +00008215// Subtract with Carry (immediate) subtracts an immediate value and the value of
8216// NOT (Carry flag) from a register value, and writes the result to the destination register.
8217// It can optionally update the condition flags based on the result.
8218bool
8219EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
8220{
8221#if 0
8222 // ARM pseudo code...
8223 if ConditionPassed() then
8224 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008225 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008226 if d == 15 then // Can only occur for ARM encoding
8227 ALUWritePC(result); // setflags is always FALSE here
8228 else
8229 R[d] = result;
8230 if setflags then
8231 APSR.N = result<31>;
8232 APSR.Z = IsZeroBit(result);
8233 APSR.C = carry;
8234 APSR.V = overflow;
8235#endif
8236
8237 bool success = false;
8238 const uint32_t opcode = OpcodeAsUnsigned (&success);
8239 if (!success)
8240 return false;
8241
8242 uint32_t Rd; // the destination register
8243 uint32_t Rn; // the first operand
8244 bool setflags;
8245 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8246 switch (encoding) {
8247 case eEncodingT1:
8248 Rd = Bits32(opcode, 11, 8);
8249 Rn = Bits32(opcode, 19, 16);
8250 setflags = BitIsSet(opcode, 20);
8251 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8252 if (BadReg(Rd) || BadReg(Rn))
8253 return false;
8254 break;
8255 case eEncodingA1:
8256 Rd = Bits32(opcode, 15, 12);
8257 Rn = Bits32(opcode, 19, 16);
8258 setflags = BitIsSet(opcode, 20);
8259 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8260 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8261 // TODO: Emulate SUBS PC, LR and related instructions.
8262 if (Rd == 15 && setflags)
8263 return false;
8264 break;
8265 default:
8266 return false;
8267 }
8268 // Read the register value from the operand register Rn.
8269 uint32_t reg_val = ReadCoreReg(Rn, &success);
8270 if (!success)
8271 return false;
8272
8273 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8274
8275 EmulateInstruction::Context context;
8276 context.type = EmulateInstruction::eContextImmediate;
8277 context.SetNoArgs ();
8278
8279 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8280 return false;
8281
8282 return true;
8283}
8284
8285// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8286// NOT (Carry flag) from a register value, and writes the result to the destination register.
8287// It can optionally update the condition flags based on the result.
8288bool
8289EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8290{
8291#if 0
8292 // ARM pseudo code...
8293 if ConditionPassed() then
8294 EncodingSpecificOperations();
8295 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8296 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8297 if d == 15 then // Can only occur for ARM encoding
8298 ALUWritePC(result); // setflags is always FALSE here
8299 else
8300 R[d] = result;
8301 if setflags then
8302 APSR.N = result<31>;
8303 APSR.Z = IsZeroBit(result);
8304 APSR.C = carry;
8305 APSR.V = overflow;
8306#endif
8307
8308 bool success = false;
8309 const uint32_t opcode = OpcodeAsUnsigned (&success);
8310 if (!success)
8311 return false;
8312
8313 uint32_t Rd; // the destination register
8314 uint32_t Rn; // the first operand
8315 uint32_t Rm; // the second operand
8316 bool setflags;
8317 ARM_ShifterType shift_t;
8318 uint32_t shift_n; // the shift applied to the value read from Rm
8319 switch (encoding) {
8320 case eEncodingT1:
8321 Rd = Rn = Bits32(opcode, 2, 0);
8322 Rm = Bits32(opcode, 5, 3);
8323 setflags = !InITBlock();
8324 shift_t = SRType_LSL;
8325 shift_n = 0;
8326 break;
8327 case eEncodingT2:
8328 Rd = Bits32(opcode, 11, 8);
8329 Rn = Bits32(opcode, 19, 16);
8330 Rm = Bits32(opcode, 3, 0);
8331 setflags = BitIsSet(opcode, 20);
8332 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8333 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8334 return false;
8335 break;
8336 case eEncodingA1:
8337 Rd = Bits32(opcode, 15, 12);
8338 Rn = Bits32(opcode, 19, 16);
8339 Rm = Bits32(opcode, 3, 0);
8340 setflags = BitIsSet(opcode, 20);
8341 shift_n = DecodeImmShiftARM(opcode, shift_t);
8342 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8343 // TODO: Emulate SUBS PC, LR and related instructions.
8344 if (Rd == 15 && setflags)
8345 return false;
8346 break;
8347 default:
8348 return false;
8349 }
8350 // Read the register value from register Rn.
8351 uint32_t val1 = ReadCoreReg(Rn, &success);
8352 if (!success)
8353 return false;
8354
8355 // Read the register value from register Rm.
8356 uint32_t val2 = ReadCoreReg(Rm, &success);
8357 if (!success)
8358 return false;
8359
8360 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8361 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8362
8363 EmulateInstruction::Context context;
8364 context.type = EmulateInstruction::eContextImmediate;
8365 context.SetNoArgs();
8366 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8367 return false;
8368
8369 return true;
8370}
8371
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008372// This instruction subtracts an immediate value from a register value, and writes the result
8373// to the destination register. It can optionally update the condition flags based on the result.
8374bool
8375EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8376{
8377#if 0
8378 // ARM pseudo code...
8379 if ConditionPassed() then
8380 EncodingSpecificOperations();
8381 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8382 R[d] = result;
8383 if setflags then
8384 APSR.N = result<31>;
8385 APSR.Z = IsZeroBit(result);
8386 APSR.C = carry;
8387 APSR.V = overflow;
8388#endif
8389
8390 bool success = false;
8391 const uint32_t opcode = OpcodeAsUnsigned (&success);
8392 if (!success)
8393 return false;
8394
8395 uint32_t Rd; // the destination register
8396 uint32_t Rn; // the first operand
8397 bool setflags;
8398 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8399 switch (encoding) {
8400 case eEncodingT1:
8401 Rd = Bits32(opcode, 2, 0);
8402 Rn = Bits32(opcode, 5, 3);
8403 setflags = !InITBlock();
8404 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8405 break;
8406 case eEncodingT2:
8407 Rd = Rn = Bits32(opcode, 10, 8);
8408 setflags = !InITBlock();
8409 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8410 break;
8411 case eEncodingT3:
8412 Rd = Bits32(opcode, 11, 8);
8413 Rn = Bits32(opcode, 19, 16);
8414 setflags = BitIsSet(opcode, 20);
8415 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8416
8417 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8418 if (Rd == 15 && setflags)
8419 return EmulateCMPImm(eEncodingT2);
8420
8421 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8422 if (Rn == 13)
8423 return EmulateSUBSPImm(eEncodingT2);
8424
8425 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8426 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8427 return false;
8428 break;
8429 case eEncodingT4:
8430 Rd = Bits32(opcode, 11, 8);
8431 Rn = Bits32(opcode, 19, 16);
8432 setflags = BitIsSet(opcode, 20);
8433 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8434
8435 // if Rn == '1111' then SEE ADR;
8436 if (Rn == 15)
8437 return EmulateADR(eEncodingT2);
8438
8439 // if Rn == '1101' then SEE SUB (SP minus immediate);
8440 if (Rn == 13)
8441 return EmulateSUBSPImm(eEncodingT3);
8442
8443 if (BadReg(Rd))
8444 return false;
8445 break;
8446 default:
8447 return false;
8448 }
8449 // Read the register value from the operand register Rn.
8450 uint32_t reg_val = ReadCoreReg(Rn, &success);
8451 if (!success)
8452 return false;
8453
8454 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8455
8456 EmulateInstruction::Context context;
8457 context.type = EmulateInstruction::eContextImmediate;
8458 context.SetNoArgs ();
8459
8460 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8461 return false;
8462
8463 return true;
8464}
8465
8466// This instruction subtracts an immediate value from a register value, and writes the result
8467// to the destination register. It can optionally update the condition flags based on the result.
8468bool
8469EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
8470{
8471#if 0
8472 // ARM pseudo code...
8473 if ConditionPassed() then
8474 EncodingSpecificOperations();
8475 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8476 if d == 15 then
8477 ALUWritePC(result); // setflags is always FALSE here
8478 else
8479 R[d] = result;
8480 if setflags then
8481 APSR.N = result<31>;
8482 APSR.Z = IsZeroBit(result);
8483 APSR.C = carry;
8484 APSR.V = overflow;
8485#endif
8486
8487 bool success = false;
8488 const uint32_t opcode = OpcodeAsUnsigned (&success);
8489 if (!success)
8490 return false;
8491
8492 uint32_t Rd; // the destination register
8493 uint32_t Rn; // the first operand
8494 bool setflags;
8495 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8496 switch (encoding) {
8497 case eEncodingA1:
8498 Rd = Bits32(opcode, 15, 12);
8499 Rn = Bits32(opcode, 19, 16);
8500 setflags = BitIsSet(opcode, 20);
8501 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8502
8503 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
8504 if (Rn == 15 && !setflags)
8505 return EmulateADR(eEncodingA2);
8506
8507 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8508 if (Rn == 13)
8509 return EmulateSUBSPImm(eEncodingA1);
8510
8511 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8512 // TODO: Emulate SUBS PC, LR and related instructions.
8513 if (Rd == 15 && setflags)
8514 return false;
8515 break;
8516 default:
8517 return false;
8518 }
8519 // Read the register value from the operand register Rn.
8520 uint32_t reg_val = ReadCoreReg(Rn, &success);
8521 if (!success)
8522 return false;
8523
8524 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8525
8526 EmulateInstruction::Context context;
8527 context.type = EmulateInstruction::eContextImmediate;
8528 context.SetNoArgs ();
8529
8530 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8531 return false;
8532
8533 return true;
8534}
8535
Johnny Chen2115b412011-02-21 23:42:44 +00008536// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8537// immediate value. It updates the condition flags based on the result, and discards the result.
8538bool
8539EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
8540{
8541#if 0
8542 // ARM pseudo code...
8543 if ConditionPassed() then
8544 EncodingSpecificOperations();
8545 result = R[n] EOR imm32;
8546 APSR.N = result<31>;
8547 APSR.Z = IsZeroBit(result);
8548 APSR.C = carry;
8549 // APSR.V unchanged
8550#endif
8551
8552 bool success = false;
8553 const uint32_t opcode = OpcodeAsUnsigned (&success);
8554 if (!success)
8555 return false;
8556
8557 if (ConditionPassed())
8558 {
8559 uint32_t Rn;
8560 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8561 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8562 switch (encoding)
8563 {
8564 case eEncodingT1:
8565 Rn = Bits32(opcode, 19, 16);
8566 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8567 if (BadReg(Rn))
8568 return false;
8569 break;
8570 case eEncodingA1:
8571 Rn = Bits32(opcode, 19, 16);
8572 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8573 break;
8574 default:
8575 return false;
8576 }
8577
8578 // Read the first operand.
8579 uint32_t val1 = ReadCoreReg(Rn, &success);
8580 if (!success)
8581 return false;
8582
8583 uint32_t result = val1 ^ imm32;
8584
8585 EmulateInstruction::Context context;
8586 context.type = EmulateInstruction::eContextImmediate;
8587 context.SetNoArgs ();
8588
8589 if (!WriteFlags(context, result, carry))
8590 return false;
8591 }
8592 return true;
8593}
8594
8595// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8596// optionally-shifted register value. It updates the condition flags based on the result, and discards
8597// the result.
8598bool
8599EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
8600{
8601#if 0
8602 // ARM pseudo code...
8603 if ConditionPassed() then
8604 EncodingSpecificOperations();
8605 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8606 result = R[n] EOR shifted;
8607 APSR.N = result<31>;
8608 APSR.Z = IsZeroBit(result);
8609 APSR.C = carry;
8610 // APSR.V unchanged
8611#endif
8612
8613 bool success = false;
8614 const uint32_t opcode = OpcodeAsUnsigned (&success);
8615 if (!success)
8616 return false;
8617
8618 if (ConditionPassed())
8619 {
8620 uint32_t Rn, Rm;
8621 ARM_ShifterType shift_t;
8622 uint32_t shift_n; // the shift applied to the value read from Rm
8623 uint32_t carry;
8624 switch (encoding)
8625 {
8626 case eEncodingT1:
8627 Rn = Bits32(opcode, 19, 16);
8628 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008629 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008630 if (BadReg(Rn) || BadReg(Rm))
8631 return false;
8632 break;
8633 case eEncodingA1:
8634 Rn = Bits32(opcode, 19, 16);
8635 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008636 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008637 break;
8638 default:
8639 return false;
8640 }
8641
8642 // Read the first operand.
8643 uint32_t val1 = ReadCoreReg(Rn, &success);
8644 if (!success)
8645 return false;
8646
8647 // Read the second operand.
8648 uint32_t val2 = ReadCoreReg(Rm, &success);
8649 if (!success)
8650 return false;
8651
8652 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8653 uint32_t result = val1 ^ shifted;
8654
8655 EmulateInstruction::Context context;
8656 context.type = EmulateInstruction::eContextImmediate;
8657 context.SetNoArgs ();
8658
8659 if (!WriteFlags(context, result, carry))
8660 return false;
8661 }
8662 return true;
8663}
8664
Johnny Chende3cce32011-02-21 21:24:49 +00008665// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
8666// It updates the condition flags based on the result, and discards the result.
8667bool
8668EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
8669{
8670#if 0
8671 // ARM pseudo code...
8672 if ConditionPassed() then
8673 EncodingSpecificOperations();
8674 result = R[n] AND imm32;
8675 APSR.N = result<31>;
8676 APSR.Z = IsZeroBit(result);
8677 APSR.C = carry;
8678 // APSR.V unchanged
8679#endif
8680
8681 bool success = false;
8682 const uint32_t opcode = OpcodeAsUnsigned (&success);
8683 if (!success)
8684 return false;
8685
8686 if (ConditionPassed())
8687 {
8688 uint32_t Rn;
8689 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8690 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8691 switch (encoding)
8692 {
8693 case eEncodingT1:
8694 Rn = Bits32(opcode, 19, 16);
8695 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8696 if (BadReg(Rn))
8697 return false;
8698 break;
8699 case eEncodingA1:
8700 Rn = Bits32(opcode, 19, 16);
8701 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8702 break;
8703 default:
8704 return false;
8705 }
8706
8707 // Read the first operand.
8708 uint32_t val1 = ReadCoreReg(Rn, &success);
8709 if (!success)
8710 return false;
8711
8712 uint32_t result = val1 & imm32;
8713
8714 EmulateInstruction::Context context;
8715 context.type = EmulateInstruction::eContextImmediate;
8716 context.SetNoArgs ();
8717
8718 if (!WriteFlags(context, result, carry))
8719 return false;
8720 }
8721 return true;
8722}
8723
8724// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
8725// It updates the condition flags based on the result, and discards the result.
8726bool
8727EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
8728{
8729#if 0
8730 // ARM pseudo code...
8731 if ConditionPassed() then
8732 EncodingSpecificOperations();
8733 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8734 result = R[n] AND shifted;
8735 APSR.N = result<31>;
8736 APSR.Z = IsZeroBit(result);
8737 APSR.C = carry;
8738 // APSR.V unchanged
8739#endif
8740
8741 bool success = false;
8742 const uint32_t opcode = OpcodeAsUnsigned (&success);
8743 if (!success)
8744 return false;
8745
8746 if (ConditionPassed())
8747 {
8748 uint32_t Rn, Rm;
8749 ARM_ShifterType shift_t;
8750 uint32_t shift_n; // the shift applied to the value read from Rm
8751 uint32_t carry;
8752 switch (encoding)
8753 {
8754 case eEncodingT1:
8755 Rn = Bits32(opcode, 2, 0);
8756 Rm = Bits32(opcode, 5, 3);
8757 shift_t = SRType_LSL;
8758 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008759 break;
Johnny Chende3cce32011-02-21 21:24:49 +00008760 case eEncodingT2:
8761 Rn = Bits32(opcode, 19, 16);
8762 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008763 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00008764 if (BadReg(Rn) || BadReg(Rm))
8765 return false;
8766 break;
8767 case eEncodingA1:
8768 Rn = Bits32(opcode, 19, 16);
8769 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008770 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00008771 break;
8772 default:
8773 return false;
8774 }
8775
8776 // Read the first operand.
8777 uint32_t val1 = ReadCoreReg(Rn, &success);
8778 if (!success)
8779 return false;
8780
8781 // Read the second operand.
8782 uint32_t val2 = ReadCoreReg(Rm, &success);
8783 if (!success)
8784 return false;
8785
8786 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8787 uint32_t result = val1 & shifted;
8788
8789 EmulateInstruction::Context context;
8790 context.type = EmulateInstruction::eContextImmediate;
8791 context.SetNoArgs ();
8792
8793 if (!WriteFlags(context, result, carry))
8794 return false;
8795 }
8796 return true;
8797}
8798
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008799EmulateInstructionARM::ARMOpcode*
8800EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00008801{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008802 static ARMOpcode
8803 g_arm_opcodes[] =
8804 {
8805 //----------------------------------------------------------------------
8806 // Prologue instructions
8807 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00008808
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008809 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00008810 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
8811 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00008812
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008813 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00008814 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00008815 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00008816 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00008817 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
8818 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00008819 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00008820
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008821 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00008822 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00008823
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008824 // push one register
8825 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00008826 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00008827
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008828 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00008829 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
8830 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00008831
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008832 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00008833 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008834 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00008835
Johnny Chen9f687722011-02-18 00:02:28 +00008836 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
8837 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00008838 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008839 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
8840
8841 //----------------------------------------------------------------------
8842 // Supervisor Call (previously Software Interrupt)
8843 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00008844 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
8845
8846 //----------------------------------------------------------------------
8847 // Branch instructions
8848 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00008849 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00008850 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
8851 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
8852 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
8853 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00008854 // for example, "bx lr"
8855 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00008856 // bxj
8857 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008858
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008859 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00008860 // Data-processing instructions
8861 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00008862 // adc (immediate)
8863 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
8864 // adc (register)
8865 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00008866 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008867 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00008868 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00008869 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00008870 // adr
8871 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
8872 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008873 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008874 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008875 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00008876 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00008877 // bic (immediate)
8878 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
8879 // bic (register)
8880 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00008881 // eor (immediate)
8882 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
8883 // eor (register)
8884 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008885 // orr (immediate)
8886 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
8887 // orr (register)
8888 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00008889 // rsb (immediate)
8890 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
8891 // rsb (register)
8892 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00008893 // rsc (immediate)
8894 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
8895 // rsc (register)
8896 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00008897 // sbc (immediate)
8898 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
8899 // sbc (register)
8900 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008901 // sub (immediate, ARM)
8902 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008903 // sub (sp minus immediate)
8904 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00008905 // teq (immediate)
8906 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
8907 // teq (register)
8908 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00008909 // tst (immediate)
8910 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
8911 // tst (register)
8912 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
8913
8914
Johnny Chen01d61572011-02-25 00:23:25 +00008915 // mov (register)
8916 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00008917 // mvn (immediate)
8918 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
8919 // mvn (register)
8920 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00008921 // cmn (immediate)
8922 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
8923 // cmn (register)
8924 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008925 // cmp (immediate)
8926 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
8927 // cmp (register)
8928 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00008929 // asr (immediate)
8930 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008931 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00008932 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008933 // lsl (immediate)
8934 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
8935 // lsl (register)
8936 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
8937 // lsr (immediate)
8938 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
8939 // lsr (register)
8940 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00008941 // rrx is a special case encoding of ror (immediate)
8942 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
8943 // ror (immediate)
8944 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
8945 // ror (register)
8946 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00008947 // mul
8948 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00008949
8950 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008951 // Load instructions
8952 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00008953 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00008954 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00008955 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00008956 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00008957 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00008958 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00008959 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00008960 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00008961 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00008962 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00008963 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00008964 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00008965 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00008966 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00008967 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
8968 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00008969
8970 //----------------------------------------------------------------------
8971 // Store instructions
8972 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00008973 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00008974 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00008975 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00008976 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00008977 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00008978
Caroline Tice6bf65162011-03-03 17:42:58 +00008979 //----------------------------------------------------------------------
8980 // Other instructions
8981 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00008982 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
8983 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00008984
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008985 };
8986 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
8987
8988 for (size_t i=0; i<k_num_arm_opcodes; ++i)
8989 {
8990 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
8991 return &g_arm_opcodes[i];
8992 }
8993 return NULL;
8994}
Greg Clayton64c84432011-01-21 22:02:52 +00008995
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008996
8997EmulateInstructionARM::ARMOpcode*
8998EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00008999{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009000
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009001 static ARMOpcode
9002 g_thumb_opcodes[] =
9003 {
9004 //----------------------------------------------------------------------
9005 // Prologue instructions
9006 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009007
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009008 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009009 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9010 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9011 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009012
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009013 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009014 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009015 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009016 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009017 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009018 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009019
Johnny Chen864a8e82011-02-18 00:07:39 +00009020 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009021 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009022
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009023 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009024 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009025 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009026 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9027 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009028
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009029 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009030 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9031 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009032
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009033 //----------------------------------------------------------------------
9034 // Epilogue instructions
9035 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009036
Johnny Chen864a8e82011-02-18 00:07:39 +00009037 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009038 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9039 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9040 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009041 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9042 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009043
9044 //----------------------------------------------------------------------
9045 // Supervisor Call (previously Software Interrupt)
9046 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009047 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9048
9049 //----------------------------------------------------------------------
9050 // If Then makes up to four following instructions conditional.
9051 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009052 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9053
9054 //----------------------------------------------------------------------
9055 // Branch instructions
9056 //----------------------------------------------------------------------
9057 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9058 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009059 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009060 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009061 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009062 // J1 == J2 == 1
9063 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9064 // J1 == J2 == 1
9065 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9066 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009067 // for example, "bx lr"
9068 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009069 // bxj
9070 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009071 // compare and branch
9072 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009073 // table branch byte
9074 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9075 // table branch halfword
9076 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009077
9078 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009079 // Data-processing instructions
9080 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009081 // adc (immediate)
9082 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9083 // adc (register)
9084 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9085 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9086 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009087 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009088 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009089 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009090 // adr
9091 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9092 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9093 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009094 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009095 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009096 // and (register)
9097 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9098 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009099 // bic (immediate)
9100 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9101 // bic (register)
9102 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9103 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009104 // eor (immediate)
9105 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9106 // eor (register)
9107 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9108 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009109 // orr (immediate)
9110 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9111 // orr (register)
9112 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9113 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009114 // rsb (immediate)
9115 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9116 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9117 // rsb (register)
9118 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009119 // sbc (immediate)
9120 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9121 // sbc (register)
9122 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9123 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009124 // add (immediate, Thumb)
9125 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9126 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9127 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9128 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009129 // sub (immediate, Thumb)
9130 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9131 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9132 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9133 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009134 // sub (sp minus immediate)
9135 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9136 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009137 // teq (immediate)
9138 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9139 // teq (register)
9140 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009141 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009142 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009143 // tst (register)
9144 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9145 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9146
Johnny Chen7c5234d2011-02-18 23:41:11 +00009147
Johnny Chen338bf542011-02-10 19:29:03 +00009148 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009149 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009150 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009151 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009152 // mov{s}<c>.w <Rd>, <Rm>
9153 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009154 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009155 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9156 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009157 // mvn (immediate)
9158 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9159 // mvn (register)
9160 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9161 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009162 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009163 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009164 // cmn (register)
9165 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009166 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009167 // cmp (immediate)
9168 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009169 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009170 // cmp (register) (Rn and Rm both from r0-r7)
9171 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9172 // cmp (register) (Rn and Rm not both from r0-r7)
9173 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009174 // asr (immediate)
9175 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009176 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009177 // asr (register)
9178 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9179 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009180 // lsl (immediate)
9181 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9182 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9183 // lsl (register)
9184 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9185 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9186 // lsr (immediate)
9187 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9188 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9189 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009190 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009191 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009192 // rrx is a special case encoding of ror (immediate)
9193 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9194 // ror (immediate)
9195 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9196 // ror (register)
9197 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9198 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009199 // mul
9200 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9201 // mul
9202 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009203
Johnny Chen26863dc2011-02-09 23:43:29 +00009204 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009205 // Load instructions
9206 //----------------------------------------------------------------------
9207 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009208 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009209 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00009210 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9211 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009212 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009213 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9214 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009215 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9216 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9217 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009218 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009219 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9220 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009221 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9222 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9223 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009224 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009225 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9226 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009227 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9228 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009229 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009230 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9231 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009232 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9233 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009234 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009235 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9236 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009237
9238 //----------------------------------------------------------------------
9239 // Store instructions
9240 //----------------------------------------------------------------------
9241 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009242 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009243 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009244 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9245 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9246 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9247 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9248 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9249 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9250 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9251 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009252 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
9253
9254 //----------------------------------------------------------------------
9255 // Other instructions
9256 //----------------------------------------------------------------------
9257 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009258 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9259 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
9260 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009261
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009262 };
9263
9264 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9265 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9266 {
9267 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9268 return &g_thumb_opcodes[i];
9269 }
9270 return NULL;
9271}
Greg Clayton64c84432011-01-21 22:02:52 +00009272
Greg Clayton31e2a382011-01-30 20:03:56 +00009273bool
Greg Clayton395fc332011-02-15 21:59:32 +00009274EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009275{
9276 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009277 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009278 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009279 {
Greg Clayton395fc332011-02-15 21:59:32 +00009280 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9281 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9282 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9283 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9284 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9285 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9286 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9287 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9288 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9289 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009290 }
9291 return m_arm_isa != 0;
9292}
9293
9294
Greg Clayton64c84432011-01-21 22:02:52 +00009295bool
9296EmulateInstructionARM::ReadInstruction ()
9297{
9298 bool success = false;
9299 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
9300 if (success)
9301 {
9302 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9303 if (success)
9304 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009305 Context read_inst_context;
9306 read_inst_context.type = eContextReadOpcode;
9307 read_inst_context.SetNoArgs ();
9308
Greg Clayton64c84432011-01-21 22:02:52 +00009309 if (m_inst_cpsr & MASK_CPSR_T)
9310 {
9311 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009312 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009313
9314 if (success)
9315 {
9316 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9317 {
9318 m_inst.opcode_type = eOpcode16;
9319 m_inst.opcode.inst16 = thumb_opcode;
9320 }
9321 else
9322 {
9323 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009324 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009325 }
9326 }
9327 }
9328 else
9329 {
9330 m_inst_mode = eModeARM;
9331 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009332 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009333 }
9334 }
9335 }
9336 if (!success)
9337 {
9338 m_inst_mode = eModeInvalid;
9339 m_inst_pc = LLDB_INVALID_ADDRESS;
9340 }
9341 return success;
9342}
9343
Johnny Chenee9b1f72011-02-09 01:00:31 +00009344uint32_t
9345EmulateInstructionARM::ArchVersion ()
9346{
9347 return m_arm_isa;
9348}
9349
Greg Clayton64c84432011-01-21 22:02:52 +00009350bool
9351EmulateInstructionARM::ConditionPassed ()
9352{
9353 if (m_inst_cpsr == 0)
9354 return false;
9355
9356 const uint32_t cond = CurrentCond ();
9357
9358 if (cond == UINT32_MAX)
9359 return false;
9360
9361 bool result = false;
9362 switch (UnsignedBits(cond, 3, 1))
9363 {
9364 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9365 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9366 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9367 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9368 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9369 case 5:
9370 {
9371 bool n = (m_inst_cpsr & MASK_CPSR_N);
9372 bool v = (m_inst_cpsr & MASK_CPSR_V);
9373 result = n == v;
9374 }
9375 break;
9376 case 6:
9377 {
9378 bool n = (m_inst_cpsr & MASK_CPSR_N);
9379 bool v = (m_inst_cpsr & MASK_CPSR_V);
9380 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
9381 }
9382 break;
9383 case 7:
9384 result = true;
9385 break;
9386 }
9387
9388 if (cond & 1)
9389 result = !result;
9390 return result;
9391}
9392
Johnny Chen9ee056b2011-02-08 00:06:35 +00009393uint32_t
9394EmulateInstructionARM::CurrentCond ()
9395{
9396 switch (m_inst_mode)
9397 {
9398 default:
9399 case eModeInvalid:
9400 break;
9401
9402 case eModeARM:
9403 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
9404
9405 case eModeThumb:
9406 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9407 // 'cond' field of the encoding.
9408 if (m_inst.opcode_type == eOpcode16 &&
9409 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
9410 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
9411 {
9412 return Bits32(m_inst.opcode.inst16, 11, 7);
9413 }
9414 else if (m_inst.opcode_type == eOpcode32 &&
9415 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
9416 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
9417 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
9418 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
9419 {
9420 return Bits32(m_inst.opcode.inst32, 25, 22);
9421 }
9422
9423 return m_it_session.GetCond();
9424 }
9425 return UINT32_MAX; // Return invalid value
9426}
9427
Johnny Chen9ee056b2011-02-08 00:06:35 +00009428bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009429EmulateInstructionARM::InITBlock()
9430{
9431 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9432}
9433
9434bool
9435EmulateInstructionARM::LastInITBlock()
9436{
9437 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9438}
9439
9440bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00009441EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
9442{
9443 addr_t target;
9444
Johnny Chenee9b1f72011-02-09 01:00:31 +00009445 // Check the current instruction set.
9446 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009447 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009448 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00009449 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009450
Johnny Chen9ee056b2011-02-08 00:06:35 +00009451 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009452 return false;
9453
9454 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009455}
9456
9457// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
9458bool
Johnny Chen668b4512011-02-15 21:08:58 +00009459EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009460{
9461 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00009462 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
9463 // we want to record it and issue a WriteRegister callback so the clients
9464 // can track the mode changes accordingly.
9465 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009466
9467 if (BitIsSet(addr, 0))
9468 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009469 if (CurrentInstrSet() != eModeThumb)
9470 {
9471 SelectInstrSet(eModeThumb);
9472 cpsr_changed = true;
9473 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009474 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00009475 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009476 }
9477 else if (BitIsClear(addr, 1))
9478 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009479 if (CurrentInstrSet() != eModeARM)
9480 {
9481 SelectInstrSet(eModeARM);
9482 cpsr_changed = true;
9483 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009484 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00009485 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009486 }
9487 else
9488 return false; // address<1:0> == '10' => UNPREDICTABLE
9489
Johnny Chen0f309db2011-02-09 19:11:32 +00009490 if (cpsr_changed)
9491 {
Johnny Chen558133b2011-02-09 23:59:17 +00009492 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00009493 return false;
9494 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009495 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009496 return false;
9497
9498 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009499}
Greg Clayton64c84432011-01-21 22:02:52 +00009500
Johnny Chenee9b1f72011-02-09 01:00:31 +00009501// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
9502bool
Johnny Chen668b4512011-02-15 21:08:58 +00009503EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00009504{
9505 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00009506 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00009507 else
9508 return BranchWritePC((const Context)context, addr);
9509}
9510
Johnny Chen26863dc2011-02-09 23:43:29 +00009511// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
9512bool
Johnny Chen668b4512011-02-15 21:08:58 +00009513EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00009514{
9515 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00009516 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00009517 else
9518 return BranchWritePC((const Context)context, addr);
9519}
9520
Johnny Chenee9b1f72011-02-09 01:00:31 +00009521EmulateInstructionARM::Mode
9522EmulateInstructionARM::CurrentInstrSet ()
9523{
9524 return m_inst_mode;
9525}
9526
9527// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00009528// ReadInstruction() is performed. This function has a side effect of updating
9529// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00009530bool
9531EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
9532{
Johnny Chen558133b2011-02-09 23:59:17 +00009533 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009534 switch (arm_or_thumb)
9535 {
9536 default:
9537 return false;
9538 eModeARM:
9539 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009540 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009541 break;
9542 eModeThumb:
9543 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009544 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009545 break;
9546 }
9547 return true;
9548}
9549
Johnny Chenef21b592011-02-10 01:52:38 +00009550// This function returns TRUE if the processor currently provides support for
9551// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
9552// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
9553bool
9554EmulateInstructionARM::UnalignedSupport()
9555{
9556 return (ArchVersion() >= ARMv7);
9557}
9558
Johnny Chenbf6ad172011-02-11 01:29:53 +00009559// The main addition and subtraction instructions can produce status information
9560// about both unsigned carry and signed overflow conditions. This status
9561// information can be used to synthesize multi-word additions and subtractions.
9562EmulateInstructionARM::AddWithCarryResult
9563EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
9564{
9565 uint32_t result;
9566 uint8_t carry_out;
9567 uint8_t overflow;
9568
9569 uint64_t unsigned_sum = x + y + carry_in;
9570 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
9571
9572 result = UnsignedBits(unsigned_sum, 31, 0);
9573 carry_out = (result == unsigned_sum ? 0 : 1);
9574 overflow = ((int32_t)result == signed_sum ? 0 : 1);
9575
9576 AddWithCarryResult res = { result, carry_out, overflow };
9577 return res;
9578}
9579
Johnny Chen157b9592011-02-18 21:13:05 +00009580uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00009581EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00009582{
Johnny Chene39f22d2011-02-19 01:36:13 +00009583 uint32_t reg_kind, reg_num;
9584 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00009585 {
Johnny Chene39f22d2011-02-19 01:36:13 +00009586 case SP_REG:
9587 reg_kind = eRegisterKindGeneric;
9588 reg_num = LLDB_REGNUM_GENERIC_SP;
9589 break;
9590 case LR_REG:
9591 reg_kind = eRegisterKindGeneric;
9592 reg_num = LLDB_REGNUM_GENERIC_RA;
9593 break;
9594 case PC_REG:
9595 reg_kind = eRegisterKindGeneric;
9596 reg_num = LLDB_REGNUM_GENERIC_PC;
9597 break;
9598 default:
9599 if (0 <= num && num < SP_REG)
9600 {
9601 reg_kind = eRegisterKindDWARF;
9602 reg_num = dwarf_r0 + num;
9603 }
Johnny Chen157b9592011-02-18 21:13:05 +00009604 else
Johnny Chene39f22d2011-02-19 01:36:13 +00009605 {
9606 assert(0 && "Invalid register number");
9607 *success = false;
9608 return ~0u;
9609 }
9610 break;
Johnny Chen157b9592011-02-18 21:13:05 +00009611 }
Johnny Chene39f22d2011-02-19 01:36:13 +00009612
9613 // Read our register.
9614 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
9615
9616 // When executing an ARM instruction , PC reads as the address of the current
9617 // instruction plus 8.
9618 // When executing a Thumb instruction , PC reads as the address of the current
9619 // instruction plus 4.
9620 if (num == 15)
9621 {
9622 if (CurrentInstrSet() == eModeARM)
9623 val += 8;
9624 else
9625 val += 4;
9626 }
Johnny Chen157b9592011-02-18 21:13:05 +00009627
9628 return val;
9629}
9630
Johnny Chenca67d1c2011-02-17 01:35:27 +00009631// Write the result to the ARM core register Rd, and optionally update the
9632// condition flags based on the result.
9633//
9634// This helper method tries to encapsulate the following pseudocode from the
9635// ARM Architecture Reference Manual:
9636//
9637// if d == 15 then // Can only occur for encoding A1
9638// ALUWritePC(result); // setflags is always FALSE here
9639// else
9640// R[d] = result;
9641// if setflags then
9642// APSR.N = result<31>;
9643// APSR.Z = IsZeroBit(result);
9644// APSR.C = carry;
9645// // APSR.V unchanged
9646//
9647// In the above case, the API client does not pass in the overflow arg, which
9648// defaults to ~0u.
9649bool
Johnny Chen10530c22011-02-17 22:37:12 +00009650EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
9651 const uint32_t result,
9652 const uint32_t Rd,
9653 bool setflags,
9654 const uint32_t carry,
9655 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00009656{
9657 if (Rd == 15)
9658 {
9659 if (!ALUWritePC (context, result))
9660 return false;
9661 }
9662 else
9663 {
Johnny Chena695f952011-02-23 21:24:25 +00009664 uint32_t reg_kind, reg_num;
9665 switch (Rd)
9666 {
9667 case SP_REG:
9668 reg_kind = eRegisterKindGeneric;
9669 reg_num = LLDB_REGNUM_GENERIC_SP;
9670 break;
9671 case LR_REG:
9672 reg_kind = eRegisterKindGeneric;
9673 reg_num = LLDB_REGNUM_GENERIC_RA;
9674 break;
9675 default:
9676 reg_kind = eRegisterKindDWARF;
9677 reg_num = dwarf_r0 + Rd;
9678 }
9679 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +00009680 return false;
9681 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00009682 return WriteFlags (context, result, carry, overflow);
9683 }
9684 return true;
9685}
9686
9687// This helper method tries to encapsulate the following pseudocode from the
9688// ARM Architecture Reference Manual:
9689//
9690// APSR.N = result<31>;
9691// APSR.Z = IsZeroBit(result);
9692// APSR.C = carry;
9693// APSR.V = overflow
9694//
9695// Default arguments can be specified for carry and overflow parameters, which means
9696// not to update the respective flags.
9697bool
9698EmulateInstructionARM::WriteFlags (Context &context,
9699 const uint32_t result,
9700 const uint32_t carry,
9701 const uint32_t overflow)
9702{
9703 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +00009704 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
9705 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +00009706 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00009707 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +00009708 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00009709 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +00009710 if (m_new_inst_cpsr != m_inst_cpsr)
9711 {
9712 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
9713 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00009714 }
9715 return true;
9716}
9717
Greg Clayton64c84432011-01-21 22:02:52 +00009718bool
9719EmulateInstructionARM::EvaluateInstruction ()
9720{
Johnny Chenc315f862011-02-05 00:46:10 +00009721 // Advance the ITSTATE bits to their values for the next instruction.
9722 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
9723 m_it_session.ITAdvance();
9724
Greg Clayton64c84432011-01-21 22:02:52 +00009725 return false;
9726}