blob: 6606267c364b6f6414a5e94a3a5bccd0af52ee09 [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);
Caroline Tice8ce96d92011-03-03 18:27:17 +00007487 int64_t data = llvm::SignExtend64<8>(rotated);
Caroline Tice6bf65162011-03-03 17:42:58 +00007488
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
Caroline Tice8ce96d92011-03-03 18:27:17 +00007496 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice6bf65162011-03-03 17:42:58 +00007497 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
Caroline Tice8ce96d92011-03-03 18:27:17 +00007579 int64_t data = llvm::SignExtend64<16> (rotated);
7580 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
Caroline Tice868198b2011-03-03 18:04:49 +00007581 return false;
7582 }
7583
7584 return true;
7585}
7586
Caroline Tice8ce96d92011-03-03 18:27:17 +00007587// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
7588// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
7589bool
7590EmulateInstructionARM::EmulateUXTB (ARMEncoding encoding)
7591{
7592#if 0
7593 if ConditionPassed() then
7594 EncodingSpecificOperations();
7595 rotated = ROR(R[m], rotation);
7596 R[d] = ZeroExtend(rotated<7:0>, 32);
7597#endif
7598
7599 bool success = false;
7600 const uint32_t opcode = OpcodeAsUnsigned (&success);
7601 if (!success)
7602 return false;
7603
7604 if (ConditionPassed())
7605 {
7606 uint32_t d;
7607 uint32_t m;
7608 uint32_t rotation;
7609
7610 // EncodingSpecificOperations();
7611 switch (encoding)
7612 {
7613 case eEncodingT1:
7614 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7615 d = Bits32 (opcode, 2, 0);
7616 m = Bits32 (opcode, 5, 3);
7617 rotation = 0;
7618
7619 break;
7620
7621 case eEncodingT2:
7622 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7623 d = Bits32 (opcode, 11, 8);
7624 m = Bits32 (opcode, 3, 0);
7625 rotation = Bits32 (opcode, 5, 4) << 3;
7626
7627 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7628 if (BadReg (d) || BadReg (m))
7629 return false;
7630
7631 break;
7632
7633 case eEncodingA1:
7634 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7635 d = Bits32 (opcode, 15, 12);
7636 m = Bits32 (opcode, 3, 0);
7637 rotation = Bits32 (opcode, 11, 10) << 3;
7638
7639 // if d == 15 || m == 15 then UNPREDICTABLE;
7640 if ((d == 15) || (m == 15))
7641 return false;
7642
7643 break;
7644
7645 default:
7646 return false;
7647 }
7648
7649 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7650 if (!success)
7651 return false;
7652
7653 // rotated = ROR(R[m], rotation);
7654 uint64_t rotated = ROR (Rm, rotation);
7655
7656 // R[d] = ZeroExtend(rotated<7:0>, 32);
7657 Register source_reg;
7658 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7659
7660 EmulateInstruction::Context context;
7661 context.type = eContextRegisterLoad;
7662 context.SetRegister (source_reg);
7663
7664 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
7665 return false;
7666 }
7667 return true;
7668}
7669
Caroline Tice11555f22011-03-03 18:48:58 +00007670// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination
7671// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
7672bool
7673EmulateInstructionARM::EmulateUXTH (ARMEncoding encoding)
7674{
7675#if 0
7676 if ConditionPassed() then
7677 EncodingSpecificOperations();
7678 rotated = ROR(R[m], rotation);
7679 R[d] = ZeroExtend(rotated<15:0>, 32);
7680#endif
7681
7682 bool success = false;
7683 const uint32_t opcode = OpcodeAsUnsigned (&success);
7684 if (!success)
7685 return false;
7686
7687 if (ConditionPassed ())
7688 {
7689 uint32_t d;
7690 uint32_t m;
7691 uint32_t rotation;
7692
7693 switch (encoding)
7694 {
7695 case eEncodingT1:
7696 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
7697 d = Bits32 (opcode, 2, 0);
7698 m = Bits32 (opcode, 5, 3);
7699 rotation = 0;
7700
7701 break;
7702
7703 case eEncodingT2:
7704 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7705 d = Bits32 (opcode, 11, 8);
7706 m = Bits32 (opcode, 3, 0);
7707 rotation = Bits32 (opcode, 5, 4) << 3;
7708
7709 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
7710 if (BadReg (d) || BadReg (m))
7711 return false;
7712
7713 break;
7714
7715 case eEncodingA1:
7716 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:’000’);
7717 d = Bits32 (opcode, 15, 12);
7718 m = Bits32 (opcode, 3, 0);
7719 rotation = Bits32 (opcode, 11, 10) << 3;
7720
7721 // if d == 15 || m == 15 then UNPREDICTABLE;
7722 if ((d == 15) || (m == 15))
7723 return false;
7724
7725 break;
7726
7727 default:
7728 return false;
7729 }
7730
7731 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7732 if (!success)
7733 return false;
7734
7735 // rotated = ROR(R[m], rotation);
7736 uint64_t rotated = ROR (Rm, rotation);
7737
7738 // R[d] = ZeroExtend(rotated<15:0>, 32);
7739 Register source_reg;
7740 source_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
7741
7742 EmulateInstruction::Context context;
7743 context.type = eContextRegisterLoad;
7744 context.SetRegister (source_reg);
7745
7746 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
7747 return false;
7748 }
7749 return true;
7750}
Caroline Ticeb27771d2011-03-03 22:37:46 +00007751
7752// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following
7753// word respectively.
7754bool
7755EmulateInstructionARM::EmulateRFE (ARMEncoding encoding)
7756{
7757#if 0
7758 if ConditionPassed() then
7759 EncodingSpecificOperations();
7760 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7761 UNPREDICTABLE;
7762 else
7763 address = if increment then R[n] else R[n]-8;
7764 if wordhigher then address = address+4;
7765 CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
7766 BranchWritePC(MemA[address,4]);
7767 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7768#endif
7769
7770 bool success = false;
7771 const uint32_t opcode = OpcodeAsUnsigned (&success);
7772 if (!success)
7773 return false;
7774
7775 if (ConditionPassed())
7776 {
7777 uint32_t n;
7778 bool wback;
7779 bool increment;
7780 bool wordhigher;
7781
7782 // EncodingSpecificOperations();
7783 switch (encoding)
7784 {
7785 case eEncodingT1:
7786 // n = UInt(Rn); wback = (W == ’1’); increment = FALSE; wordhigher = FALSE;
7787 n = Bits32 (opcode, 19, 16);
7788 wback = BitIsSet (opcode, 21);
7789 increment = false;
7790 wordhigher = false;
7791
7792 // if n == 15 then UNPREDICTABLE;
7793 if (n == 15)
7794 return false;
7795
7796 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7797 if (InITBlock() && !LastInITBlock())
7798 return false;
7799
7800 break;
7801
7802 case eEncodingT2:
7803 // n = UInt(Rn); wback = (W == ’1’); increment = TRUE; wordhigher = FALSE;
7804 n = Bits32 (opcode, 19, 16);
7805 wback = BitIsSet (opcode, 21);
7806 increment = true;
7807 wordhigher = false;
7808
7809 // if n == 15 then UNPREDICTABLE;
7810 if (n == 15)
7811 return false;
7812
7813 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
7814 if (InITBlock() && !LastInITBlock())
7815 return false;
7816
7817 break;
7818
7819 case eEncodingA1:
7820 // n = UInt(Rn);
7821 n = Bits32 (opcode, 19, 16);
7822
7823 // wback = (W == ’1’); inc = (U == ’1’); wordhigher = (P == U);
7824 wback = BitIsSet (opcode, 21);
7825 increment = BitIsSet (opcode, 23);
7826 wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
7827
7828 // if n == 15 then UNPREDICTABLE;
7829 if (n == 15)
7830 return false;
7831
7832 break;
7833
7834 default:
7835 return false;
7836 }
7837
7838 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
7839 if (!CurrentModeIsPrivileged ())
7840 // UNPREDICTABLE;
7841 return false;
7842 else
7843 {
7844 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7845 if (!success)
7846 return false;
7847
7848 addr_t address;
7849 // address = if increment then R[n] else R[n]-8;
7850 if (increment)
7851 address = Rn;
7852 else
7853 address = Rn - 8;
7854
7855 // if wordhigher then address = address+4;
7856 if (wordhigher)
7857 address = address + 4;
7858
7859 // CPSRWriteByInstr(MemA[address+4,4], ’1111’, TRUE);
7860 Register base_reg;
7861 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
7862
7863 EmulateInstruction::Context context;
7864 context.type = eContextReturnFromException;
7865 context.SetRegisterPlusOffset (base_reg, address - Rn);
7866
7867 uint64_t data = MemARead (context, address + 4, 4, 0, &success);
7868 if (!success)
7869 return false;
7870
7871 CPSRWriteByInstr (data, 15, true);
7872
7873 // BranchWritePC(MemA[address,4]);
7874 uint64_t data2 = MemARead (context, address, 4, 0, &success);
7875 if (!success)
7876 return false;
7877
7878 BranchWritePC (context, data2);
7879
7880 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
7881 if (wback)
7882 {
7883 context.type = eContextAdjustBaseRegister;
7884 if (increment)
7885 {
7886 context.SetOffset (8);
7887 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
7888 return false;
7889 }
7890 else
7891 {
7892 context.SetOffset (-8);
7893 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
7894 return false;
7895 }
7896 } // if wback
7897 }
7898 } // if ConditionPassed()
7899 return true;
7900}
Caroline Tice11555f22011-03-03 18:48:58 +00007901
Johnny Chen2115b412011-02-21 23:42:44 +00007902// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
7903// and writes the result to the destination register. It can optionally update the condition flags based on
7904// the result.
7905bool
7906EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
7907{
7908#if 0
7909 // ARM pseudo code...
7910 if ConditionPassed() then
7911 EncodingSpecificOperations();
7912 result = R[n] EOR imm32;
7913 if d == 15 then // Can only occur for ARM encoding
7914 ALUWritePC(result); // setflags is always FALSE here
7915 else
7916 R[d] = result;
7917 if setflags then
7918 APSR.N = result<31>;
7919 APSR.Z = IsZeroBit(result);
7920 APSR.C = carry;
7921 // APSR.V unchanged
7922#endif
7923
7924 bool success = false;
7925 const uint32_t opcode = OpcodeAsUnsigned (&success);
7926 if (!success)
7927 return false;
7928
7929 if (ConditionPassed())
7930 {
7931 uint32_t Rd, Rn;
7932 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7933 bool setflags;
7934 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7935 switch (encoding)
7936 {
7937 case eEncodingT1:
7938 Rd = Bits32(opcode, 11, 8);
7939 Rn = Bits32(opcode, 19, 16);
7940 setflags = BitIsSet(opcode, 20);
7941 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7942 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
7943 if (Rd == 15 && setflags)
7944 return EmulateTEQImm(eEncodingT1);
7945 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
7946 return false;
7947 break;
7948 case eEncodingA1:
7949 Rd = Bits32(opcode, 15, 12);
7950 Rn = Bits32(opcode, 19, 16);
7951 setflags = BitIsSet(opcode, 20);
7952 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7953 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7954 // TODO: Emulate SUBS PC, LR and related instructions.
7955 if (Rd == 15 && setflags)
7956 return false;
7957 break;
7958 default:
7959 return false;
7960 }
7961
7962 // Read the first operand.
7963 uint32_t val1 = ReadCoreReg(Rn, &success);
7964 if (!success)
7965 return false;
7966
7967 uint32_t result = val1 ^ imm32;
7968
7969 EmulateInstruction::Context context;
7970 context.type = EmulateInstruction::eContextImmediate;
7971 context.SetNoArgs ();
7972
7973 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7974 return false;
7975 }
7976 return true;
7977}
7978
7979// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
7980// optionally-shifted register value, and writes the result to the destination register.
7981// It can optionally update the condition flags based on the result.
7982bool
7983EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
7984{
7985#if 0
7986 // ARM pseudo code...
7987 if ConditionPassed() then
7988 EncodingSpecificOperations();
7989 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7990 result = R[n] EOR shifted;
7991 if d == 15 then // Can only occur for ARM encoding
7992 ALUWritePC(result); // setflags is always FALSE here
7993 else
7994 R[d] = result;
7995 if setflags then
7996 APSR.N = result<31>;
7997 APSR.Z = IsZeroBit(result);
7998 APSR.C = carry;
7999 // APSR.V unchanged
8000#endif
8001
8002 bool success = false;
8003 const uint32_t opcode = OpcodeAsUnsigned (&success);
8004 if (!success)
8005 return false;
8006
8007 if (ConditionPassed())
8008 {
8009 uint32_t Rd, Rn, Rm;
8010 ARM_ShifterType shift_t;
8011 uint32_t shift_n; // the shift applied to the value read from Rm
8012 bool setflags;
8013 uint32_t carry;
8014 switch (encoding)
8015 {
8016 case eEncodingT1:
8017 Rd = Rn = Bits32(opcode, 2, 0);
8018 Rm = Bits32(opcode, 5, 3);
8019 setflags = !InITBlock();
8020 shift_t = SRType_LSL;
8021 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008022 break;
Johnny Chen2115b412011-02-21 23:42:44 +00008023 case eEncodingT2:
8024 Rd = Bits32(opcode, 11, 8);
8025 Rn = Bits32(opcode, 19, 16);
8026 Rm = Bits32(opcode, 3, 0);
8027 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008028 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8029 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00008030 if (Rd == 15 && setflags)
8031 return EmulateTEQReg(eEncodingT1);
8032 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8033 return false;
8034 break;
8035 case eEncodingA1:
8036 Rd = Bits32(opcode, 15, 12);
8037 Rn = Bits32(opcode, 19, 16);
8038 Rm = Bits32(opcode, 3, 0);
8039 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008040 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008041 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8042 // TODO: Emulate SUBS PC, LR and related instructions.
8043 if (Rd == 15 && setflags)
8044 return false;
8045 break;
8046 default:
8047 return false;
8048 }
8049
8050 // Read the first operand.
8051 uint32_t val1 = ReadCoreReg(Rn, &success);
8052 if (!success)
8053 return false;
8054
8055 // Read the second operand.
8056 uint32_t val2 = ReadCoreReg(Rm, &success);
8057 if (!success)
8058 return false;
8059
8060 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8061 uint32_t result = val1 ^ shifted;
8062
8063 EmulateInstruction::Context context;
8064 context.type = EmulateInstruction::eContextImmediate;
8065 context.SetNoArgs ();
8066
8067 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8068 return false;
8069 }
8070 return true;
8071}
8072
Johnny Chen7c5234d2011-02-18 23:41:11 +00008073// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
8074// writes the result to the destination register. It can optionally update the condition flags based
8075// on the result.
8076bool
8077EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
8078{
8079#if 0
8080 // ARM pseudo code...
8081 if ConditionPassed() then
8082 EncodingSpecificOperations();
8083 result = R[n] OR imm32;
8084 if d == 15 then // Can only occur for ARM encoding
8085 ALUWritePC(result); // setflags is always FALSE here
8086 else
8087 R[d] = result;
8088 if setflags then
8089 APSR.N = result<31>;
8090 APSR.Z = IsZeroBit(result);
8091 APSR.C = carry;
8092 // APSR.V unchanged
8093#endif
8094
8095 bool success = false;
8096 const uint32_t opcode = OpcodeAsUnsigned (&success);
8097 if (!success)
8098 return false;
8099
8100 if (ConditionPassed())
8101 {
8102 uint32_t Rd, Rn;
8103 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
8104 bool setflags;
8105 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8106 switch (encoding)
8107 {
8108 case eEncodingT1:
8109 Rd = Bits32(opcode, 11, 8);
8110 Rn = Bits32(opcode, 19, 16);
8111 setflags = BitIsSet(opcode, 20);
8112 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8113 // if Rn == ‘1111’ then SEE MOV (immediate);
8114 if (Rn == 15)
8115 return EmulateMOVRdImm(eEncodingT2);
8116 if (BadReg(Rd) || Rn == 13)
8117 return false;
8118 break;
8119 case eEncodingA1:
8120 Rd = Bits32(opcode, 15, 12);
8121 Rn = Bits32(opcode, 19, 16);
8122 setflags = BitIsSet(opcode, 20);
8123 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8124 // TODO: Emulate SUBS PC, LR and related instructions.
8125 if (Rd == 15 && setflags)
8126 return false;
8127 break;
8128 default:
8129 return false;
8130 }
8131
8132 // Read the first operand.
8133 uint32_t val1 = ReadCoreReg(Rn, &success);
8134 if (!success)
8135 return false;
8136
8137 uint32_t result = val1 | imm32;
8138
8139 EmulateInstruction::Context context;
8140 context.type = EmulateInstruction::eContextImmediate;
8141 context.SetNoArgs ();
8142
8143 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8144 return false;
8145 }
8146 return true;
8147}
8148
8149// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
8150// value, and writes the result to the destination register. It can optionally update the condition flags based
8151// on the result.
8152bool
8153EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
8154{
8155#if 0
8156 // ARM pseudo code...
8157 if ConditionPassed() then
8158 EncodingSpecificOperations();
8159 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8160 result = R[n] OR shifted;
8161 if d == 15 then // Can only occur for ARM encoding
8162 ALUWritePC(result); // setflags is always FALSE here
8163 else
8164 R[d] = result;
8165 if setflags then
8166 APSR.N = result<31>;
8167 APSR.Z = IsZeroBit(result);
8168 APSR.C = carry;
8169 // APSR.V unchanged
8170#endif
8171
8172 bool success = false;
8173 const uint32_t opcode = OpcodeAsUnsigned (&success);
8174 if (!success)
8175 return false;
8176
8177 if (ConditionPassed())
8178 {
8179 uint32_t Rd, Rn, Rm;
8180 ARM_ShifterType shift_t;
8181 uint32_t shift_n; // the shift applied to the value read from Rm
8182 bool setflags;
8183 uint32_t carry;
8184 switch (encoding)
8185 {
8186 case eEncodingT1:
8187 Rd = Rn = Bits32(opcode, 2, 0);
8188 Rm = Bits32(opcode, 5, 3);
8189 setflags = !InITBlock();
8190 shift_t = SRType_LSL;
8191 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008192 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008193 case eEncodingT2:
8194 Rd = Bits32(opcode, 11, 8);
8195 Rn = Bits32(opcode, 19, 16);
8196 Rm = Bits32(opcode, 3, 0);
8197 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008198 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8199 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008200 if (Rn == 15)
8201 return EmulateMOVRdRm(eEncodingT3);
8202 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
8203 return false;
8204 break;
8205 case eEncodingA1:
8206 Rd = Bits32(opcode, 15, 12);
8207 Rn = Bits32(opcode, 19, 16);
8208 Rm = Bits32(opcode, 3, 0);
8209 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00008210 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00008211 // TODO: Emulate SUBS PC, LR and related instructions.
8212 if (Rd == 15 && setflags)
8213 return false;
8214 break;
8215 default:
8216 return false;
8217 }
8218
8219 // Read the first operand.
8220 uint32_t val1 = ReadCoreReg(Rn, &success);
8221 if (!success)
8222 return false;
8223
8224 // Read the second operand.
8225 uint32_t val2 = ReadCoreReg(Rm, &success);
8226 if (!success)
8227 return false;
8228
8229 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00008230 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00008231
8232 EmulateInstruction::Context context;
8233 context.type = EmulateInstruction::eContextImmediate;
8234 context.SetNoArgs ();
8235
8236 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8237 return false;
8238 }
8239 return true;
8240}
8241
Johnny Chened32e7c2011-02-22 23:42:58 +00008242// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
8243// the destination register. It can optionally update the condition flags based on the result.
8244bool
8245EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
8246{
8247#if 0
8248 // ARM pseudo code...
8249 if ConditionPassed() then
8250 EncodingSpecificOperations();
8251 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
8252 if d == 15 then // Can only occur for ARM encoding
8253 ALUWritePC(result); // setflags is always FALSE here
8254 else
8255 R[d] = result;
8256 if setflags then
8257 APSR.N = result<31>;
8258 APSR.Z = IsZeroBit(result);
8259 APSR.C = carry;
8260 APSR.V = overflow;
8261#endif
8262
8263 bool success = false;
8264 const uint32_t opcode = OpcodeAsUnsigned (&success);
8265 if (!success)
8266 return false;
8267
8268 uint32_t Rd; // the destination register
8269 uint32_t Rn; // the first operand
8270 bool setflags;
8271 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8272 switch (encoding) {
8273 case eEncodingT1:
8274 Rd = Bits32(opcode, 2, 0);
8275 Rn = Bits32(opcode, 5, 3);
8276 setflags = !InITBlock();
8277 imm32 = 0;
8278 break;
8279 case eEncodingT2:
8280 Rd = Bits32(opcode, 11, 8);
8281 Rn = Bits32(opcode, 19, 16);
8282 setflags = BitIsSet(opcode, 20);
8283 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8284 if (BadReg(Rd) || BadReg(Rn))
8285 return false;
8286 break;
8287 case eEncodingA1:
8288 Rd = Bits32(opcode, 15, 12);
8289 Rn = Bits32(opcode, 19, 16);
8290 setflags = BitIsSet(opcode, 20);
8291 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8292 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8293 // TODO: Emulate SUBS PC, LR and related instructions.
8294 if (Rd == 15 && setflags)
8295 return false;
8296 break;
8297 default:
8298 return false;
8299 }
8300 // Read the register value from the operand register Rn.
8301 uint32_t reg_val = ReadCoreReg(Rn, &success);
8302 if (!success)
8303 return false;
8304
8305 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
8306
8307 EmulateInstruction::Context context;
8308 context.type = EmulateInstruction::eContextImmediate;
8309 context.SetNoArgs ();
8310
8311 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8312 return false;
8313
8314 return true;
8315}
8316
8317// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
8318// result to the destination register. It can optionally update the condition flags based on the result.
8319bool
8320EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
8321{
8322#if 0
8323 // ARM pseudo code...
8324 if ConditionPassed() then
8325 EncodingSpecificOperations();
8326 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8327 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
8328 if d == 15 then // Can only occur for ARM encoding
8329 ALUWritePC(result); // setflags is always FALSE here
8330 else
8331 R[d] = result;
8332 if setflags then
8333 APSR.N = result<31>;
8334 APSR.Z = IsZeroBit(result);
8335 APSR.C = carry;
8336 APSR.V = overflow;
8337#endif
8338
8339 bool success = false;
8340 const uint32_t opcode = OpcodeAsUnsigned (&success);
8341 if (!success)
8342 return false;
8343
8344 uint32_t Rd; // the destination register
8345 uint32_t Rn; // the first operand
8346 uint32_t Rm; // the second operand
8347 bool setflags;
8348 ARM_ShifterType shift_t;
8349 uint32_t shift_n; // the shift applied to the value read from Rm
8350 switch (encoding) {
8351 case eEncodingT1:
8352 Rd = Bits32(opcode, 11, 8);
8353 Rn = Bits32(opcode, 19, 16);
8354 Rm = Bits32(opcode, 3, 0);
8355 setflags = BitIsSet(opcode, 20);
8356 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8357 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
8358 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8359 return false;
8360 break;
8361 case eEncodingA1:
8362 Rd = Bits32(opcode, 15, 12);
8363 Rn = Bits32(opcode, 19, 16);
8364 Rm = Bits32(opcode, 3, 0);
8365 setflags = BitIsSet(opcode, 20);
8366 shift_n = DecodeImmShiftARM(opcode, shift_t);
8367 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8368 // TODO: Emulate SUBS PC, LR and related instructions.
8369 if (Rd == 15 && setflags)
8370 return false;
8371 break;
8372 default:
8373 return false;
8374 }
8375 // Read the register value from register Rn.
8376 uint32_t val1 = ReadCoreReg(Rn, &success);
8377 if (!success)
8378 return false;
8379
8380 // Read the register value from register Rm.
8381 uint32_t val2 = ReadCoreReg(Rm, &success);
8382 if (!success)
8383 return false;
8384
8385 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8386 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
8387
8388 EmulateInstruction::Context context;
8389 context.type = EmulateInstruction::eContextImmediate;
8390 context.SetNoArgs();
8391 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8392 return false;
8393
8394 return true;
8395}
8396
Johnny Chen90e607b2011-02-23 00:07:09 +00008397// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
8398// an immediate value, and writes the result to the destination register. It can optionally update the condition
8399// flags based on the result.
8400bool
8401EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
8402{
8403#if 0
8404 // ARM pseudo code...
8405 if ConditionPassed() then
8406 EncodingSpecificOperations();
8407 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
8408 if d == 15 then
8409 ALUWritePC(result); // setflags is always FALSE here
8410 else
8411 R[d] = result;
8412 if setflags then
8413 APSR.N = result<31>;
8414 APSR.Z = IsZeroBit(result);
8415 APSR.C = carry;
8416 APSR.V = overflow;
8417#endif
8418
8419 bool success = false;
8420 const uint32_t opcode = OpcodeAsUnsigned (&success);
8421 if (!success)
8422 return false;
8423
8424 uint32_t Rd; // the destination register
8425 uint32_t Rn; // the first operand
8426 bool setflags;
8427 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8428 switch (encoding) {
8429 case eEncodingA1:
8430 Rd = Bits32(opcode, 15, 12);
8431 Rn = Bits32(opcode, 19, 16);
8432 setflags = BitIsSet(opcode, 20);
8433 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8434 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8435 // TODO: Emulate SUBS PC, LR and related instructions.
8436 if (Rd == 15 && setflags)
8437 return false;
8438 break;
8439 default:
8440 return false;
8441 }
8442 // Read the register value from the operand register Rn.
8443 uint32_t reg_val = ReadCoreReg(Rn, &success);
8444 if (!success)
8445 return false;
8446
8447 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
8448
8449 EmulateInstruction::Context context;
8450 context.type = EmulateInstruction::eContextImmediate;
8451 context.SetNoArgs ();
8452
8453 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8454 return false;
8455
8456 return true;
8457}
8458
8459// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
8460// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
8461// condition flags based on the result.
8462bool
8463EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
8464{
8465#if 0
8466 // ARM pseudo code...
8467 if ConditionPassed() then
8468 EncodingSpecificOperations();
8469 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8470 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
8471 if d == 15 then
8472 ALUWritePC(result); // setflags is always FALSE here
8473 else
8474 R[d] = result;
8475 if setflags then
8476 APSR.N = result<31>;
8477 APSR.Z = IsZeroBit(result);
8478 APSR.C = carry;
8479 APSR.V = overflow;
8480#endif
8481
8482 bool success = false;
8483 const uint32_t opcode = OpcodeAsUnsigned (&success);
8484 if (!success)
8485 return false;
8486
8487 uint32_t Rd; // the destination register
8488 uint32_t Rn; // the first operand
8489 uint32_t Rm; // the second operand
8490 bool setflags;
8491 ARM_ShifterType shift_t;
8492 uint32_t shift_n; // the shift applied to the value read from Rm
8493 switch (encoding) {
8494 case eEncodingA1:
8495 Rd = Bits32(opcode, 15, 12);
8496 Rn = Bits32(opcode, 19, 16);
8497 Rm = Bits32(opcode, 3, 0);
8498 setflags = BitIsSet(opcode, 20);
8499 shift_n = DecodeImmShiftARM(opcode, shift_t);
8500 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8501 // TODO: Emulate SUBS PC, LR and related instructions.
8502 if (Rd == 15 && setflags)
8503 return false;
8504 break;
8505 default:
8506 return false;
8507 }
8508 // Read the register value from register Rn.
8509 uint32_t val1 = ReadCoreReg(Rn, &success);
8510 if (!success)
8511 return false;
8512
8513 // Read the register value from register Rm.
8514 uint32_t val2 = ReadCoreReg(Rm, &success);
8515 if (!success)
8516 return false;
8517
8518 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8519 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
8520
8521 EmulateInstruction::Context context;
8522 context.type = EmulateInstruction::eContextImmediate;
8523 context.SetNoArgs();
8524 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8525 return false;
8526
8527 return true;
8528}
8529
Johnny Chen9b381772011-02-23 01:01:21 +00008530// Subtract with Carry (immediate) subtracts an immediate value and the value of
8531// NOT (Carry flag) from a register value, and writes the result to the destination register.
8532// It can optionally update the condition flags based on the result.
8533bool
8534EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
8535{
8536#if 0
8537 // ARM pseudo code...
8538 if ConditionPassed() then
8539 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008540 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00008541 if d == 15 then // Can only occur for ARM encoding
8542 ALUWritePC(result); // setflags is always FALSE here
8543 else
8544 R[d] = result;
8545 if setflags then
8546 APSR.N = result<31>;
8547 APSR.Z = IsZeroBit(result);
8548 APSR.C = carry;
8549 APSR.V = overflow;
8550#endif
8551
8552 bool success = false;
8553 const uint32_t opcode = OpcodeAsUnsigned (&success);
8554 if (!success)
8555 return false;
8556
8557 uint32_t Rd; // the destination register
8558 uint32_t Rn; // the first operand
8559 bool setflags;
8560 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
8561 switch (encoding) {
8562 case eEncodingT1:
8563 Rd = Bits32(opcode, 11, 8);
8564 Rn = Bits32(opcode, 19, 16);
8565 setflags = BitIsSet(opcode, 20);
8566 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8567 if (BadReg(Rd) || BadReg(Rn))
8568 return false;
8569 break;
8570 case eEncodingA1:
8571 Rd = Bits32(opcode, 15, 12);
8572 Rn = Bits32(opcode, 19, 16);
8573 setflags = BitIsSet(opcode, 20);
8574 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8575 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8576 // TODO: Emulate SUBS PC, LR and related instructions.
8577 if (Rd == 15 && setflags)
8578 return false;
8579 break;
8580 default:
8581 return false;
8582 }
8583 // Read the register value from the operand register Rn.
8584 uint32_t reg_val = ReadCoreReg(Rn, &success);
8585 if (!success)
8586 return false;
8587
8588 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
8589
8590 EmulateInstruction::Context context;
8591 context.type = EmulateInstruction::eContextImmediate;
8592 context.SetNoArgs ();
8593
8594 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8595 return false;
8596
8597 return true;
8598}
8599
8600// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
8601// NOT (Carry flag) from a register value, and writes the result to the destination register.
8602// It can optionally update the condition flags based on the result.
8603bool
8604EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
8605{
8606#if 0
8607 // ARM pseudo code...
8608 if ConditionPassed() then
8609 EncodingSpecificOperations();
8610 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
8611 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
8612 if d == 15 then // Can only occur for ARM encoding
8613 ALUWritePC(result); // setflags is always FALSE here
8614 else
8615 R[d] = result;
8616 if setflags then
8617 APSR.N = result<31>;
8618 APSR.Z = IsZeroBit(result);
8619 APSR.C = carry;
8620 APSR.V = overflow;
8621#endif
8622
8623 bool success = false;
8624 const uint32_t opcode = OpcodeAsUnsigned (&success);
8625 if (!success)
8626 return false;
8627
8628 uint32_t Rd; // the destination register
8629 uint32_t Rn; // the first operand
8630 uint32_t Rm; // the second operand
8631 bool setflags;
8632 ARM_ShifterType shift_t;
8633 uint32_t shift_n; // the shift applied to the value read from Rm
8634 switch (encoding) {
8635 case eEncodingT1:
8636 Rd = Rn = Bits32(opcode, 2, 0);
8637 Rm = Bits32(opcode, 5, 3);
8638 setflags = !InITBlock();
8639 shift_t = SRType_LSL;
8640 shift_n = 0;
8641 break;
8642 case eEncodingT2:
8643 Rd = Bits32(opcode, 11, 8);
8644 Rn = Bits32(opcode, 19, 16);
8645 Rm = Bits32(opcode, 3, 0);
8646 setflags = BitIsSet(opcode, 20);
8647 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8648 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
8649 return false;
8650 break;
8651 case eEncodingA1:
8652 Rd = Bits32(opcode, 15, 12);
8653 Rn = Bits32(opcode, 19, 16);
8654 Rm = Bits32(opcode, 3, 0);
8655 setflags = BitIsSet(opcode, 20);
8656 shift_n = DecodeImmShiftARM(opcode, shift_t);
8657 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8658 // TODO: Emulate SUBS PC, LR and related instructions.
8659 if (Rd == 15 && setflags)
8660 return false;
8661 break;
8662 default:
8663 return false;
8664 }
8665 // Read the register value from register Rn.
8666 uint32_t val1 = ReadCoreReg(Rn, &success);
8667 if (!success)
8668 return false;
8669
8670 // Read the register value from register Rm.
8671 uint32_t val2 = ReadCoreReg(Rm, &success);
8672 if (!success)
8673 return false;
8674
8675 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
8676 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
8677
8678 EmulateInstruction::Context context;
8679 context.type = EmulateInstruction::eContextImmediate;
8680 context.SetNoArgs();
8681 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8682 return false;
8683
8684 return true;
8685}
8686
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008687// This instruction subtracts an immediate value from a register value, and writes the result
8688// to the destination register. It can optionally update the condition flags based on the result.
8689bool
8690EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
8691{
8692#if 0
8693 // ARM pseudo code...
8694 if ConditionPassed() then
8695 EncodingSpecificOperations();
8696 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8697 R[d] = result;
8698 if setflags then
8699 APSR.N = result<31>;
8700 APSR.Z = IsZeroBit(result);
8701 APSR.C = carry;
8702 APSR.V = overflow;
8703#endif
8704
8705 bool success = false;
8706 const uint32_t opcode = OpcodeAsUnsigned (&success);
8707 if (!success)
8708 return false;
8709
8710 uint32_t Rd; // the destination register
8711 uint32_t Rn; // the first operand
8712 bool setflags;
8713 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8714 switch (encoding) {
8715 case eEncodingT1:
8716 Rd = Bits32(opcode, 2, 0);
8717 Rn = Bits32(opcode, 5, 3);
8718 setflags = !InITBlock();
8719 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
8720 break;
8721 case eEncodingT2:
8722 Rd = Rn = Bits32(opcode, 10, 8);
8723 setflags = !InITBlock();
8724 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
8725 break;
8726 case eEncodingT3:
8727 Rd = Bits32(opcode, 11, 8);
8728 Rn = Bits32(opcode, 19, 16);
8729 setflags = BitIsSet(opcode, 20);
8730 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
8731
8732 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
8733 if (Rd == 15 && setflags)
8734 return EmulateCMPImm(eEncodingT2);
8735
8736 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8737 if (Rn == 13)
8738 return EmulateSUBSPImm(eEncodingT2);
8739
8740 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
8741 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
8742 return false;
8743 break;
8744 case eEncodingT4:
8745 Rd = Bits32(opcode, 11, 8);
8746 Rn = Bits32(opcode, 19, 16);
8747 setflags = BitIsSet(opcode, 20);
8748 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
8749
8750 // if Rn == '1111' then SEE ADR;
8751 if (Rn == 15)
8752 return EmulateADR(eEncodingT2);
8753
8754 // if Rn == '1101' then SEE SUB (SP minus immediate);
8755 if (Rn == 13)
8756 return EmulateSUBSPImm(eEncodingT3);
8757
8758 if (BadReg(Rd))
8759 return false;
8760 break;
8761 default:
8762 return false;
8763 }
8764 // Read the register value from the operand register Rn.
8765 uint32_t reg_val = ReadCoreReg(Rn, &success);
8766 if (!success)
8767 return false;
8768
8769 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8770
8771 EmulateInstruction::Context context;
8772 context.type = EmulateInstruction::eContextImmediate;
8773 context.SetNoArgs ();
8774
8775 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8776 return false;
8777
8778 return true;
8779}
8780
8781// This instruction subtracts an immediate value from a register value, and writes the result
8782// to the destination register. It can optionally update the condition flags based on the result.
8783bool
8784EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
8785{
8786#if 0
8787 // ARM pseudo code...
8788 if ConditionPassed() then
8789 EncodingSpecificOperations();
8790 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
8791 if d == 15 then
8792 ALUWritePC(result); // setflags is always FALSE here
8793 else
8794 R[d] = result;
8795 if setflags then
8796 APSR.N = result<31>;
8797 APSR.Z = IsZeroBit(result);
8798 APSR.C = carry;
8799 APSR.V = overflow;
8800#endif
8801
8802 bool success = false;
8803 const uint32_t opcode = OpcodeAsUnsigned (&success);
8804 if (!success)
8805 return false;
8806
8807 uint32_t Rd; // the destination register
8808 uint32_t Rn; // the first operand
8809 bool setflags;
8810 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
8811 switch (encoding) {
8812 case eEncodingA1:
8813 Rd = Bits32(opcode, 15, 12);
8814 Rn = Bits32(opcode, 19, 16);
8815 setflags = BitIsSet(opcode, 20);
8816 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
8817
8818 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
8819 if (Rn == 15 && !setflags)
8820 return EmulateADR(eEncodingA2);
8821
8822 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
8823 if (Rn == 13)
8824 return EmulateSUBSPImm(eEncodingA1);
8825
8826 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
8827 // TODO: Emulate SUBS PC, LR and related instructions.
8828 if (Rd == 15 && setflags)
8829 return false;
8830 break;
8831 default:
8832 return false;
8833 }
8834 // Read the register value from the operand register Rn.
8835 uint32_t reg_val = ReadCoreReg(Rn, &success);
8836 if (!success)
8837 return false;
8838
8839 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
8840
8841 EmulateInstruction::Context context;
8842 context.type = EmulateInstruction::eContextImmediate;
8843 context.SetNoArgs ();
8844
8845 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
8846 return false;
8847
8848 return true;
8849}
8850
Johnny Chen2115b412011-02-21 23:42:44 +00008851// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
8852// immediate value. It updates the condition flags based on the result, and discards the result.
8853bool
8854EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
8855{
8856#if 0
8857 // ARM pseudo code...
8858 if ConditionPassed() then
8859 EncodingSpecificOperations();
8860 result = R[n] EOR imm32;
8861 APSR.N = result<31>;
8862 APSR.Z = IsZeroBit(result);
8863 APSR.C = carry;
8864 // APSR.V unchanged
8865#endif
8866
8867 bool success = false;
8868 const uint32_t opcode = OpcodeAsUnsigned (&success);
8869 if (!success)
8870 return false;
8871
8872 if (ConditionPassed())
8873 {
8874 uint32_t Rn;
8875 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8876 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8877 switch (encoding)
8878 {
8879 case eEncodingT1:
8880 Rn = Bits32(opcode, 19, 16);
8881 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8882 if (BadReg(Rn))
8883 return false;
8884 break;
8885 case eEncodingA1:
8886 Rn = Bits32(opcode, 19, 16);
8887 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8888 break;
8889 default:
8890 return false;
8891 }
8892
8893 // Read the first operand.
8894 uint32_t val1 = ReadCoreReg(Rn, &success);
8895 if (!success)
8896 return false;
8897
8898 uint32_t result = val1 ^ imm32;
8899
8900 EmulateInstruction::Context context;
8901 context.type = EmulateInstruction::eContextImmediate;
8902 context.SetNoArgs ();
8903
8904 if (!WriteFlags(context, result, carry))
8905 return false;
8906 }
8907 return true;
8908}
8909
8910// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
8911// optionally-shifted register value. It updates the condition flags based on the result, and discards
8912// the result.
8913bool
8914EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
8915{
8916#if 0
8917 // ARM pseudo code...
8918 if ConditionPassed() then
8919 EncodingSpecificOperations();
8920 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8921 result = R[n] EOR shifted;
8922 APSR.N = result<31>;
8923 APSR.Z = IsZeroBit(result);
8924 APSR.C = carry;
8925 // APSR.V unchanged
8926#endif
8927
8928 bool success = false;
8929 const uint32_t opcode = OpcodeAsUnsigned (&success);
8930 if (!success)
8931 return false;
8932
8933 if (ConditionPassed())
8934 {
8935 uint32_t Rn, Rm;
8936 ARM_ShifterType shift_t;
8937 uint32_t shift_n; // the shift applied to the value read from Rm
8938 uint32_t carry;
8939 switch (encoding)
8940 {
8941 case eEncodingT1:
8942 Rn = Bits32(opcode, 19, 16);
8943 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008944 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008945 if (BadReg(Rn) || BadReg(Rm))
8946 return false;
8947 break;
8948 case eEncodingA1:
8949 Rn = Bits32(opcode, 19, 16);
8950 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008951 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008952 break;
8953 default:
8954 return false;
8955 }
8956
8957 // Read the first operand.
8958 uint32_t val1 = ReadCoreReg(Rn, &success);
8959 if (!success)
8960 return false;
8961
8962 // Read the second operand.
8963 uint32_t val2 = ReadCoreReg(Rm, &success);
8964 if (!success)
8965 return false;
8966
8967 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8968 uint32_t result = val1 ^ shifted;
8969
8970 EmulateInstruction::Context context;
8971 context.type = EmulateInstruction::eContextImmediate;
8972 context.SetNoArgs ();
8973
8974 if (!WriteFlags(context, result, carry))
8975 return false;
8976 }
8977 return true;
8978}
8979
Johnny Chende3cce32011-02-21 21:24:49 +00008980// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
8981// It updates the condition flags based on the result, and discards the result.
8982bool
8983EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
8984{
8985#if 0
8986 // ARM pseudo code...
8987 if ConditionPassed() then
8988 EncodingSpecificOperations();
8989 result = R[n] AND imm32;
8990 APSR.N = result<31>;
8991 APSR.Z = IsZeroBit(result);
8992 APSR.C = carry;
8993 // APSR.V unchanged
8994#endif
8995
8996 bool success = false;
8997 const uint32_t opcode = OpcodeAsUnsigned (&success);
8998 if (!success)
8999 return false;
9000
9001 if (ConditionPassed())
9002 {
9003 uint32_t Rn;
9004 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
9005 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9006 switch (encoding)
9007 {
9008 case eEncodingT1:
9009 Rn = Bits32(opcode, 19, 16);
9010 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9011 if (BadReg(Rn))
9012 return false;
9013 break;
9014 case eEncodingA1:
9015 Rn = Bits32(opcode, 19, 16);
9016 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9017 break;
9018 default:
9019 return false;
9020 }
9021
9022 // Read the first operand.
9023 uint32_t val1 = ReadCoreReg(Rn, &success);
9024 if (!success)
9025 return false;
9026
9027 uint32_t result = val1 & imm32;
9028
9029 EmulateInstruction::Context context;
9030 context.type = EmulateInstruction::eContextImmediate;
9031 context.SetNoArgs ();
9032
9033 if (!WriteFlags(context, result, carry))
9034 return false;
9035 }
9036 return true;
9037}
9038
9039// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
9040// It updates the condition flags based on the result, and discards the result.
9041bool
9042EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
9043{
9044#if 0
9045 // ARM pseudo code...
9046 if ConditionPassed() then
9047 EncodingSpecificOperations();
9048 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9049 result = R[n] AND shifted;
9050 APSR.N = result<31>;
9051 APSR.Z = IsZeroBit(result);
9052 APSR.C = carry;
9053 // APSR.V unchanged
9054#endif
9055
9056 bool success = false;
9057 const uint32_t opcode = OpcodeAsUnsigned (&success);
9058 if (!success)
9059 return false;
9060
9061 if (ConditionPassed())
9062 {
9063 uint32_t Rn, Rm;
9064 ARM_ShifterType shift_t;
9065 uint32_t shift_n; // the shift applied to the value read from Rm
9066 uint32_t carry;
9067 switch (encoding)
9068 {
9069 case eEncodingT1:
9070 Rn = Bits32(opcode, 2, 0);
9071 Rm = Bits32(opcode, 5, 3);
9072 shift_t = SRType_LSL;
9073 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00009074 break;
Johnny Chende3cce32011-02-21 21:24:49 +00009075 case eEncodingT2:
9076 Rn = Bits32(opcode, 19, 16);
9077 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009078 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009079 if (BadReg(Rn) || BadReg(Rm))
9080 return false;
9081 break;
9082 case eEncodingA1:
9083 Rn = Bits32(opcode, 19, 16);
9084 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00009085 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00009086 break;
9087 default:
9088 return false;
9089 }
9090
9091 // Read the first operand.
9092 uint32_t val1 = ReadCoreReg(Rn, &success);
9093 if (!success)
9094 return false;
9095
9096 // Read the second operand.
9097 uint32_t val2 = ReadCoreReg(Rm, &success);
9098 if (!success)
9099 return false;
9100
9101 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
9102 uint32_t result = val1 & shifted;
9103
9104 EmulateInstruction::Context context;
9105 context.type = EmulateInstruction::eContextImmediate;
9106 context.SetNoArgs ();
9107
9108 if (!WriteFlags(context, result, carry))
9109 return false;
9110 }
9111 return true;
9112}
9113
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009114EmulateInstructionARM::ARMOpcode*
9115EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00009116{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009117 static ARMOpcode
9118 g_arm_opcodes[] =
9119 {
9120 //----------------------------------------------------------------------
9121 // Prologue instructions
9122 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00009123
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009124 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009125 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9126 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00009127
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009128 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009129 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009130 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00009131 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00009132 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
9133 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00009134 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00009135
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009136 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009137 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00009138
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009139 // push one register
9140 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00009141 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00009142
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009143 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00009144 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9145 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00009146
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009147 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00009148 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009149 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00009150
Johnny Chen9f687722011-02-18 00:02:28 +00009151 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9152 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00009153 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009154 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
9155
9156 //----------------------------------------------------------------------
9157 // Supervisor Call (previously Software Interrupt)
9158 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009159 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
9160
9161 //----------------------------------------------------------------------
9162 // Branch instructions
9163 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00009164 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00009165 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
9166 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9167 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9168 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009169 // for example, "bx lr"
9170 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009171 // bxj
9172 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009173
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009174 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00009175 // Data-processing instructions
9176 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009177 // adc (immediate)
9178 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
9179 // adc (register)
9180 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009181 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009182 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00009183 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009184 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00009185 // adr
9186 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9187 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009188 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009189 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009190 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00009191 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009192 // bic (immediate)
9193 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
9194 // bic (register)
9195 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009196 // eor (immediate)
9197 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
9198 // eor (register)
9199 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009200 // orr (immediate)
9201 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
9202 // orr (register)
9203 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009204 // rsb (immediate)
9205 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
9206 // rsb (register)
9207 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00009208 // rsc (immediate)
9209 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
9210 // rsc (register)
9211 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009212 // sbc (immediate)
9213 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9214 // sbc (register)
9215 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009216 // sub (immediate, ARM)
9217 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009218 // sub (sp minus immediate)
9219 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00009220 // teq (immediate)
9221 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
9222 // teq (register)
9223 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009224 // tst (immediate)
9225 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
9226 // tst (register)
9227 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
9228
9229
Johnny Chen01d61572011-02-25 00:23:25 +00009230 // mov (register)
9231 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009232 // mvn (immediate)
9233 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
9234 // mvn (register)
9235 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00009236 // cmn (immediate)
9237 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
9238 // cmn (register)
9239 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009240 // cmp (immediate)
9241 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
9242 // cmp (register)
9243 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009244 // asr (immediate)
9245 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009246 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00009247 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009248 // lsl (immediate)
9249 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
9250 // lsl (register)
9251 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
9252 // lsr (immediate)
9253 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
9254 // lsr (register)
9255 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009256 // rrx is a special case encoding of ror (immediate)
9257 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
9258 // ror (immediate)
9259 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
9260 // ror (register)
9261 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009262 // mul
9263 { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
Johnny Chen28070c32011-02-12 01:27:26 +00009264
9265 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009266 // Load instructions
9267 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00009268 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00009269 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00009270 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00009271 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00009272 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00009273 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00009274 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00009275 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009276 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009277 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009278 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009279 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009280 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009281 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Tice291a3e92011-03-02 21:13:44 +00009282 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
9283 { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticefa172202011-02-11 22:49:54 +00009284
9285 //----------------------------------------------------------------------
9286 // Store instructions
9287 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00009288 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009289 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00009290 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00009291 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009292 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
Caroline Tice1511f502011-02-15 00:19:42 +00009293
Caroline Tice6bf65162011-03-03 17:42:58 +00009294 //----------------------------------------------------------------------
9295 // Other instructions
9296 //----------------------------------------------------------------------
Caroline Tice868198b2011-03-03 18:04:49 +00009297 { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009298 { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Tice11555f22011-03-03 18:48:58 +00009299 { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009300 { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
9301 { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009302
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009303 };
9304 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
9305
9306 for (size_t i=0; i<k_num_arm_opcodes; ++i)
9307 {
9308 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
9309 return &g_arm_opcodes[i];
9310 }
9311 return NULL;
9312}
Greg Clayton64c84432011-01-21 22:02:52 +00009313
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009314
9315EmulateInstructionARM::ARMOpcode*
9316EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00009317{
Johnny Chenfdd179e2011-01-31 20:09:28 +00009318
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009319 static ARMOpcode
9320 g_thumb_opcodes[] =
9321 {
9322 //----------------------------------------------------------------------
9323 // Prologue instructions
9324 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00009325
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009326 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00009327 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
9328 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
9329 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00009330
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009331 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00009332 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009333 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00009334 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00009335 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00009336 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00009337
Johnny Chen864a8e82011-02-18 00:07:39 +00009338 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00009339 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00009340
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009341 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00009342 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009343 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00009344 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
9345 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009346
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009347 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00009348 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
9349 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00009350
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009351 //----------------------------------------------------------------------
9352 // Epilogue instructions
9353 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00009354
Johnny Chen864a8e82011-02-18 00:07:39 +00009355 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00009356 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
9357 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
9358 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00009359 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
9360 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00009361
9362 //----------------------------------------------------------------------
9363 // Supervisor Call (previously Software Interrupt)
9364 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00009365 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
9366
9367 //----------------------------------------------------------------------
9368 // If Then makes up to four following instructions conditional.
9369 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00009370 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
9371
9372 //----------------------------------------------------------------------
9373 // Branch instructions
9374 //----------------------------------------------------------------------
9375 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
9376 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009377 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00009378 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00009379 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00009380 // J1 == J2 == 1
9381 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
9382 // J1 == J2 == 1
9383 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
9384 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00009385 // for example, "bx lr"
9386 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00009387 // bxj
9388 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00009389 // compare and branch
9390 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00009391 // table branch byte
9392 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
9393 // table branch halfword
9394 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009395
9396 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00009397 // Data-processing instructions
9398 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00009399 // adc (immediate)
9400 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
9401 // adc (register)
9402 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
9403 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
9404 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00009405 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00009406 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00009407 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00009408 // adr
9409 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
9410 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
9411 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009412 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00009413 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00009414 // and (register)
9415 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
9416 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00009417 // bic (immediate)
9418 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
9419 // bic (register)
9420 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
9421 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00009422 // eor (immediate)
9423 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
9424 // eor (register)
9425 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
9426 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009427 // orr (immediate)
9428 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
9429 // orr (register)
9430 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
9431 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00009432 // rsb (immediate)
9433 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
9434 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
9435 // rsb (register)
9436 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00009437 // sbc (immediate)
9438 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
9439 // sbc (register)
9440 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
9441 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Caroline Ticedcc11b32011-03-02 23:57:02 +00009442 // add (immediate, Thumb)
9443 { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
9444 { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
9445 { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
9446 { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
Johnny Chen15a7a6b2011-02-23 23:47:56 +00009447 // sub (immediate, Thumb)
9448 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
9449 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
9450 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
9451 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00009452 // sub (sp minus immediate)
9453 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
9454 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00009455 // teq (immediate)
9456 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
9457 // teq (register)
9458 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00009459 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00009460 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00009461 // tst (register)
9462 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
9463 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
9464
Johnny Chen7c5234d2011-02-18 23:41:11 +00009465
Johnny Chen338bf542011-02-10 19:29:03 +00009466 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00009467 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00009468 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00009469 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00009470 // mov{s}<c>.w <Rd>, <Rm>
9471 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00009472 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00009473 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
9474 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00009475 // mvn (immediate)
9476 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
9477 // mvn (register)
9478 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
9479 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009480 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00009481 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009482 // cmn (register)
9483 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009484 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009485 // cmp (immediate)
9486 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00009487 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00009488 // cmp (register) (Rn and Rm both from r0-r7)
9489 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
9490 // cmp (register) (Rn and Rm not both from r0-r7)
9491 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00009492 // asr (immediate)
9493 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00009494 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00009495 // asr (register)
9496 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
9497 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009498 // lsl (immediate)
9499 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
9500 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
9501 // lsl (register)
9502 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
9503 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
9504 // lsr (immediate)
9505 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
9506 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
9507 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00009508 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00009509 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00009510 // rrx is a special case encoding of ror (immediate)
9511 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
9512 // ror (immediate)
9513 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
9514 // ror (register)
9515 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
9516 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Caroline Tice5c1e2ed2011-03-02 22:43:54 +00009517 // mul
9518 { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
9519 // mul
9520 { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009521
Johnny Chen26863dc2011-02-09 23:43:29 +00009522 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00009523 // Load instructions
9524 //----------------------------------------------------------------------
9525 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00009526 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00009527 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00009528 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
9529 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00009530 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00009531 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
9532 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00009533 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
9534 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9535 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00009536 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00009537 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
9538 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00009539 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
9540 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
9541 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00009542 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00009543 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
9544 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00009545 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
9546 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00009547 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00009548 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
9549 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00009550 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
9551 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00009552 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Tice291a3e92011-03-02 21:13:44 +00009553 { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
9554 { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticefa172202011-02-11 22:49:54 +00009555
9556 //----------------------------------------------------------------------
9557 // Store instructions
9558 //----------------------------------------------------------------------
9559 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00009560 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00009561 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00009562 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
9563 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
9564 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
9565 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
9566 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
9567 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
9568 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
9569 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
Caroline Tice6bf65162011-03-03 17:42:58 +00009570 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
9571
9572 //----------------------------------------------------------------------
9573 // Other instructions
9574 //----------------------------------------------------------------------
9575 { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
Caroline Tice868198b2011-03-03 18:04:49 +00009576 { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9577 { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
Caroline Tice8ce96d92011-03-03 18:27:17 +00009578 { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9579 { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
Caroline Tice11555f22011-03-03 18:48:58 +00009580 { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
9581 { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
Caroline Ticeb27771d2011-03-03 22:37:46 +00009582 { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
9583 { 0xffd00000, 0xe8100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
9584 { 0xffd00000, 0xe9900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }
Caroline Tice6bf65162011-03-03 17:42:58 +00009585
Greg Clayton2b8e8b02011-02-01 00:49:32 +00009586 };
9587
9588 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
9589 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
9590 {
9591 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
9592 return &g_thumb_opcodes[i];
9593 }
9594 return NULL;
9595}
Greg Clayton64c84432011-01-21 22:02:52 +00009596
Greg Clayton31e2a382011-01-30 20:03:56 +00009597bool
Greg Clayton395fc332011-02-15 21:59:32 +00009598EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00009599{
9600 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00009601 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00009602 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00009603 {
Greg Clayton395fc332011-02-15 21:59:32 +00009604 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
9605 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
9606 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
9607 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
9608 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
9609 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
9610 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
9611 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
9612 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
9613 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00009614 }
9615 return m_arm_isa != 0;
9616}
9617
9618
Greg Clayton64c84432011-01-21 22:02:52 +00009619bool
9620EmulateInstructionARM::ReadInstruction ()
9621{
9622 bool success = false;
9623 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
9624 if (success)
9625 {
9626 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
9627 if (success)
9628 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00009629 Context read_inst_context;
9630 read_inst_context.type = eContextReadOpcode;
9631 read_inst_context.SetNoArgs ();
9632
Greg Clayton64c84432011-01-21 22:02:52 +00009633 if (m_inst_cpsr & MASK_CPSR_T)
9634 {
9635 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009636 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009637
9638 if (success)
9639 {
9640 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
9641 {
9642 m_inst.opcode_type = eOpcode16;
9643 m_inst.opcode.inst16 = thumb_opcode;
9644 }
9645 else
9646 {
9647 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009648 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009649 }
9650 }
9651 }
9652 else
9653 {
9654 m_inst_mode = eModeARM;
9655 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00009656 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00009657 }
9658 }
9659 }
9660 if (!success)
9661 {
9662 m_inst_mode = eModeInvalid;
9663 m_inst_pc = LLDB_INVALID_ADDRESS;
9664 }
9665 return success;
9666}
9667
Johnny Chenee9b1f72011-02-09 01:00:31 +00009668uint32_t
9669EmulateInstructionARM::ArchVersion ()
9670{
9671 return m_arm_isa;
9672}
9673
Greg Clayton64c84432011-01-21 22:02:52 +00009674bool
9675EmulateInstructionARM::ConditionPassed ()
9676{
9677 if (m_inst_cpsr == 0)
9678 return false;
9679
9680 const uint32_t cond = CurrentCond ();
9681
9682 if (cond == UINT32_MAX)
9683 return false;
9684
9685 bool result = false;
9686 switch (UnsignedBits(cond, 3, 1))
9687 {
9688 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
9689 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
9690 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
9691 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
9692 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
9693 case 5:
9694 {
9695 bool n = (m_inst_cpsr & MASK_CPSR_N);
9696 bool v = (m_inst_cpsr & MASK_CPSR_V);
9697 result = n == v;
9698 }
9699 break;
9700 case 6:
9701 {
9702 bool n = (m_inst_cpsr & MASK_CPSR_N);
9703 bool v = (m_inst_cpsr & MASK_CPSR_V);
9704 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
9705 }
9706 break;
9707 case 7:
9708 result = true;
9709 break;
9710 }
9711
9712 if (cond & 1)
9713 result = !result;
9714 return result;
9715}
9716
Johnny Chen9ee056b2011-02-08 00:06:35 +00009717uint32_t
9718EmulateInstructionARM::CurrentCond ()
9719{
9720 switch (m_inst_mode)
9721 {
9722 default:
9723 case eModeInvalid:
9724 break;
9725
9726 case eModeARM:
9727 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
9728
9729 case eModeThumb:
9730 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
9731 // 'cond' field of the encoding.
9732 if (m_inst.opcode_type == eOpcode16 &&
9733 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
9734 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
9735 {
9736 return Bits32(m_inst.opcode.inst16, 11, 7);
9737 }
9738 else if (m_inst.opcode_type == eOpcode32 &&
9739 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
9740 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
9741 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
9742 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
9743 {
9744 return Bits32(m_inst.opcode.inst32, 25, 22);
9745 }
9746
9747 return m_it_session.GetCond();
9748 }
9749 return UINT32_MAX; // Return invalid value
9750}
9751
Johnny Chen9ee056b2011-02-08 00:06:35 +00009752bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00009753EmulateInstructionARM::InITBlock()
9754{
9755 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
9756}
9757
9758bool
9759EmulateInstructionARM::LastInITBlock()
9760{
9761 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
9762}
9763
Caroline Ticeb27771d2011-03-03 22:37:46 +00009764bool
9765EmulateInstructionARM::BadMode (uint32_t mode)
9766{
9767
9768 switch (mode)
9769 {
9770 case 16: return false; // '10000'
9771 case 17: return false; // '10001'
9772 case 18: return false; // '10010'
9773 case 19: return false; // '10011'
9774 case 22: return false; // '10110'
9775 case 23: return false; // '10111'
9776 case 27: return false; // '11011'
9777 case 31: return false; // '11111'
9778 default: return true;
9779 }
9780 return true;
9781}
9782
9783bool
9784EmulateInstructionARM::CurrentModeIsPrivileged ()
9785{
9786 uint32_t mode = Bits32 (m_inst_cpsr, 4, 0);
9787
9788 if (BadMode (mode))
9789 return false;
9790
9791 if (mode == 16)
9792 return false;
9793
9794 return true;
9795}
9796
9797void
9798EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
9799{
9800 bool privileged = CurrentModeIsPrivileged();
9801
9802 uint32_t tmp_cpsr = 0;
9803
9804 tmp_cpsr = tmp_cpsr | (Bits32 (m_inst_cpsr, 23, 20) << 20);
9805
9806 if (BitIsSet (bytemask, 3))
9807 {
9808 tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
9809 if (affect_execstate)
9810 tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
9811 }
9812
9813 if (BitIsSet (bytemask, 2))
9814 {
9815 tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
9816 }
9817
9818 if (BitIsSet (bytemask, 1))
9819 {
9820 if (affect_execstate)
9821 tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
9822 tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
9823 if (privileged)
9824 tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
9825 }
9826
9827 if (BitIsSet (bytemask, 0))
9828 {
9829 if (privileged)
9830 tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
9831 if (affect_execstate)
9832 tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
9833 if (privileged)
9834 tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
9835 }
9836
9837 m_inst_cpsr = tmp_cpsr;
9838}
9839
9840
Johnny Chen098ae2d2011-02-12 00:50:05 +00009841bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00009842EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
9843{
9844 addr_t target;
9845
Johnny Chenee9b1f72011-02-09 01:00:31 +00009846 // Check the current instruction set.
9847 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009848 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009849 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00009850 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009851
Johnny Chen9ee056b2011-02-08 00:06:35 +00009852 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009853 return false;
9854
9855 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009856}
9857
9858// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
9859bool
Johnny Chen668b4512011-02-15 21:08:58 +00009860EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00009861{
9862 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00009863 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
9864 // we want to record it and issue a WriteRegister callback so the clients
9865 // can track the mode changes accordingly.
9866 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009867
9868 if (BitIsSet(addr, 0))
9869 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009870 if (CurrentInstrSet() != eModeThumb)
9871 {
9872 SelectInstrSet(eModeThumb);
9873 cpsr_changed = true;
9874 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009875 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00009876 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009877 }
9878 else if (BitIsClear(addr, 1))
9879 {
Johnny Chen0f309db2011-02-09 19:11:32 +00009880 if (CurrentInstrSet() != eModeARM)
9881 {
9882 SelectInstrSet(eModeARM);
9883 cpsr_changed = true;
9884 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009885 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00009886 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00009887 }
9888 else
9889 return false; // address<1:0> == '10' => UNPREDICTABLE
9890
Johnny Chen0f309db2011-02-09 19:11:32 +00009891 if (cpsr_changed)
9892 {
Johnny Chen558133b2011-02-09 23:59:17 +00009893 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00009894 return false;
9895 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00009896 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00009897 return false;
9898
9899 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00009900}
Greg Clayton64c84432011-01-21 22:02:52 +00009901
Johnny Chenee9b1f72011-02-09 01:00:31 +00009902// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
9903bool
Johnny Chen668b4512011-02-15 21:08:58 +00009904EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00009905{
9906 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00009907 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00009908 else
9909 return BranchWritePC((const Context)context, addr);
9910}
9911
Johnny Chen26863dc2011-02-09 23:43:29 +00009912// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
9913bool
Johnny Chen668b4512011-02-15 21:08:58 +00009914EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00009915{
9916 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00009917 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00009918 else
9919 return BranchWritePC((const Context)context, addr);
9920}
9921
Johnny Chenee9b1f72011-02-09 01:00:31 +00009922EmulateInstructionARM::Mode
9923EmulateInstructionARM::CurrentInstrSet ()
9924{
9925 return m_inst_mode;
9926}
9927
9928// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00009929// ReadInstruction() is performed. This function has a side effect of updating
9930// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00009931bool
9932EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
9933{
Johnny Chen558133b2011-02-09 23:59:17 +00009934 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009935 switch (arm_or_thumb)
9936 {
9937 default:
9938 return false;
9939 eModeARM:
9940 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009941 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009942 break;
9943 eModeThumb:
9944 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00009945 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00009946 break;
9947 }
9948 return true;
9949}
9950
Johnny Chenef21b592011-02-10 01:52:38 +00009951// This function returns TRUE if the processor currently provides support for
9952// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
9953// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
9954bool
9955EmulateInstructionARM::UnalignedSupport()
9956{
9957 return (ArchVersion() >= ARMv7);
9958}
9959
Johnny Chenbf6ad172011-02-11 01:29:53 +00009960// The main addition and subtraction instructions can produce status information
9961// about both unsigned carry and signed overflow conditions. This status
9962// information can be used to synthesize multi-word additions and subtractions.
9963EmulateInstructionARM::AddWithCarryResult
9964EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
9965{
9966 uint32_t result;
9967 uint8_t carry_out;
9968 uint8_t overflow;
9969
9970 uint64_t unsigned_sum = x + y + carry_in;
9971 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
9972
9973 result = UnsignedBits(unsigned_sum, 31, 0);
9974 carry_out = (result == unsigned_sum ? 0 : 1);
9975 overflow = ((int32_t)result == signed_sum ? 0 : 1);
9976
9977 AddWithCarryResult res = { result, carry_out, overflow };
9978 return res;
9979}
9980
Johnny Chen157b9592011-02-18 21:13:05 +00009981uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00009982EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00009983{
Johnny Chene39f22d2011-02-19 01:36:13 +00009984 uint32_t reg_kind, reg_num;
9985 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00009986 {
Johnny Chene39f22d2011-02-19 01:36:13 +00009987 case SP_REG:
9988 reg_kind = eRegisterKindGeneric;
9989 reg_num = LLDB_REGNUM_GENERIC_SP;
9990 break;
9991 case LR_REG:
9992 reg_kind = eRegisterKindGeneric;
9993 reg_num = LLDB_REGNUM_GENERIC_RA;
9994 break;
9995 case PC_REG:
9996 reg_kind = eRegisterKindGeneric;
9997 reg_num = LLDB_REGNUM_GENERIC_PC;
9998 break;
9999 default:
10000 if (0 <= num && num < SP_REG)
10001 {
10002 reg_kind = eRegisterKindDWARF;
10003 reg_num = dwarf_r0 + num;
10004 }
Johnny Chen157b9592011-02-18 21:13:05 +000010005 else
Johnny Chene39f22d2011-02-19 01:36:13 +000010006 {
10007 assert(0 && "Invalid register number");
10008 *success = false;
10009 return ~0u;
10010 }
10011 break;
Johnny Chen157b9592011-02-18 21:13:05 +000010012 }
Johnny Chene39f22d2011-02-19 01:36:13 +000010013
10014 // Read our register.
10015 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
10016
10017 // When executing an ARM instruction , PC reads as the address of the current
10018 // instruction plus 8.
10019 // When executing a Thumb instruction , PC reads as the address of the current
10020 // instruction plus 4.
10021 if (num == 15)
10022 {
10023 if (CurrentInstrSet() == eModeARM)
10024 val += 8;
10025 else
10026 val += 4;
10027 }
Johnny Chen157b9592011-02-18 21:13:05 +000010028
10029 return val;
10030}
10031
Johnny Chenca67d1c2011-02-17 01:35:27 +000010032// Write the result to the ARM core register Rd, and optionally update the
10033// condition flags based on the result.
10034//
10035// This helper method tries to encapsulate the following pseudocode from the
10036// ARM Architecture Reference Manual:
10037//
10038// if d == 15 then // Can only occur for encoding A1
10039// ALUWritePC(result); // setflags is always FALSE here
10040// else
10041// R[d] = result;
10042// if setflags then
10043// APSR.N = result<31>;
10044// APSR.Z = IsZeroBit(result);
10045// APSR.C = carry;
10046// // APSR.V unchanged
10047//
10048// In the above case, the API client does not pass in the overflow arg, which
10049// defaults to ~0u.
10050bool
Johnny Chen10530c22011-02-17 22:37:12 +000010051EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
10052 const uint32_t result,
10053 const uint32_t Rd,
10054 bool setflags,
10055 const uint32_t carry,
10056 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +000010057{
10058 if (Rd == 15)
10059 {
10060 if (!ALUWritePC (context, result))
10061 return false;
10062 }
10063 else
10064 {
Johnny Chena695f952011-02-23 21:24:25 +000010065 uint32_t reg_kind, reg_num;
10066 switch (Rd)
10067 {
10068 case SP_REG:
10069 reg_kind = eRegisterKindGeneric;
10070 reg_num = LLDB_REGNUM_GENERIC_SP;
10071 break;
10072 case LR_REG:
10073 reg_kind = eRegisterKindGeneric;
10074 reg_num = LLDB_REGNUM_GENERIC_RA;
10075 break;
10076 default:
10077 reg_kind = eRegisterKindDWARF;
10078 reg_num = dwarf_r0 + Rd;
10079 }
10080 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +000010081 return false;
10082 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +000010083 return WriteFlags (context, result, carry, overflow);
10084 }
10085 return true;
10086}
10087
10088// This helper method tries to encapsulate the following pseudocode from the
10089// ARM Architecture Reference Manual:
10090//
10091// APSR.N = result<31>;
10092// APSR.Z = IsZeroBit(result);
10093// APSR.C = carry;
10094// APSR.V = overflow
10095//
10096// Default arguments can be specified for carry and overflow parameters, which means
10097// not to update the respective flags.
10098bool
10099EmulateInstructionARM::WriteFlags (Context &context,
10100 const uint32_t result,
10101 const uint32_t carry,
10102 const uint32_t overflow)
10103{
10104 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +000010105 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
10106 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +000010107 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010108 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +000010109 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +000010110 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +000010111 if (m_new_inst_cpsr != m_inst_cpsr)
10112 {
10113 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
10114 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +000010115 }
10116 return true;
10117}
10118
Greg Clayton64c84432011-01-21 22:02:52 +000010119bool
10120EmulateInstructionARM::EvaluateInstruction ()
10121{
Johnny Chenc315f862011-02-05 00:46:10 +000010122 // Advance the ITSTATE bits to their values for the next instruction.
10123 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
10124 m_it_session.ITAdvance();
10125
Greg Clayton64c84432011-01-21 22:02:52 +000010126 return false;
10127}