blob: e99c2b42f03002ce70b819ce8811582a30bfd7a3 [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)
Johnny Chen9b8d7832011-02-02 01:13:56 +0000133#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv8)
Greg Clayton64c84432011-01-21 22:02:52 +0000134
Johnny Chen0e00af22011-02-10 19:40:42 +0000135//----------------------------------------------------------------------
136//
137// EmulateInstructionARM implementation
138//
139//----------------------------------------------------------------------
140
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000141void
142EmulateInstructionARM::Initialize ()
Johnny Chen7dc60e12011-01-24 19:46:32 +0000143{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000144}
Johnny Chen7dc60e12011-01-24 19:46:32 +0000145
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000146void
147EmulateInstructionARM::Terminate ()
Greg Clayton64c84432011-01-21 22:02:52 +0000148{
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000149}
150
Caroline Ticefa172202011-02-11 22:49:54 +0000151// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions.
152bool
153EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
154{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000155 EmulateInstruction::Context context;
156 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
157 context.SetNoArgs ();
Caroline Ticefa172202011-02-11 22:49:54 +0000158
159 uint32_t random_data = rand ();
160 const uint32_t addr_byte_size = GetAddressByteSize();
161
Caroline Ticecc96eb52011-02-17 19:20:40 +0000162 if (!MemAWrite (context, address, random_data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +0000163 return false;
164
165 return true;
166}
167
Caroline Tice713c2662011-02-11 17:59:55 +0000168// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions.
169bool
170EmulateInstructionARM::WriteBits32Unknown (int n)
171{
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000172 EmulateInstruction::Context context;
173 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
174 context.SetNoArgs ();
Caroline Tice713c2662011-02-11 17:59:55 +0000175
Johnny Chen62ff6f52011-02-11 18:11:22 +0000176 bool success;
Caroline Tice713c2662011-02-11 17:59:55 +0000177 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
178
179 if (!success)
180 return false;
181
182 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
183 return false;
184
185 return true;
186}
187
Johnny Chen08c25e82011-01-31 18:02:28 +0000188// Push Multiple Registers stores multiple registers to the stack, storing to
189// consecutive memory locations ending just below the address in SP, and updates
190// SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000191bool
Johnny Chen9f687722011-02-18 00:02:28 +0000192EmulateInstructionARM::EmulatePUSH (ARMEncoding encoding)
Greg Clayton64c84432011-01-21 22:02:52 +0000193{
194#if 0
195 // ARM pseudo code...
196 if (ConditionPassed())
197 {
198 EncodingSpecificOperations();
199 NullCheckIfThumbEE(13);
200 address = SP - 4*BitCount(registers);
201
202 for (i = 0 to 14)
203 {
204 if (registers<i> == ’1’)
205 {
206 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
207 MemA[address,4] = bits(32) UNKNOWN;
208 else
209 MemA[address,4] = R[i];
210 address = address + 4;
211 }
212 }
213
214 if (registers<15> == ’1’) // Only possible for encoding A1 or A2
215 MemA[address,4] = PCStoreValue();
216
217 SP = SP - 4*BitCount(registers);
218 }
219#endif
220
221 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000222 const uint32_t opcode = OpcodeAsUnsigned (&success);
Greg Clayton64c84432011-01-21 22:02:52 +0000223 if (!success)
224 return false;
225
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000226 if (ConditionPassed())
Greg Clayton64c84432011-01-21 22:02:52 +0000227 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000228 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000229 const addr_t sp = ReadCoreReg (SP_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000230 if (!success)
231 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000232 uint32_t registers = 0;
Johnny Chen91d99862011-01-25 19:07:04 +0000233 uint32_t Rt; // the source register
Johnny Chen3c75c762011-01-22 00:47:08 +0000234 switch (encoding) {
Johnny Chenaedde1c2011-01-24 20:38:45 +0000235 case eEncodingT1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000236 registers = Bits32(opcode, 7, 0);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000237 // The M bit represents LR.
Johnny Chenbd599902011-02-10 21:39:01 +0000238 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000239 registers |= (1u << 14);
Johnny Chenaedde1c2011-01-24 20:38:45 +0000240 // if BitCount(registers) < 1 then UNPREDICTABLE;
241 if (BitCount(registers) < 1)
242 return false;
243 break;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000244 case eEncodingT2:
245 // Ignore bits 15 & 13.
Johnny Chen108d5aa2011-01-26 01:00:55 +0000246 registers = Bits32(opcode, 15, 0) & ~0xa000;
Johnny Chen7dc60e12011-01-24 19:46:32 +0000247 // if BitCount(registers) < 2 then UNPREDICTABLE;
248 if (BitCount(registers) < 2)
249 return false;
250 break;
251 case eEncodingT3:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000252 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000253 // if BadReg(t) then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000254 if (BadReg(Rt))
Johnny Chen7dc60e12011-01-24 19:46:32 +0000255 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000256 registers = (1u << Rt);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000257 break;
Johnny Chen3c75c762011-01-22 00:47:08 +0000258 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000259 registers = Bits32(opcode, 15, 0);
Johnny Chena33d4842011-01-24 22:25:48 +0000260 // Instead of return false, let's handle the following case as well,
261 // which amounts to pushing one reg onto the full descending stacks.
262 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
Johnny Chen3c75c762011-01-22 00:47:08 +0000263 break;
264 case eEncodingA2:
Johnny Chen108d5aa2011-01-26 01:00:55 +0000265 Rt = Bits32(opcode, 15, 12);
Johnny Chen7dc60e12011-01-24 19:46:32 +0000266 // if t == 13 then UNPREDICTABLE;
Johnny Chen91d99862011-01-25 19:07:04 +0000267 if (Rt == dwarf_sp)
Johnny Chen3c75c762011-01-22 00:47:08 +0000268 return false;
Johnny Chen91d99862011-01-25 19:07:04 +0000269 registers = (1u << Rt);
Johnny Chen3c75c762011-01-22 00:47:08 +0000270 break;
Johnny Chence1ca772011-01-25 01:13:00 +0000271 default:
272 return false;
Johnny Chen3c75c762011-01-22 00:47:08 +0000273 }
Johnny Chence1ca772011-01-25 01:13:00 +0000274 addr_t sp_offset = addr_byte_size * BitCount (registers);
Greg Clayton64c84432011-01-21 22:02:52 +0000275 addr_t addr = sp - sp_offset;
276 uint32_t i;
277
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000278 EmulateInstruction::Context context;
279 context.type = EmulateInstruction::eContextPushRegisterOnStack;
280 Register dwarf_reg;
281 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Greg Clayton64c84432011-01-21 22:02:52 +0000282 for (i=0; i<15; ++i)
283 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000284 if (BitIsSet (registers, i))
Greg Clayton64c84432011-01-21 22:02:52 +0000285 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000286 dwarf_reg.num = dwarf_r0 + i;
287 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000288 uint32_t reg_value = ReadCoreReg(i, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000289 if (!success)
290 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +0000291 if (!MemAWrite (context, addr, reg_value, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000292 return false;
293 addr += addr_byte_size;
294 }
295 }
296
Johnny Chen7c1bf922011-02-08 23:49:37 +0000297 if (BitIsSet (registers, 15))
Greg Clayton64c84432011-01-21 22:02:52 +0000298 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000299 dwarf_reg.num = dwarf_pc;
300 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +0000301 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Greg Clayton64c84432011-01-21 22:02:52 +0000302 if (!success)
303 return false;
Johnny Chene39f22d2011-02-19 01:36:13 +0000304 if (!MemAWrite (context, addr, pc, addr_byte_size))
Greg Clayton64c84432011-01-21 22:02:52 +0000305 return false;
306 }
307
308 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000309 context.SetImmediateSigned (-sp_offset);
Greg Clayton64c84432011-01-21 22:02:52 +0000310
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000311 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Greg Clayton64c84432011-01-21 22:02:52 +0000312 return false;
313 }
314 return true;
315}
316
Johnny Chenef85e912011-01-31 23:07:40 +0000317// Pop Multiple Registers loads multiple registers from the stack, loading from
318// consecutive memory locations staring at the address in SP, and updates
319// SP to point just above the loaded data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000320bool
Johnny Chen9f687722011-02-18 00:02:28 +0000321EmulateInstructionARM::EmulatePOP (ARMEncoding encoding)
Johnny Chenef85e912011-01-31 23:07:40 +0000322{
323#if 0
324 // ARM pseudo code...
325 if (ConditionPassed())
326 {
327 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
328 address = SP;
329 for i = 0 to 14
330 if registers<i> == ‘1’ then
331 R[i} = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
332 if registers<15> == ‘1’ then
333 if UnalignedAllowed then
334 LoadWritePC(MemU[address,4]);
335 else
336 LoadWritePC(MemA[address,4]);
337 if registers<13> == ‘0’ then SP = SP + 4*BitCount(registers);
338 if registers<13> == ‘1’ then SP = bits(32) UNKNOWN;
339 }
340#endif
341
342 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000343 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenef85e912011-01-31 23:07:40 +0000344 if (!success)
345 return false;
346
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000347 if (ConditionPassed())
Johnny Chenef85e912011-01-31 23:07:40 +0000348 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000349 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +0000350 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000351 if (!success)
352 return false;
353 uint32_t registers = 0;
354 uint32_t Rt; // the destination register
355 switch (encoding) {
356 case eEncodingT1:
357 registers = Bits32(opcode, 7, 0);
358 // The P bit represents PC.
Johnny Chenbd599902011-02-10 21:39:01 +0000359 if (Bit32(opcode, 8))
Johnny Chenef85e912011-01-31 23:07:40 +0000360 registers |= (1u << 15);
361 // if BitCount(registers) < 1 then UNPREDICTABLE;
362 if (BitCount(registers) < 1)
363 return false;
364 break;
365 case eEncodingT2:
366 // Ignore bit 13.
367 registers = Bits32(opcode, 15, 0) & ~0x2000;
368 // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
Johnny Chenbd599902011-02-10 21:39:01 +0000369 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
Johnny Chenef85e912011-01-31 23:07:40 +0000370 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000371 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
372 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
373 return false;
Johnny Chenef85e912011-01-31 23:07:40 +0000374 break;
375 case eEncodingT3:
376 Rt = Bits32(opcode, 15, 12);
377 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000378 if (Rt == 13)
379 return false;
380 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenef85e912011-01-31 23:07:40 +0000381 return false;
382 registers = (1u << Rt);
383 break;
384 case eEncodingA1:
385 registers = Bits32(opcode, 15, 0);
386 // Instead of return false, let's handle the following case as well,
387 // which amounts to popping one reg from the full descending stacks.
388 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
389
390 // if registers<13> == ‘1’ && ArchVersion() >= 7 then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +0000391 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
Johnny Chenef85e912011-01-31 23:07:40 +0000392 return false;
393 break;
394 case eEncodingA2:
395 Rt = Bits32(opcode, 15, 12);
396 // if t == 13 then UNPREDICTABLE;
397 if (Rt == dwarf_sp)
398 return false;
399 registers = (1u << Rt);
400 break;
401 default:
402 return false;
403 }
404 addr_t sp_offset = addr_byte_size * BitCount (registers);
405 addr_t addr = sp;
406 uint32_t i, data;
407
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000408 EmulateInstruction::Context context;
409 context.type = EmulateInstruction::eContextPopRegisterOffStack;
410 Register dwarf_reg;
411 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chenef85e912011-01-31 23:07:40 +0000412 for (i=0; i<15; ++i)
413 {
Johnny Chen7c1bf922011-02-08 23:49:37 +0000414 if (BitIsSet (registers, i))
Johnny Chenef85e912011-01-31 23:07:40 +0000415 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000416 dwarf_reg.num = dwarf_r0 + i;
417 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000418 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000419 if (!success)
420 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000421 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000422 return false;
423 addr += addr_byte_size;
424 }
425 }
426
Johnny Chen7c1bf922011-02-08 23:49:37 +0000427 if (BitIsSet (registers, 15))
Johnny Chenef85e912011-01-31 23:07:40 +0000428 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000429 dwarf_reg.num = dwarf_pc;
430 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000431 data = MemARead(context, addr, 4, 0, &success);
Johnny Chenef85e912011-01-31 23:07:40 +0000432 if (!success)
433 return false;
Johnny Chenf3eaacf2011-02-09 19:30:49 +0000434 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000435 if (!LoadWritePC(context, data))
Johnny Chenef85e912011-01-31 23:07:40 +0000436 return false;
437 addr += addr_byte_size;
438 }
439
440 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000441 context.SetImmediateSigned (sp_offset);
Johnny Chenef85e912011-01-31 23:07:40 +0000442
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000443 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
Johnny Chenef85e912011-01-31 23:07:40 +0000444 return false;
445 }
446 return true;
447}
448
Johnny Chen5b442b72011-01-27 19:34:30 +0000449// Set r7 or ip to point to saved value residing within the stack.
Johnny Chenbcec3af2011-01-27 01:26:19 +0000450// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000451bool
Johnny Chen9f687722011-02-18 00:02:28 +0000452EmulateInstructionARM::EmulateADDRdSPImm (ARMEncoding encoding)
Johnny Chenbcec3af2011-01-27 01:26:19 +0000453{
454#if 0
455 // ARM pseudo code...
456 if (ConditionPassed())
457 {
458 EncodingSpecificOperations();
459 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
460 if d == 15 then
461 ALUWritePC(result); // setflags is always FALSE here
462 else
463 R[d] = result;
464 if setflags then
465 APSR.N = result<31>;
466 APSR.Z = IsZeroBit(result);
467 APSR.C = carry;
468 APSR.V = overflow;
469 }
470#endif
471
472 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000473 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000474 if (!success)
475 return false;
476
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000477 if (ConditionPassed())
Johnny Chenbcec3af2011-01-27 01:26:19 +0000478 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000479 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000480 if (!success)
481 return false;
482 uint32_t Rd; // the destination register
483 uint32_t imm32;
484 switch (encoding) {
485 case eEncodingT1:
486 Rd = 7;
487 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
488 break;
489 case eEncodingA1:
490 Rd = Bits32(opcode, 15, 12);
491 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
492 break;
493 default:
494 return false;
495 }
496 addr_t sp_offset = imm32;
497 addr_t addr = sp + sp_offset; // a pointer to the stack area
498
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000499 EmulateInstruction::Context context;
500 context.type = EmulateInstruction::eContextRegisterPlusOffset;
501 Register sp_reg;
502 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
503 context.SetRegisterPlusOffset (sp_reg, sp_offset);
Johnny Chenbcec3af2011-01-27 01:26:19 +0000504
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000505 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
Johnny Chenbcec3af2011-01-27 01:26:19 +0000506 return false;
507 }
508 return true;
509}
510
Johnny Chen2ccad832011-01-28 19:57:25 +0000511// Set r7 or ip to the current stack pointer.
512// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000513bool
Johnny Chen9f687722011-02-18 00:02:28 +0000514EmulateInstructionARM::EmulateMOVRdSP (ARMEncoding encoding)
Johnny Chen2ccad832011-01-28 19:57:25 +0000515{
516#if 0
517 // ARM pseudo code...
518 if (ConditionPassed())
519 {
520 EncodingSpecificOperations();
521 result = R[m];
522 if d == 15 then
523 ALUWritePC(result); // setflags is always FALSE here
524 else
525 R[d] = result;
526 if setflags then
527 APSR.N = result<31>;
528 APSR.Z = IsZeroBit(result);
529 // APSR.C unchanged
530 // APSR.V unchanged
531 }
532#endif
533
534 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000535 //const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000536 //if (!success)
537 // return false;
Johnny Chen2ccad832011-01-28 19:57:25 +0000538
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000539 if (ConditionPassed())
Johnny Chen2ccad832011-01-28 19:57:25 +0000540 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000541 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen2ccad832011-01-28 19:57:25 +0000542 if (!success)
543 return false;
544 uint32_t Rd; // the destination register
545 switch (encoding) {
546 case eEncodingT1:
547 Rd = 7;
548 break;
549 case eEncodingA1:
550 Rd = 12;
551 break;
552 default:
553 return false;
554 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000555
556 EmulateInstruction::Context context;
557 context.type = EmulateInstruction::eContextRegisterPlusOffset;
558 Register sp_reg;
559 sp_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
560 context.SetRegisterPlusOffset (sp_reg, 0);
Johnny Chen2ccad832011-01-28 19:57:25 +0000561
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000562 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
Johnny Chen2ccad832011-01-28 19:57:25 +0000563 return false;
564 }
565 return true;
566}
567
Johnny Chen1c13b622011-01-29 00:11:15 +0000568// Move from high register (r8-r15) to low register (r0-r7).
569// MOV (register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000570bool
Johnny Chen9f687722011-02-18 00:02:28 +0000571EmulateInstructionARM::EmulateMOVLowHigh (ARMEncoding encoding)
Johnny Chen1c13b622011-01-29 00:11:15 +0000572{
Johnny Chen9f687722011-02-18 00:02:28 +0000573 return EmulateMOVRdRm (encoding);
Johnny Chen338bf542011-02-10 19:29:03 +0000574}
575
576// Move from register to register.
577// MOV (register)
578bool
Johnny Chen9f687722011-02-18 00:02:28 +0000579EmulateInstructionARM::EmulateMOVRdRm (ARMEncoding encoding)
Johnny Chen338bf542011-02-10 19:29:03 +0000580{
Johnny Chen1c13b622011-01-29 00:11:15 +0000581#if 0
582 // ARM pseudo code...
583 if (ConditionPassed())
584 {
585 EncodingSpecificOperations();
586 result = R[m];
587 if d == 15 then
588 ALUWritePC(result); // setflags is always FALSE here
589 else
590 R[d] = result;
591 if setflags then
592 APSR.N = result<31>;
593 APSR.Z = IsZeroBit(result);
594 // APSR.C unchanged
595 // APSR.V unchanged
596 }
597#endif
598
599 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000600 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000601 if (!success)
602 return false;
603
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000604 if (ConditionPassed())
Johnny Chen1c13b622011-01-29 00:11:15 +0000605 {
606 uint32_t Rm; // the source register
607 uint32_t Rd; // the destination register
Johnny Chen338bf542011-02-10 19:29:03 +0000608 bool setflags;
Johnny Chen1c13b622011-01-29 00:11:15 +0000609 switch (encoding) {
610 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000611 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen1c13b622011-01-29 00:11:15 +0000612 Rm = Bits32(opcode, 6, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000613 setflags = false;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000614 if (Rd == 15 && InITBlock() && !LastInITBlock())
615 return false;
Johnny Chen338bf542011-02-10 19:29:03 +0000616 break;
617 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000618 Rd = Bits32(opcode, 2, 0);
Johnny Chen338bf542011-02-10 19:29:03 +0000619 Rm = Bits32(opcode, 5, 3);
Johnny Chen338bf542011-02-10 19:29:03 +0000620 setflags = true;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000621 if (InITBlock())
622 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000623 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +0000624 case eEncodingT3:
625 Rd = Bits32(opcode, 11, 8);
626 Rm = Bits32(opcode, 3, 0);
627 setflags = BitIsSet(opcode, 20);
628 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
629 if (setflags && (BadReg(Rd) || BadReg(Rm)))
630 return false;
631 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
632 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
633 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000634 break;
Johnny Chen01d61572011-02-25 00:23:25 +0000635 case eEncodingA1:
636 Rd = Bits32(opcode, 15, 12);
637 Rm = Bits32(opcode, 3, 0);
638 setflags = BitIsSet(opcode, 20);
639 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
640 // TODO: Emulate SUBS PC, LR and related instructions.
641 if (Rd == 15 && setflags)
642 return false;
643 break;
Johnny Chen1c13b622011-01-29 00:11:15 +0000644 default:
645 return false;
646 }
Johnny Chen7c5234d2011-02-18 23:41:11 +0000647 uint32_t result = ReadCoreReg(Rm, &success);
Johnny Chen1c13b622011-01-29 00:11:15 +0000648 if (!success)
649 return false;
650
651 // The context specifies that Rm is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000652 EmulateInstruction::Context context;
653 context.type = EmulateInstruction::eContextRegisterPlusOffset;
654 Register dwarf_reg;
655 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
656 context.SetRegisterPlusOffset (dwarf_reg, 0);
Johnny Chenca67d1c2011-02-17 01:35:27 +0000657
Johnny Chen10530c22011-02-17 22:37:12 +0000658 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000659 return false;
Johnny Chen1c13b622011-01-29 00:11:15 +0000660 }
661 return true;
662}
663
Johnny Chen357c30f2011-02-14 22:04:25 +0000664// Move (immediate) writes an immediate value to the destination register. It
665// can optionally update the condition flags based on the value.
666// MOV (immediate)
667bool
Johnny Chen9f687722011-02-18 00:02:28 +0000668EmulateInstructionARM::EmulateMOVRdImm (ARMEncoding encoding)
Johnny Chen357c30f2011-02-14 22:04:25 +0000669{
670#if 0
671 // ARM pseudo code...
672 if (ConditionPassed())
673 {
674 EncodingSpecificOperations();
675 result = imm32;
676 if d == 15 then // Can only occur for ARM encoding
677 ALUWritePC(result); // setflags is always FALSE here
678 else
679 R[d] = result;
680 if setflags then
681 APSR.N = result<31>;
682 APSR.Z = IsZeroBit(result);
683 APSR.C = carry;
684 // APSR.V unchanged
685 }
686#endif
687 bool success = false;
688 const uint32_t opcode = OpcodeAsUnsigned (&success);
689 if (!success)
690 return false;
691
692 if (ConditionPassed())
693 {
694 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000695 uint32_t imm32; // the immediate value to be written to Rd
696 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
697 bool setflags;
698 switch (encoding) {
699 case eEncodingT1:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000700 Rd = Bits32(opcode, 10, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000701 setflags = !InITBlock();
702 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
Johnny Chene97c0d52011-02-18 19:32:20 +0000703 carry = APSR_C;
Johnny Chen357c30f2011-02-14 22:04:25 +0000704 break;
705 case eEncodingT2:
Johnny Chen7c5234d2011-02-18 23:41:11 +0000706 Rd = Bits32(opcode, 11, 8);
Johnny Chen357c30f2011-02-14 22:04:25 +0000707 setflags = BitIsSet(opcode, 20);
Johnny Chen7c5234d2011-02-18 23:41:11 +0000708 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen9798cfc2011-02-14 23:33:58 +0000709 if (BadReg(Rd))
710 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000711 break;
712 default:
713 return false;
714 }
715 uint32_t result = imm32;
716
717 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000718 EmulateInstruction::Context context;
719 context.type = EmulateInstruction::eContextImmediate;
720 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000721
Johnny Chen10530c22011-02-17 22:37:12 +0000722 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000723 return false;
Johnny Chen357c30f2011-02-14 22:04:25 +0000724 }
725 return true;
726}
727
Johnny Chend642a6a2011-02-22 01:01:03 +0000728// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
729// It can optionally update the condition flags based on the value.
Johnny Chen28070c32011-02-12 01:27:26 +0000730bool
Johnny Chend642a6a2011-02-22 01:01:03 +0000731EmulateInstructionARM::EmulateMVNImm (ARMEncoding encoding)
Johnny Chen28070c32011-02-12 01:27:26 +0000732{
733#if 0
734 // ARM pseudo code...
735 if (ConditionPassed())
736 {
737 EncodingSpecificOperations();
738 result = NOT(imm32);
739 if d == 15 then // Can only occur for ARM encoding
740 ALUWritePC(result); // setflags is always FALSE here
741 else
742 R[d] = result;
743 if setflags then
744 APSR.N = result<31>;
745 APSR.Z = IsZeroBit(result);
746 APSR.C = carry;
747 // APSR.V unchanged
748 }
749#endif
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000750 bool success = false;
751 const uint32_t opcode = OpcodeAsUnsigned (&success);
752 if (!success)
753 return false;
754
755 if (ConditionPassed())
756 {
757 uint32_t Rd; // the destination register
Johnny Chen357c30f2011-02-14 22:04:25 +0000758 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
759 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000760 bool setflags;
761 switch (encoding) {
762 case eEncodingT1:
763 Rd = Bits32(opcode, 11, 8);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000764 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000765 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000766 break;
767 case eEncodingA1:
768 Rd = Bits32(opcode, 15, 12);
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000769 setflags = BitIsSet(opcode, 20);
Johnny Chend642a6a2011-02-22 01:01:03 +0000770 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
771 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
772 // TODO: Emulate SUBS PC, LR and related instructions.
773 if (Rd == 15 && setflags)
774 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000775 break;
776 default:
777 return false;
778 }
779 uint32_t result = ~imm32;
780
781 // The context specifies that an immediate is to be moved into Rd.
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000782 EmulateInstruction::Context context;
783 context.type = EmulateInstruction::eContextImmediate;
784 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +0000785
Johnny Chen10530c22011-02-17 22:37:12 +0000786 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +0000787 return false;
Johnny Chen33bf6ab2011-02-14 20:39:01 +0000788 }
789 return true;
Johnny Chen28070c32011-02-12 01:27:26 +0000790}
791
Johnny Chend642a6a2011-02-22 01:01:03 +0000792// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
793// It can optionally update the condition flags based on the result.
794bool
795EmulateInstructionARM::EmulateMVNReg (ARMEncoding encoding)
796{
797#if 0
798 // ARM pseudo code...
799 if (ConditionPassed())
800 {
801 EncodingSpecificOperations();
802 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
803 result = NOT(shifted);
804 if d == 15 then // Can only occur for ARM encoding
805 ALUWritePC(result); // setflags is always FALSE here
806 else
807 R[d] = result;
808 if setflags then
809 APSR.N = result<31>;
810 APSR.Z = IsZeroBit(result);
811 APSR.C = carry;
812 // APSR.V unchanged
813 }
814#endif
815
816 bool success = false;
817 const uint32_t opcode = OpcodeAsUnsigned (&success);
818 if (!success)
819 return false;
820
821 if (ConditionPassed())
822 {
823 uint32_t Rm; // the source register
824 uint32_t Rd; // the destination register
825 ARM_ShifterType shift_t;
826 uint32_t shift_n; // the shift applied to the value read from Rm
827 bool setflags;
828 uint32_t carry; // the carry bit after the shift operation
829 switch (encoding) {
830 case eEncodingT1:
831 Rd = Bits32(opcode, 2, 0);
832 Rm = Bits32(opcode, 5, 3);
833 setflags = !InITBlock();
834 shift_t = SRType_LSL;
835 shift_n = 0;
836 if (InITBlock())
837 return false;
838 break;
839 case eEncodingT2:
840 Rd = Bits32(opcode, 11, 8);
841 Rm = Bits32(opcode, 3, 0);
842 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000843 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000844 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
Johnny Chened32e7c2011-02-22 23:42:58 +0000845 if (BadReg(Rd) || BadReg(Rm))
Johnny Chend642a6a2011-02-22 01:01:03 +0000846 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +0000847 break;
Johnny Chend642a6a2011-02-22 01:01:03 +0000848 case eEncodingA1:
849 Rd = Bits32(opcode, 15, 12);
850 Rm = Bits32(opcode, 3, 0);
851 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +0000852 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chend642a6a2011-02-22 01:01:03 +0000853 break;
854 default:
855 return false;
856 }
857 uint32_t value = ReadCoreReg(Rm, &success);
858 if (!success)
859 return false;
860
861 uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry);
862 uint32_t result = ~shifted;
863
864 // The context specifies that an immediate is to be moved into Rd.
865 EmulateInstruction::Context context;
866 context.type = EmulateInstruction::eContextImmediate;
867 context.SetNoArgs ();
868
869 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
870 return false;
871 }
872 return true;
873}
874
Johnny Chen788e0552011-01-27 22:52:23 +0000875// PC relative immediate load into register, possibly followed by ADD (SP plus register).
876// LDR (literal)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000877bool
Johnny Chenc9de9102011-02-11 19:12:30 +0000878EmulateInstructionARM::EmulateLDRRtPCRelative (ARMEncoding encoding)
Johnny Chen788e0552011-01-27 22:52:23 +0000879{
880#if 0
881 // ARM pseudo code...
882 if (ConditionPassed())
883 {
884 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
885 base = Align(PC,4);
886 address = if add then (base + imm32) else (base - imm32);
887 data = MemU[address,4];
888 if t == 15 then
889 if address<1:0> == ‘00’ then LoadWritePC(data); else UNPREDICTABLE;
890 elsif UnalignedSupport() || address<1:0> = ‘00’ then
891 R[t] = data;
892 else // Can only apply before ARMv7
893 if CurrentInstrSet() == InstrSet_ARM then
894 R[t] = ROR(data, 8*UInt(address<1:0>));
895 else
896 R[t] = bits(32) UNKNOWN;
897 }
898#endif
899
900 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000901 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen788e0552011-01-27 22:52:23 +0000902 if (!success)
903 return false;
904
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000905 if (ConditionPassed())
Johnny Chen788e0552011-01-27 22:52:23 +0000906 {
Johnny Chene39f22d2011-02-19 01:36:13 +0000907 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000908 if (!success)
909 return false;
Johnny Chen809742e2011-01-28 00:32:27 +0000910
911 // PC relative immediate load context
Caroline Tice9bfe7f22011-02-14 23:03:21 +0000912 EmulateInstruction::Context context;
913 context.type = EmulateInstruction::eContextRegisterPlusOffset;
914 Register pc_reg;
915 pc_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
916 context.SetRegisterPlusOffset (pc_reg, 0);
917
Johnny Chenc9de9102011-02-11 19:12:30 +0000918 uint32_t Rt; // the destination register
Johnny Chen788e0552011-01-27 22:52:23 +0000919 uint32_t imm32; // immediate offset from the PC
Johnny Chenc9de9102011-02-11 19:12:30 +0000920 bool add; // +imm32 or -imm32?
921 addr_t base; // the base address
922 addr_t address; // the PC relative address
Johnny Chen788e0552011-01-27 22:52:23 +0000923 uint32_t data; // the literal data value from the PC relative load
924 switch (encoding) {
925 case eEncodingT1:
Johnny Chenc9de9102011-02-11 19:12:30 +0000926 Rt = Bits32(opcode, 10, 8);
Johnny Chen788e0552011-01-27 22:52:23 +0000927 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
Johnny Chenc9de9102011-02-11 19:12:30 +0000928 add = true;
Johnny Chenc9de9102011-02-11 19:12:30 +0000929 break;
930 case eEncodingT2:
931 Rt = Bits32(opcode, 15, 12);
932 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
933 add = BitIsSet(opcode, 23);
Johnny Chen098ae2d2011-02-12 00:50:05 +0000934 if (Rt == 15 && InITBlock() && !LastInITBlock())
Johnny Chenc9de9102011-02-11 19:12:30 +0000935 return false;
Johnny Chen788e0552011-01-27 22:52:23 +0000936 break;
937 default:
938 return false;
939 }
Johnny Chenc9de9102011-02-11 19:12:30 +0000940
Johnny Chene39f22d2011-02-19 01:36:13 +0000941 base = Align(pc, 4);
Johnny Chenc9de9102011-02-11 19:12:30 +0000942 if (add)
943 address = base + imm32;
944 else
945 address = base - imm32;
Johnny Chene39f22d2011-02-19 01:36:13 +0000946
947 context.SetRegisterPlusOffset(pc_reg, address - base);
Caroline Ticecc96eb52011-02-17 19:20:40 +0000948 data = MemURead(context, address, 4, 0, &success);
Johnny Chen788e0552011-01-27 22:52:23 +0000949 if (!success)
Johnny Chen809742e2011-01-28 00:32:27 +0000950 return false;
Johnny Chenc9de9102011-02-11 19:12:30 +0000951
952 if (Rt == 15)
953 {
954 if (Bits32(address, 1, 0) == 0)
955 {
956 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +0000957 if (!LoadWritePC(context, data))
Johnny Chenc9de9102011-02-11 19:12:30 +0000958 return false;
959 }
960 else
961 return false;
962 }
963 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
964 {
965 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
966 return false;
967 }
968 else // We don't handle ARM for now.
969 return false;
970
971 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
Johnny Chen788e0552011-01-27 22:52:23 +0000972 return false;
973 }
974 return true;
975}
976
Johnny Chen5b442b72011-01-27 19:34:30 +0000977// An add operation to adjust the SP.
Johnny Chenfdd179e2011-01-31 20:09:28 +0000978// ADD (SP plus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +0000979bool
Johnny Chen864a8e82011-02-18 00:07:39 +0000980EmulateInstructionARM::EmulateADDSPImm (ARMEncoding encoding)
Johnny Chenfdd179e2011-01-31 20:09:28 +0000981{
982#if 0
983 // ARM pseudo code...
984 if (ConditionPassed())
985 {
986 EncodingSpecificOperations();
987 (result, carry, overflow) = AddWithCarry(SP, imm32, ‘0’);
988 if d == 15 then // Can only occur for ARM encoding
989 ALUWritePC(result); // setflags is always FALSE here
990 else
991 R[d] = result;
992 if setflags then
993 APSR.N = result<31>;
994 APSR.Z = IsZeroBit(result);
995 APSR.C = carry;
996 APSR.V = overflow;
997 }
998#endif
999
1000 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001001 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001002 if (!success)
1003 return false;
1004
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001005 if (ConditionPassed())
Johnny Chenfdd179e2011-01-31 20:09:28 +00001006 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001007 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001008 if (!success)
1009 return false;
1010 uint32_t imm32; // the immediate operand
1011 switch (encoding) {
1012 case eEncodingT2:
Johnny Chena695f952011-02-23 21:24:25 +00001013 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chenfdd179e2011-01-31 20:09:28 +00001014 break;
1015 default:
1016 return false;
1017 }
1018 addr_t sp_offset = imm32;
1019 addr_t addr = sp + sp_offset; // the adjusted stack pointer value
1020
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001021 EmulateInstruction::Context context;
1022 context.type = EmulateInstruction::eContextAdjustStackPointer;
1023 context.SetImmediateSigned (sp_offset);
Johnny Chenfdd179e2011-01-31 20:09:28 +00001024
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001025 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chenfdd179e2011-01-31 20:09:28 +00001026 return false;
1027 }
1028 return true;
1029}
1030
1031// An add operation to adjust the SP.
Johnny Chen5b442b72011-01-27 19:34:30 +00001032// ADD (SP plus register)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001033bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001034EmulateInstructionARM::EmulateADDSPRm (ARMEncoding encoding)
Johnny Chen5b442b72011-01-27 19:34:30 +00001035{
1036#if 0
1037 // ARM pseudo code...
1038 if (ConditionPassed())
1039 {
1040 EncodingSpecificOperations();
1041 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1042 (result, carry, overflow) = AddWithCarry(SP, shifted, ‘0’);
1043 if d == 15 then
1044 ALUWritePC(result); // setflags is always FALSE here
1045 else
1046 R[d] = result;
1047 if setflags then
1048 APSR.N = result<31>;
1049 APSR.Z = IsZeroBit(result);
1050 APSR.C = carry;
1051 APSR.V = overflow;
1052 }
1053#endif
1054
1055 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001056 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001057 if (!success)
1058 return false;
1059
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001060 if (ConditionPassed())
Johnny Chen5b442b72011-01-27 19:34:30 +00001061 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001062 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001063 if (!success)
1064 return false;
1065 uint32_t Rm; // the second operand
1066 switch (encoding) {
1067 case eEncodingT2:
1068 Rm = Bits32(opcode, 6, 3);
1069 break;
1070 default:
1071 return false;
1072 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001073 int32_t reg_value = ReadCoreReg(Rm, &success);
Johnny Chen5b442b72011-01-27 19:34:30 +00001074 if (!success)
1075 return false;
1076
1077 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1078
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001079 EmulateInstruction::Context context;
1080 context.type = EmulateInstruction::eContextAdjustStackPointer;
1081 context.SetImmediateSigned (reg_value);
Johnny Chen5b442b72011-01-27 19:34:30 +00001082
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001083 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
Johnny Chen5b442b72011-01-27 19:34:30 +00001084 return false;
1085 }
1086 return true;
1087}
1088
Johnny Chen9b8d7832011-02-02 01:13:56 +00001089// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
1090// at a PC-relative address, and changes instruction set from ARM to Thumb, or
1091// from Thumb to ARM.
1092// BLX (immediate)
1093bool
1094EmulateInstructionARM::EmulateBLXImmediate (ARMEncoding encoding)
1095{
1096#if 0
1097 // ARM pseudo code...
1098 if (ConditionPassed())
1099 {
1100 EncodingSpecificOperations();
1101 if CurrentInstrSet() == InstrSet_ARM then
1102 LR = PC - 4;
1103 else
1104 LR = PC<31:1> : '1';
1105 if targetInstrSet == InstrSet_ARM then
1106 targetAddress = Align(PC,4) + imm32;
1107 else
1108 targetAddress = PC + imm32;
1109 SelectInstrSet(targetInstrSet);
1110 BranchWritePC(targetAddress);
1111 }
1112#endif
1113
1114 bool success = false;
1115 const uint32_t opcode = OpcodeAsUnsigned (&success);
1116 if (!success)
1117 return false;
1118
1119 if (ConditionPassed())
1120 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001121 EmulateInstruction::Context context;
1122 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001123 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001124 if (!success)
1125 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001126 addr_t lr; // next instruction address
1127 addr_t target; // target address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001128 int32_t imm32; // PC-relative offset
1129 switch (encoding) {
Johnny Chend6c13f02011-02-08 20:36:34 +00001130 case eEncodingT1:
1131 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001132 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001133 uint32_t S = Bit32(opcode, 26);
Johnny Chend6c13f02011-02-08 20:36:34 +00001134 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001135 uint32_t J1 = Bit32(opcode, 13);
1136 uint32_t J2 = Bit32(opcode, 11);
Johnny Chend6c13f02011-02-08 20:36:34 +00001137 uint32_t imm11 = Bits32(opcode, 10, 0);
1138 uint32_t I1 = !(J1 ^ S);
1139 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001140 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chend6c13f02011-02-08 20:36:34 +00001141 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001142 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001143 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001144 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001145 return false;
Johnny Chend6c13f02011-02-08 20:36:34 +00001146 break;
1147 }
Johnny Chen9b8d7832011-02-02 01:13:56 +00001148 case eEncodingT2:
1149 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001150 lr = pc | 1u; // return address
Johnny Chenbd599902011-02-10 21:39:01 +00001151 uint32_t S = Bit32(opcode, 26);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001152 uint32_t imm10H = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001153 uint32_t J1 = Bit32(opcode, 13);
1154 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001155 uint32_t imm10L = Bits32(opcode, 10, 1);
1156 uint32_t I1 = !(J1 ^ S);
1157 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001158 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001159 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001160 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001161 context.SetModeAndImmediateSigned (eModeARM, 4 + imm32);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001162 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001163 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001164 break;
1165 }
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001166 case eEncodingA1:
1167 lr = pc + 4; // return address
1168 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001169 target = Align(pc, 4) + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001170 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chenc47d0ca2011-02-08 18:58:31 +00001171 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001172 case eEncodingA2:
1173 lr = pc + 4; // return address
1174 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001175 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001176 context.SetModeAndImmediateSigned (eModeThumb, 8 + imm32);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001177 break;
1178 default:
1179 return false;
1180 }
1181 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1182 return false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00001183 if (!BranchWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001184 return false;
1185 }
1186 return true;
1187}
1188
1189// Branch with Link and Exchange (register) calls a subroutine at an address and
1190// instruction set specified by a register.
1191// BLX (register)
1192bool
1193EmulateInstructionARM::EmulateBLXRm (ARMEncoding encoding)
1194{
1195#if 0
1196 // ARM pseudo code...
1197 if (ConditionPassed())
1198 {
1199 EncodingSpecificOperations();
1200 target = R[m];
1201 if CurrentInstrSet() == InstrSet_ARM then
1202 next_instr_addr = PC - 4;
1203 LR = next_instr_addr;
1204 else
1205 next_instr_addr = PC - 2;
1206 LR = next_instr_addr<31:1> : ‘1’;
1207 BXWritePC(target);
1208 }
1209#endif
1210
1211 bool success = false;
1212 const uint32_t opcode = OpcodeAsUnsigned (&success);
1213 if (!success)
1214 return false;
1215
1216 if (ConditionPassed())
1217 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001218 EmulateInstruction::Context context;
1219 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chene39f22d2011-02-19 01:36:13 +00001220 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001221 addr_t lr; // next instruction address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001222 if (!success)
1223 return false;
1224 uint32_t Rm; // the register with the target address
1225 switch (encoding) {
1226 case eEncodingT1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001227 lr = (pc - 2) | 1u; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001228 Rm = Bits32(opcode, 6, 3);
1229 // if m == 15 then UNPREDICTABLE;
1230 if (Rm == 15)
1231 return false;
Johnny Chen098ae2d2011-02-12 00:50:05 +00001232 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001233 return false;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001234 break;
1235 case eEncodingA1:
Johnny Chene39f22d2011-02-19 01:36:13 +00001236 lr = pc - 4; // return address
Johnny Chen9b8d7832011-02-02 01:13:56 +00001237 Rm = Bits32(opcode, 3, 0);
1238 // if m == 15 then UNPREDICTABLE;
1239 if (Rm == 15)
1240 return false;
Johnny Chenb77be412011-02-04 00:40:18 +00001241 break;
Johnny Chen9b8d7832011-02-02 01:13:56 +00001242 default:
1243 return false;
1244 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001245 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001246 if (!success)
1247 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001248 Register dwarf_reg;
1249 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1250 context.SetRegister (dwarf_reg);
Johnny Chen9b8d7832011-02-02 01:13:56 +00001251 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1252 return false;
Johnny Chen668b4512011-02-15 21:08:58 +00001253 if (!BXWritePC(context, target))
Johnny Chen9b8d7832011-02-02 01:13:56 +00001254 return false;
1255 }
1256 return true;
1257}
1258
Johnny Chenab3b3512011-02-12 00:10:51 +00001259// Branch and Exchange causes a branch to an address and instruction set specified by a register.
Johnny Chenab3b3512011-02-12 00:10:51 +00001260bool
1261EmulateInstructionARM::EmulateBXRm (ARMEncoding encoding)
1262{
1263#if 0
1264 // ARM pseudo code...
1265 if (ConditionPassed())
1266 {
1267 EncodingSpecificOperations();
1268 BXWritePC(R[m]);
1269 }
1270#endif
1271
1272 bool success = false;
1273 const uint32_t opcode = OpcodeAsUnsigned (&success);
1274 if (!success)
1275 return false;
1276
1277 if (ConditionPassed())
1278 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001279 EmulateInstruction::Context context;
1280 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
Johnny Chenab3b3512011-02-12 00:10:51 +00001281 uint32_t Rm; // the register with the target address
1282 switch (encoding) {
1283 case eEncodingT1:
1284 Rm = Bits32(opcode, 6, 3);
Johnny Chen098ae2d2011-02-12 00:50:05 +00001285 if (InITBlock() && !LastInITBlock())
Johnny Chenab3b3512011-02-12 00:10:51 +00001286 return false;
1287 break;
1288 case eEncodingA1:
1289 Rm = Bits32(opcode, 3, 0);
1290 break;
1291 default:
1292 return false;
1293 }
Johnny Chene39f22d2011-02-19 01:36:13 +00001294 addr_t target = ReadCoreReg (Rm, &success);
Johnny Chenab3b3512011-02-12 00:10:51 +00001295 if (!success)
1296 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001297
1298 Register dwarf_reg;
1299 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
Johnny Chen668b4512011-02-15 21:08:58 +00001300 context.SetRegister (dwarf_reg);
1301 if (!BXWritePC(context, target))
Johnny Chenab3b3512011-02-12 00:10:51 +00001302 return false;
1303 }
1304 return true;
1305}
1306
Johnny Chen59e6ab72011-02-24 21:01:20 +00001307// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
1308// address and instruction set specified by a register as though it were a BX instruction.
1309//
1310// TODO: Emulate Jazelle architecture?
1311// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
1312bool
1313EmulateInstructionARM::EmulateBXJRm (ARMEncoding encoding)
1314{
1315#if 0
1316 // ARM pseudo code...
1317 if (ConditionPassed())
1318 {
1319 EncodingSpecificOperations();
1320 if JMCR.JE == ‘0’ || CurrentInstrSet() == InstrSet_ThumbEE then
1321 BXWritePC(R[m]);
1322 else
1323 if JazelleAcceptsExecution() then
1324 SwitchToJazelleExecution();
1325 else
1326 SUBARCHITECTURE_DEFINED handler call;
1327 }
1328#endif
1329
1330 bool success = false;
1331 const uint32_t opcode = OpcodeAsUnsigned (&success);
1332 if (!success)
1333 return false;
1334
1335 if (ConditionPassed())
1336 {
1337 EmulateInstruction::Context context;
1338 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
1339 uint32_t Rm; // the register with the target address
1340 switch (encoding) {
1341 case eEncodingT1:
1342 Rm = Bits32(opcode, 19, 16);
1343 if (BadReg(Rm))
1344 return false;
1345 if (InITBlock() && !LastInITBlock())
1346 return false;
1347 break;
1348 case eEncodingA1:
1349 Rm = Bits32(opcode, 3, 0);
1350 if (Rm == 15)
1351 return false;
1352 break;
1353 default:
1354 return false;
1355 }
1356 addr_t target = ReadCoreReg (Rm, &success);
1357 if (!success)
1358 return false;
1359
1360 Register dwarf_reg;
1361 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rm);
1362 context.SetRegister (dwarf_reg);
1363 if (!BXWritePC(context, target))
1364 return false;
1365 }
1366 return true;
1367}
1368
Johnny Chen0d0148e2011-01-28 02:26:08 +00001369// Set r7 to point to some ip offset.
1370// SUB (immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001371bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001372EmulateInstructionARM::EmulateSUBR7IPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001373{
1374#if 0
1375 // ARM pseudo code...
1376 if (ConditionPassed())
1377 {
1378 EncodingSpecificOperations();
1379 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1380 if d == 15 then // Can only occur for ARM encoding
1381 ALUWritePC(result); // setflags is always FALSE here
1382 else
1383 R[d] = result;
1384 if setflags then
1385 APSR.N = result<31>;
1386 APSR.Z = IsZeroBit(result);
1387 APSR.C = carry;
1388 APSR.V = overflow;
1389 }
1390#endif
1391
1392 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001393 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001394 if (!success)
1395 return false;
1396
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001397 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001398 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001399 const addr_t ip = ReadCoreReg (12, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001400 if (!success)
1401 return false;
1402 uint32_t imm32;
1403 switch (encoding) {
1404 case eEncodingA1:
1405 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1406 break;
1407 default:
1408 return false;
1409 }
1410 addr_t ip_offset = imm32;
1411 addr_t addr = ip - ip_offset; // the adjusted ip value
1412
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001413 EmulateInstruction::Context context;
1414 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1415 Register dwarf_reg;
1416 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r12);
1417 context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001418
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001419 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001420 return false;
1421 }
1422 return true;
1423}
1424
1425// Set ip to point to some stack offset.
1426// SUB (SP minus immediate)
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001427bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001428EmulateInstructionARM::EmulateSUBIPSPImm (ARMEncoding encoding)
Johnny Chen0d0148e2011-01-28 02:26:08 +00001429{
1430#if 0
1431 // ARM pseudo code...
1432 if (ConditionPassed())
1433 {
1434 EncodingSpecificOperations();
1435 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
1436 if d == 15 then // Can only occur for ARM encoding
1437 ALUWritePC(result); // setflags is always FALSE here
1438 else
1439 R[d] = result;
1440 if setflags then
1441 APSR.N = result<31>;
1442 APSR.Z = IsZeroBit(result);
1443 APSR.C = carry;
1444 APSR.V = overflow;
1445 }
1446#endif
1447
1448 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001449 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001450 if (!success)
1451 return false;
1452
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001453 if (ConditionPassed())
Johnny Chen0d0148e2011-01-28 02:26:08 +00001454 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001455 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001456 if (!success)
1457 return false;
1458 uint32_t imm32;
1459 switch (encoding) {
1460 case eEncodingA1:
1461 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1462 break;
1463 default:
1464 return false;
1465 }
1466 addr_t sp_offset = imm32;
1467 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
1468
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001469 EmulateInstruction::Context context;
1470 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1471 Register dwarf_reg;
1472 dwarf_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
1473 context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
Johnny Chen0d0148e2011-01-28 02:26:08 +00001474
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001475 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
Johnny Chen0d0148e2011-01-28 02:26:08 +00001476 return false;
1477 }
1478 return true;
1479}
1480
Johnny Chenc9e747f2011-02-23 01:55:07 +00001481// This instruction subtracts an immediate value from the SP value, and writes
1482// the result to the destination register.
1483//
1484// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001485bool
Johnny Chen864a8e82011-02-18 00:07:39 +00001486EmulateInstructionARM::EmulateSUBSPImm (ARMEncoding encoding)
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001487{
1488#if 0
1489 // ARM pseudo code...
1490 if (ConditionPassed())
1491 {
1492 EncodingSpecificOperations();
1493 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), ‘1’);
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001494 if d == 15 then // Can only occur for ARM encoding
Johnny Chen799dfd02011-01-26 23:14:33 +00001495 ALUWritePC(result); // setflags is always FALSE here
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001496 else
1497 R[d] = result;
1498 if setflags then
1499 APSR.N = result<31>;
1500 APSR.Z = IsZeroBit(result);
1501 APSR.C = carry;
1502 APSR.V = overflow;
1503 }
1504#endif
1505
1506 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001507 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001508 if (!success)
1509 return false;
1510
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001511 if (ConditionPassed())
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001512 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001513 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001514 if (!success)
1515 return false;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001516
1517 uint32_t Rd;
1518 bool setflags;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001519 uint32_t imm32;
1520 switch (encoding) {
Johnny Chene4455022011-01-26 00:08:59 +00001521 case eEncodingT1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001522 Rd = 13;
1523 setflags = false;
Johnny Chena695f952011-02-23 21:24:25 +00001524 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
Johnny Chened32e7c2011-02-22 23:42:58 +00001525 break;
Johnny Chen60c0d622011-01-25 23:49:39 +00001526 case eEncodingT2:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001527 Rd = Bits32(opcode, 11, 8);
1528 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001529 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
Johnny Chenc9e747f2011-02-23 01:55:07 +00001530 if (Rd == 15 && setflags)
1531 return EmulateCMPImm(eEncodingT2);
1532 if (Rd == 15 && !setflags)
1533 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001534 break;
1535 case eEncodingT3:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001536 Rd = Bits32(opcode, 11, 8);
1537 setflags = false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001538 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001539 if (Rd == 15)
1540 return false;
Johnny Chen60c0d622011-01-25 23:49:39 +00001541 break;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001542 case eEncodingA1:
Johnny Chenc9e747f2011-02-23 01:55:07 +00001543 Rd = Bits32(opcode, 15, 12);
1544 setflags = BitIsSet(opcode, 20);
Johnny Chen60c0d622011-01-25 23:49:39 +00001545 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chen15a7a6b2011-02-23 23:47:56 +00001546 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
1547 // TODO: Emulate SUBS PC, LR and related instructions.
1548 if (Rd == 15 && setflags)
1549 return false;
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001550 break;
1551 default:
1552 return false;
1553 }
Johnny Chenc9e747f2011-02-23 01:55:07 +00001554 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
1555
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001556 EmulateInstruction::Context context;
Johnny Chenc9e747f2011-02-23 01:55:07 +00001557 if (Rd == 13)
1558 {
1559 context.type = EmulateInstruction::eContextAdjustStackPointer;
1560 context.SetImmediateSigned (-imm32); // the stack pointer offset
1561 }
1562 else
1563 {
1564 context.type = EmulateInstruction::eContextImmediate;
1565 context.SetNoArgs ();
1566 }
1567
1568 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00001569 return false;
1570 }
1571 return true;
1572}
1573
Johnny Chen08c25e82011-01-31 18:02:28 +00001574// A store operation to the stack that also updates the SP.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001575bool
1576EmulateInstructionARM::EmulateSTRRtSP (ARMEncoding encoding)
Johnny Chence1ca772011-01-25 01:13:00 +00001577{
1578#if 0
1579 // ARM pseudo code...
1580 if (ConditionPassed())
1581 {
1582 EncodingSpecificOperations();
1583 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
1584 address = if index then offset_addr else R[n];
1585 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
1586 if wback then R[n] = offset_addr;
1587 }
1588#endif
1589
1590 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001591 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chence1ca772011-01-25 01:13:00 +00001592 if (!success)
1593 return false;
1594
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001595 if (ConditionPassed())
Johnny Chence1ca772011-01-25 01:13:00 +00001596 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001597 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001598 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001599 if (!success)
1600 return false;
Johnny Chen91d99862011-01-25 19:07:04 +00001601 uint32_t Rt; // the source register
Johnny Chence1ca772011-01-25 01:13:00 +00001602 uint32_t imm12;
1603 switch (encoding) {
1604 case eEncodingA1:
Johnny Chen108d5aa2011-01-26 01:00:55 +00001605 Rt = Bits32(opcode, 15, 12);
1606 imm12 = Bits32(opcode, 11, 0);
Johnny Chence1ca772011-01-25 01:13:00 +00001607 break;
1608 default:
1609 return false;
1610 }
1611 addr_t sp_offset = imm12;
1612 addr_t addr = sp - sp_offset;
1613
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001614 EmulateInstruction::Context context;
1615 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1616 Register dwarf_reg;
1617 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen91d99862011-01-25 19:07:04 +00001618 if (Rt != 15)
Johnny Chence1ca772011-01-25 01:13:00 +00001619 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001620 dwarf_reg.num = dwarf_r0 + Rt;
1621 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001622 uint32_t reg_value = ReadCoreReg(Rt, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001623 if (!success)
1624 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001625 if (!MemUWrite (context, addr, reg_value, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001626 return false;
1627 }
1628 else
1629 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001630 dwarf_reg.num = dwarf_pc;
1631 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Johnny Chene39f22d2011-02-19 01:36:13 +00001632 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chence1ca772011-01-25 01:13:00 +00001633 if (!success)
1634 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001635 if (!MemUWrite (context, addr, pc + 8, addr_byte_size))
Johnny Chence1ca772011-01-25 01:13:00 +00001636 return false;
1637 }
1638
1639 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001640 context.SetImmediateSigned (-sp_offset);
Johnny Chence1ca772011-01-25 01:13:00 +00001641
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001642 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chence1ca772011-01-25 01:13:00 +00001643 return false;
1644 }
1645 return true;
1646}
1647
Johnny Chen08c25e82011-01-31 18:02:28 +00001648// Vector Push stores multiple extension registers to the stack.
1649// It also updates SP to point to the start of the stored data.
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001650bool
1651EmulateInstructionARM::EmulateVPUSH (ARMEncoding encoding)
Johnny Chen799dfd02011-01-26 23:14:33 +00001652{
1653#if 0
1654 // ARM pseudo code...
1655 if (ConditionPassed())
1656 {
1657 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1658 address = SP - imm32;
1659 SP = SP - imm32;
1660 if single_regs then
1661 for r = 0 to regs-1
1662 MemA[address,4] = S[d+r]; address = address+4;
1663 else
1664 for r = 0 to regs-1
1665 // Store as two word-aligned words in the correct order for current endianness.
1666 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
1667 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
1668 address = address+8;
1669 }
1670#endif
1671
1672 bool success = false;
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001673 const uint32_t opcode = OpcodeAsUnsigned (&success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001674 if (!success)
1675 return false;
1676
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001677 if (ConditionPassed())
Johnny Chen799dfd02011-01-26 23:14:33 +00001678 {
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001679 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001680 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001681 if (!success)
1682 return false;
1683 bool single_regs;
Johnny Chen587a0a42011-02-01 18:35:28 +00001684 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
Johnny Chen799dfd02011-01-26 23:14:33 +00001685 uint32_t imm32; // stack offset
1686 uint32_t regs; // number of registers
1687 switch (encoding) {
1688 case eEncodingT1:
1689 case eEncodingA1:
1690 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001691 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen799dfd02011-01-26 23:14:33 +00001692 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1693 // If UInt(imm8) is odd, see "FSTMX".
1694 regs = Bits32(opcode, 7, 0) / 2;
1695 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1696 if (regs == 0 || regs > 16 || (d + regs) > 32)
1697 return false;
1698 break;
1699 case eEncodingT2:
1700 case eEncodingA2:
1701 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001702 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen799dfd02011-01-26 23:14:33 +00001703 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1704 regs = Bits32(opcode, 7, 0);
1705 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1706 if (regs == 0 || regs > 16 || (d + regs) > 32)
1707 return false;
1708 break;
1709 default:
1710 return false;
1711 }
1712 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1713 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1714 addr_t sp_offset = imm32;
1715 addr_t addr = sp - sp_offset;
1716 uint32_t i;
1717
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001718 EmulateInstruction::Context context;
1719 context.type = EmulateInstruction::eContextPushRegisterOnStack;
1720 Register dwarf_reg;
1721 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen799dfd02011-01-26 23:14:33 +00001722 for (i=d; i<regs; ++i)
1723 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001724 dwarf_reg.num = start_reg + i;
1725 context.SetRegisterPlusOffset ( dwarf_reg, addr - sp);
Johnny Chen799dfd02011-01-26 23:14:33 +00001726 // uint64_t to accommodate 64-bit registers.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001727 uint64_t reg_value = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_reg.num, 0, &success);
Johnny Chen799dfd02011-01-26 23:14:33 +00001728 if (!success)
1729 return false;
Caroline Ticecc96eb52011-02-17 19:20:40 +00001730 if (!MemAWrite (context, addr, reg_value, reg_byte_size))
Johnny Chen799dfd02011-01-26 23:14:33 +00001731 return false;
1732 addr += reg_byte_size;
1733 }
1734
1735 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001736 context.SetImmediateSigned (-sp_offset);
Johnny Chen799dfd02011-01-26 23:14:33 +00001737
Greg Clayton2b8e8b02011-02-01 00:49:32 +00001738 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
Johnny Chen799dfd02011-01-26 23:14:33 +00001739 return false;
1740 }
1741 return true;
1742}
1743
Johnny Chen587a0a42011-02-01 18:35:28 +00001744// Vector Pop loads multiple extension registers from the stack.
1745// It also updates SP to point just above the loaded data.
1746bool
1747EmulateInstructionARM::EmulateVPOP (ARMEncoding encoding)
1748{
1749#if 0
1750 // ARM pseudo code...
1751 if (ConditionPassed())
1752 {
1753 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
1754 address = SP;
1755 SP = SP + imm32;
1756 if single_regs then
1757 for r = 0 to regs-1
1758 S[d+r] = MemA[address,4]; address = address+4;
1759 else
1760 for r = 0 to regs-1
1761 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
1762 // Combine the word-aligned words in the correct order for current endianness.
1763 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
1764 }
1765#endif
1766
1767 bool success = false;
1768 const uint32_t opcode = OpcodeAsUnsigned (&success);
1769 if (!success)
1770 return false;
1771
1772 if (ConditionPassed())
1773 {
1774 const uint32_t addr_byte_size = GetAddressByteSize();
Johnny Chene39f22d2011-02-19 01:36:13 +00001775 const addr_t sp = ReadCoreReg (SP_REG, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001776 if (!success)
1777 return false;
1778 bool single_regs;
1779 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
1780 uint32_t imm32; // stack offset
1781 uint32_t regs; // number of registers
1782 switch (encoding) {
1783 case eEncodingT1:
1784 case eEncodingA1:
1785 single_regs = false;
Johnny Chenbd599902011-02-10 21:39:01 +00001786 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
Johnny Chen587a0a42011-02-01 18:35:28 +00001787 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1788 // If UInt(imm8) is odd, see "FLDMX".
1789 regs = Bits32(opcode, 7, 0) / 2;
1790 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1791 if (regs == 0 || regs > 16 || (d + regs) > 32)
1792 return false;
1793 break;
1794 case eEncodingT2:
1795 case eEncodingA2:
1796 single_regs = true;
Johnny Chenbd599902011-02-10 21:39:01 +00001797 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
Johnny Chen587a0a42011-02-01 18:35:28 +00001798 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
1799 regs = Bits32(opcode, 7, 0);
1800 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
1801 if (regs == 0 || regs > 16 || (d + regs) > 32)
1802 return false;
1803 break;
1804 default:
1805 return false;
1806 }
1807 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
1808 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
1809 addr_t sp_offset = imm32;
1810 addr_t addr = sp;
1811 uint32_t i;
1812 uint64_t data; // uint64_t to accomodate 64-bit registers.
1813
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001814 EmulateInstruction::Context context;
1815 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1816 Register dwarf_reg;
1817 dwarf_reg.SetRegister (eRegisterKindDWARF, 0);
Johnny Chen587a0a42011-02-01 18:35:28 +00001818 for (i=d; i<regs; ++i)
1819 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001820 dwarf_reg.num = start_reg + i;
1821 context.SetRegisterPlusOffset (dwarf_reg, addr - sp);
Caroline Ticecc96eb52011-02-17 19:20:40 +00001822 data = MemARead(context, addr, reg_byte_size, 0, &success);
Johnny Chen587a0a42011-02-01 18:35:28 +00001823 if (!success)
1824 return false;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001825 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_reg.num, data))
Johnny Chen587a0a42011-02-01 18:35:28 +00001826 return false;
1827 addr += reg_byte_size;
1828 }
1829
1830 context.type = EmulateInstruction::eContextAdjustStackPointer;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001831 context.SetImmediateSigned (sp_offset);
Johnny Chen587a0a42011-02-01 18:35:28 +00001832
1833 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1834 return false;
1835 }
1836 return true;
1837}
1838
Johnny Chenb77be412011-02-04 00:40:18 +00001839// SVC (previously SWI)
1840bool
1841EmulateInstructionARM::EmulateSVC (ARMEncoding encoding)
1842{
1843#if 0
1844 // ARM pseudo code...
1845 if (ConditionPassed())
1846 {
1847 EncodingSpecificOperations();
1848 CallSupervisor();
1849 }
1850#endif
1851
1852 bool success = false;
1853 const uint32_t opcode = OpcodeAsUnsigned (&success);
1854 if (!success)
1855 return false;
1856
1857 if (ConditionPassed())
1858 {
Johnny Chene39f22d2011-02-19 01:36:13 +00001859 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chenb77be412011-02-04 00:40:18 +00001860 addr_t lr; // next instruction address
1861 if (!success)
1862 return false;
1863 uint32_t imm32; // the immediate constant
1864 uint32_t mode; // ARM or Thumb mode
1865 switch (encoding) {
1866 case eEncodingT1:
1867 lr = (pc + 2) | 1u; // return address
1868 imm32 = Bits32(opcode, 7, 0);
1869 mode = eModeThumb;
1870 break;
1871 case eEncodingA1:
1872 lr = pc + 4; // return address
1873 imm32 = Bits32(opcode, 23, 0);
1874 mode = eModeARM;
1875 break;
1876 default:
1877 return false;
1878 }
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001879
1880 EmulateInstruction::Context context;
1881 context.type = EmulateInstruction::eContextSupervisorCall;
1882 context.SetModeAndImmediate (mode, imm32);
Johnny Chenb77be412011-02-04 00:40:18 +00001883 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
1884 return false;
1885 }
1886 return true;
1887}
1888
Johnny Chenc315f862011-02-05 00:46:10 +00001889// If Then makes up to four following instructions (the IT block) conditional.
1890bool
1891EmulateInstructionARM::EmulateIT (ARMEncoding encoding)
1892{
1893#if 0
1894 // ARM pseudo code...
1895 EncodingSpecificOperations();
1896 ITSTATE.IT<7:0> = firstcond:mask;
1897#endif
1898
1899 bool success = false;
1900 const uint32_t opcode = OpcodeAsUnsigned (&success);
1901 if (!success)
1902 return false;
1903
1904 m_it_session.InitIT(Bits32(opcode, 7, 0));
1905 return true;
1906}
1907
Johnny Chen3b620b32011-02-07 20:11:47 +00001908// Branch causes a branch to a target address.
1909bool
1910EmulateInstructionARM::EmulateB (ARMEncoding encoding)
1911{
1912#if 0
1913 // ARM pseudo code...
1914 if (ConditionPassed())
1915 {
1916 EncodingSpecificOperations();
1917 BranchWritePC(PC + imm32);
1918 }
1919#endif
1920
1921 bool success = false;
1922 const uint32_t opcode = OpcodeAsUnsigned (&success);
1923 if (!success)
1924 return false;
1925
Johnny Chen9ee056b2011-02-08 00:06:35 +00001926 if (ConditionPassed())
1927 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001928 EmulateInstruction::Context context;
1929 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00001930 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001931 if (!success)
1932 return false;
Johnny Chen53ebab72011-02-08 23:21:57 +00001933 addr_t target; // target address
Johnny Chen9ee056b2011-02-08 00:06:35 +00001934 int32_t imm32; // PC-relative offset
1935 switch (encoding) {
1936 case eEncodingT1:
1937 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1938 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
Johnny Chene39f22d2011-02-19 01:36:13 +00001939 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001940 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001941 break;
1942 case eEncodingT2:
1943 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
Johnny Chene39f22d2011-02-19 01:36:13 +00001944 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001945 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001946 break;
1947 case eEncodingT3:
1948 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
1949 {
Johnny Chenbd599902011-02-10 21:39:01 +00001950 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001951 uint32_t imm6 = Bits32(opcode, 21, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001952 uint32_t J1 = Bit32(opcode, 13);
1953 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001954 uint32_t imm11 = Bits32(opcode, 10, 0);
Johnny Chen53ebab72011-02-08 23:21:57 +00001955 uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001956 imm32 = llvm::SignExtend32<21>(imm21);
Johnny Chene39f22d2011-02-19 01:36:13 +00001957 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001958 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001959 break;
1960 }
1961 case eEncodingT4:
1962 {
Johnny Chenbd599902011-02-10 21:39:01 +00001963 uint32_t S = Bit32(opcode, 26);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001964 uint32_t imm10 = Bits32(opcode, 25, 16);
Johnny Chenbd599902011-02-10 21:39:01 +00001965 uint32_t J1 = Bit32(opcode, 13);
1966 uint32_t J2 = Bit32(opcode, 11);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001967 uint32_t imm11 = Bits32(opcode, 10, 0);
1968 uint32_t I1 = !(J1 ^ S);
1969 uint32_t I2 = !(J2 ^ S);
Johnny Chen53ebab72011-02-08 23:21:57 +00001970 uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001971 imm32 = llvm::SignExtend32<25>(imm25);
Johnny Chene39f22d2011-02-19 01:36:13 +00001972 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001973 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001974 break;
1975 }
1976 case eEncodingA1:
1977 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
Johnny Chene39f22d2011-02-19 01:36:13 +00001978 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00001979 context.SetModeAndImmediateSigned (eModeARM, 8 + imm32);
Johnny Chen9ee056b2011-02-08 00:06:35 +00001980 break;
1981 default:
1982 return false;
1983 }
1984 if (!BranchWritePC(context, target))
1985 return false;
1986 }
1987 return true;
Johnny Chen3b620b32011-02-07 20:11:47 +00001988}
1989
Johnny Chen53ebab72011-02-08 23:21:57 +00001990// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
1991// zero and conditionally branch forward a constant value. They do not affect the condition flags.
1992// CBNZ, CBZ
1993bool
1994EmulateInstructionARM::EmulateCB (ARMEncoding encoding)
1995{
1996#if 0
1997 // ARM pseudo code...
1998 EncodingSpecificOperations();
1999 if nonzero ^ IsZero(R[n]) then
2000 BranchWritePC(PC + imm32);
2001#endif
2002
2003 bool success = false;
2004 const uint32_t opcode = OpcodeAsUnsigned (&success);
2005 if (!success)
2006 return false;
2007
2008 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002009 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002010 if (!success)
2011 return false;
2012
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002013 EmulateInstruction::Context context;
2014 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
Johnny Chene39f22d2011-02-19 01:36:13 +00002015 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen53ebab72011-02-08 23:21:57 +00002016 if (!success)
2017 return false;
2018
2019 addr_t target; // target address
2020 uint32_t imm32; // PC-relative offset to branch forward
2021 bool nonzero;
2022 switch (encoding) {
2023 case eEncodingT1:
Johnny Chenbd599902011-02-10 21:39:01 +00002024 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
Johnny Chen53ebab72011-02-08 23:21:57 +00002025 nonzero = BitIsSet(opcode, 11);
Johnny Chene39f22d2011-02-19 01:36:13 +00002026 target = pc + imm32;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002027 context.SetModeAndImmediateSigned (eModeThumb, 4 + imm32);
Johnny Chen53ebab72011-02-08 23:21:57 +00002028 break;
2029 default:
2030 return false;
2031 }
2032 if (nonzero ^ (reg_val == 0))
2033 if (!BranchWritePC(context, target))
2034 return false;
2035
2036 return true;
2037}
2038
Johnny Chen60299ec2011-02-17 19:34:27 +00002039// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
2040// A base register provides a pointer to the table, and a second register supplies an index into the table.
2041// The branch length is twice the value of the byte returned from the table.
2042//
2043// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
2044// A base register provides a pointer to the table, and a second register supplies an index into the table.
2045// The branch length is twice the value of the halfword returned from the table.
2046// TBB, TBH
2047bool
2048EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
2049{
2050#if 0
2051 // ARM pseudo code...
2052 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2053 if is_tbh then
2054 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2055 else
2056 halfwords = UInt(MemU[R[n]+R[m], 1]);
2057 BranchWritePC(PC + 2*halfwords);
2058#endif
2059
2060 bool success = false;
2061 const uint32_t opcode = OpcodeAsUnsigned (&success);
2062 if (!success)
2063 return false;
2064
2065 uint32_t Rn; // the base register which contains the address of the table of branch lengths
2066 uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table
2067 bool is_tbh; // true if table branch halfword
2068 switch (encoding) {
2069 case eEncodingT1:
2070 Rn = Bits32(opcode, 19, 16);
2071 Rm = Bits32(opcode, 3, 0);
2072 is_tbh = BitIsSet(opcode, 4);
2073 if (Rn == 13 || BadReg(Rm))
2074 return false;
2075 if (InITBlock() && !LastInITBlock())
2076 return false;
2077 break;
2078 default:
2079 return false;
2080 }
2081
2082 // Read the address of the table from the operand register Rn.
2083 // The PC can be used, in which case the table immediately follows this instruction.
Johnny Chene39f22d2011-02-19 01:36:13 +00002084 uint32_t base = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002085 if (!success)
2086 return false;
2087
2088 // the table index
Johnny Chene39f22d2011-02-19 01:36:13 +00002089 uint32_t index = ReadCoreReg(Rm, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002090 if (!success)
2091 return false;
2092
2093 // the offsetted table address
2094 addr_t addr = base + (is_tbh ? index*2 : index);
2095
2096 // PC-relative offset to branch forward
2097 EmulateInstruction::Context context;
2098 context.type = EmulateInstruction::eContextTableBranchReadMemory;
Johnny Chen104c8b62011-02-17 23:27:44 +00002099 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
Johnny Chen60299ec2011-02-17 19:34:27 +00002100 if (!success)
2101 return false;
2102
Johnny Chene39f22d2011-02-19 01:36:13 +00002103 const uint32_t pc = ReadCoreReg(PC_REG, &success);
Johnny Chen60299ec2011-02-17 19:34:27 +00002104 if (!success)
2105 return false;
2106
2107 // target address
Johnny Chene39f22d2011-02-19 01:36:13 +00002108 addr_t target = pc + offset;
Johnny Chen60299ec2011-02-17 19:34:27 +00002109 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2110 context.SetModeAndImmediateSigned (eModeThumb, 4 + offset);
2111
2112 if (!BranchWritePC(context, target))
2113 return false;
2114
2115 return true;
2116}
2117
Johnny Chen8fa20592011-02-18 01:22:22 +00002118// This instruction adds an immediate value to a register value, and writes the result to the destination
2119// register. It can optionally update the condition flags based on the result.
2120bool
2121EmulateInstructionARM::EmulateADDImmARM (ARMEncoding encoding)
2122{
2123#if 0
2124 // ARM pseudo code...
2125 if ConditionPassed() then
2126 EncodingSpecificOperations();
2127 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2128 if d == 15 then
2129 ALUWritePC(result); // setflags is always FALSE here
2130 else
2131 R[d] = result;
2132 if setflags then
2133 APSR.N = result<31>;
2134 APSR.Z = IsZeroBit(result);
2135 APSR.C = carry;
2136 APSR.V = overflow;
2137#endif
2138
2139 bool success = false;
2140 const uint32_t opcode = OpcodeAsUnsigned (&success);
2141 if (!success)
2142 return false;
2143
2144 if (ConditionPassed())
2145 {
2146 uint32_t Rd, Rn;
2147 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
2148 bool setflags;
2149 switch (encoding)
2150 {
2151 case eEncodingA1:
2152 Rd = Bits32(opcode, 15, 12);
2153 Rn = Bits32(opcode, 19, 16);
2154 setflags = BitIsSet(opcode, 20);
2155 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2156 break;
2157 default:
2158 return false;
2159 }
2160
Johnny Chen8fa20592011-02-18 01:22:22 +00002161 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002162 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen8fa20592011-02-18 01:22:22 +00002163 if (!success)
2164 return false;
2165
2166 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
2167
2168 EmulateInstruction::Context context;
2169 context.type = EmulateInstruction::eContextImmediate;
2170 context.SetNoArgs ();
2171
2172 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
2173 return false;
2174 }
2175 return true;
2176}
2177
Johnny Chend761dcf2011-02-17 22:03:29 +00002178// This instruction adds a register value and an optionally-shifted register value, and writes the result
2179// to the destination register. It can optionally update the condition flags based on the result.
Johnny Chen26863dc2011-02-09 23:43:29 +00002180bool
Johnny Chen9f687722011-02-18 00:02:28 +00002181EmulateInstructionARM::EmulateADDReg (ARMEncoding encoding)
Johnny Chen26863dc2011-02-09 23:43:29 +00002182{
2183#if 0
2184 // ARM pseudo code...
2185 if ConditionPassed() then
2186 EncodingSpecificOperations();
2187 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2188 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2189 if d == 15 then
2190 ALUWritePC(result); // setflags is always FALSE here
2191 else
2192 R[d] = result;
2193 if setflags then
2194 APSR.N = result<31>;
2195 APSR.Z = IsZeroBit(result);
2196 APSR.C = carry;
2197 APSR.V = overflow;
2198#endif
2199
2200 bool success = false;
2201 const uint32_t opcode = OpcodeAsUnsigned (&success);
2202 if (!success)
2203 return false;
2204
2205 if (ConditionPassed())
2206 {
2207 uint32_t Rd, Rn, Rm;
Johnny Chend761dcf2011-02-17 22:03:29 +00002208 ARM_ShifterType shift_t;
2209 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chenca67d1c2011-02-17 01:35:27 +00002210 bool setflags;
Johnny Chen26863dc2011-02-09 23:43:29 +00002211 switch (encoding)
2212 {
Johnny Chend761dcf2011-02-17 22:03:29 +00002213 case eEncodingT1:
2214 Rd = Bits32(opcode, 2, 0);
2215 Rn = Bits32(opcode, 5, 3);
2216 Rm = Bits32(opcode, 8, 6);
2217 setflags = !InITBlock();
2218 shift_t = SRType_LSL;
2219 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00002220 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002221 case eEncodingT2:
Johnny Chenbd599902011-02-10 21:39:01 +00002222 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Johnny Chen26863dc2011-02-09 23:43:29 +00002223 Rm = Bits32(opcode, 6, 3);
Johnny Chenca67d1c2011-02-17 01:35:27 +00002224 setflags = false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002225 shift_t = SRType_LSL;
2226 shift_n = 0;
Johnny Chen26863dc2011-02-09 23:43:29 +00002227 if (Rn == 15 && Rm == 15)
2228 return false;
Johnny Chend761dcf2011-02-17 22:03:29 +00002229 if (Rd == 15 && InITBlock() && !LastInITBlock())
2230 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002231 break;
Johnny Chen8fa20592011-02-18 01:22:22 +00002232 case eEncodingA1:
2233 Rd = Bits32(opcode, 15, 12);
2234 Rn = Bits32(opcode, 19, 16);
2235 Rm = Bits32(opcode, 3, 0);
2236 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00002237 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen8fa20592011-02-18 01:22:22 +00002238 break;
Johnny Chen26863dc2011-02-09 23:43:29 +00002239 default:
2240 return false;
2241 }
2242
Johnny Chen26863dc2011-02-09 23:43:29 +00002243 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002244 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002245 if (!success)
2246 return false;
2247
2248 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00002249 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chen26863dc2011-02-09 23:43:29 +00002250 if (!success)
2251 return false;
2252
Johnny Chene97c0d52011-02-18 19:32:20 +00002253 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen8fa20592011-02-18 01:22:22 +00002254 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002255
2256 EmulateInstruction::Context context;
2257 context.type = EmulateInstruction::eContextImmediate;
2258 context.SetNoArgs ();
Johnny Chenca67d1c2011-02-17 01:35:27 +00002259
Johnny Chen10530c22011-02-17 22:37:12 +00002260 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002261 return false;
Johnny Chen26863dc2011-02-09 23:43:29 +00002262 }
2263 return true;
2264}
2265
Johnny Chen34075cb2011-02-22 01:56:31 +00002266// Compare Negative (immediate) adds a register value and an immediate value.
2267// It updates the condition flags based on the result, and discards the result.
Johnny Chend4dc4442011-02-11 02:02:56 +00002268bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002269EmulateInstructionARM::EmulateCMNImm (ARMEncoding encoding)
2270{
2271#if 0
2272 // ARM pseudo code...
2273 if ConditionPassed() then
2274 EncodingSpecificOperations();
2275 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
2276 APSR.N = result<31>;
2277 APSR.Z = IsZeroBit(result);
2278 APSR.C = carry;
2279 APSR.V = overflow;
2280#endif
2281
2282 bool success = false;
2283 const uint32_t opcode = OpcodeAsUnsigned (&success);
2284 if (!success)
2285 return false;
2286
2287 uint32_t Rn; // the first operand
2288 uint32_t imm32; // the immediate value to be compared with
2289 switch (encoding) {
2290 case eEncodingT1:
Johnny Chen078fbc62011-02-22 19:48:22 +00002291 Rn = Bits32(opcode, 19, 16);
2292 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2293 if (Rn == 15)
2294 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002295 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002296 case eEncodingA1:
2297 Rn = Bits32(opcode, 19, 16);
2298 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2299 break;
2300 default:
2301 return false;
2302 }
2303 // Read the register value from the operand register Rn.
2304 uint32_t reg_val = ReadCoreReg(Rn, &success);
2305 if (!success)
2306 return false;
2307
Johnny Chen078fbc62011-02-22 19:48:22 +00002308 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002309
2310 EmulateInstruction::Context context;
2311 context.type = EmulateInstruction::eContextImmediate;
2312 context.SetNoArgs ();
2313 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2314 return false;
2315
2316 return true;
2317}
2318
2319// Compare Negative (register) adds a register value and an optionally-shifted register value.
2320// It updates the condition flags based on the result, and discards the result.
2321bool
2322EmulateInstructionARM::EmulateCMNReg (ARMEncoding encoding)
2323{
2324#if 0
2325 // ARM pseudo code...
2326 if ConditionPassed() then
2327 EncodingSpecificOperations();
2328 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2329 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
2330 APSR.N = result<31>;
2331 APSR.Z = IsZeroBit(result);
2332 APSR.C = carry;
2333 APSR.V = overflow;
2334#endif
2335
2336 bool success = false;
2337 const uint32_t opcode = OpcodeAsUnsigned (&success);
2338 if (!success)
2339 return false;
2340
2341 uint32_t Rn; // the first operand
2342 uint32_t Rm; // the second operand
2343 ARM_ShifterType shift_t;
2344 uint32_t shift_n; // the shift applied to the value read from Rm
2345 switch (encoding) {
2346 case eEncodingT1:
2347 Rn = Bits32(opcode, 2, 0);
2348 Rm = Bits32(opcode, 5, 3);
2349 shift_t = SRType_LSL;
2350 shift_n = 0;
2351 break;
2352 case eEncodingT2:
Johnny Chen078fbc62011-02-22 19:48:22 +00002353 Rn = Bits32(opcode, 19, 16);
2354 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002355 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen078fbc62011-02-22 19:48:22 +00002356 // if n == 15 || BadReg(m) then UNPREDICTABLE;
2357 if (Rn == 15 || BadReg(Rm))
Johnny Chen34075cb2011-02-22 01:56:31 +00002358 return false;
2359 break;
2360 case eEncodingA1:
2361 Rn = Bits32(opcode, 19, 16);
2362 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002363 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002364 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002365 default:
2366 return false;
2367 }
2368 // Read the register value from register Rn.
2369 uint32_t val1 = ReadCoreReg(Rn, &success);
2370 if (!success)
2371 return false;
2372
2373 // Read the register value from register Rm.
2374 uint32_t val2 = ReadCoreReg(Rm, &success);
2375 if (!success)
2376 return false;
2377
2378 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
Johnny Chen078fbc62011-02-22 19:48:22 +00002379 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
Johnny Chen34075cb2011-02-22 01:56:31 +00002380
2381 EmulateInstruction::Context context;
2382 context.type = EmulateInstruction::eContextImmediate;
2383 context.SetNoArgs();
2384 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2385 return false;
2386
2387 return true;
2388}
2389
2390// Compare (immediate) subtracts an immediate value from a register value.
2391// It updates the condition flags based on the result, and discards the result.
2392bool
2393EmulateInstructionARM::EmulateCMPImm (ARMEncoding encoding)
Johnny Chend4dc4442011-02-11 02:02:56 +00002394{
2395#if 0
2396 // ARM pseudo code...
2397 if ConditionPassed() then
2398 EncodingSpecificOperations();
2399 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
2400 APSR.N = result<31>;
2401 APSR.Z = IsZeroBit(result);
2402 APSR.C = carry;
2403 APSR.V = overflow;
2404#endif
2405
2406 bool success = false;
2407 const uint32_t opcode = OpcodeAsUnsigned (&success);
2408 if (!success)
2409 return false;
2410
2411 uint32_t Rn; // the first operand
2412 uint32_t imm32; // the immediate value to be compared with
2413 switch (encoding) {
2414 case eEncodingT1:
2415 Rn = Bits32(opcode, 10, 8);
2416 imm32 = Bits32(opcode, 7, 0);
Johnny Chened32e7c2011-02-22 23:42:58 +00002417 break;
Johnny Chen078fbc62011-02-22 19:48:22 +00002418 case eEncodingT2:
2419 Rn = Bits32(opcode, 19, 16);
2420 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2421 if (Rn == 15)
2422 return false;
Johnny Chened32e7c2011-02-22 23:42:58 +00002423 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002424 case eEncodingA1:
2425 Rn = Bits32(opcode, 19, 16);
2426 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
Johnny Chend4dc4442011-02-11 02:02:56 +00002427 break;
2428 default:
2429 return false;
2430 }
2431 // Read the register value from the operand register Rn.
Johnny Chene39f22d2011-02-19 01:36:13 +00002432 uint32_t reg_val = ReadCoreReg(Rn, &success);
Johnny Chend4dc4442011-02-11 02:02:56 +00002433 if (!success)
2434 return false;
2435
Johnny Chen10530c22011-02-17 22:37:12 +00002436 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
2437
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002438 EmulateInstruction::Context context;
2439 context.type = EmulateInstruction::eContextImmediate;
2440 context.SetNoArgs ();
Johnny Chen10530c22011-02-17 22:37:12 +00002441 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2442 return false;
2443
Johnny Chend4dc4442011-02-11 02:02:56 +00002444 return true;
2445}
2446
Johnny Chen34075cb2011-02-22 01:56:31 +00002447// Compare (register) subtracts an optionally-shifted register value from a register value.
2448// It updates the condition flags based on the result, and discards the result.
Johnny Chene4a4d302011-02-11 21:53:58 +00002449bool
Johnny Chen34075cb2011-02-22 01:56:31 +00002450EmulateInstructionARM::EmulateCMPReg (ARMEncoding encoding)
Johnny Chene4a4d302011-02-11 21:53:58 +00002451{
2452#if 0
2453 // ARM pseudo code...
2454 if ConditionPassed() then
2455 EncodingSpecificOperations();
2456 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
2457 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
2458 APSR.N = result<31>;
2459 APSR.Z = IsZeroBit(result);
2460 APSR.C = carry;
2461 APSR.V = overflow;
2462#endif
2463
2464 bool success = false;
2465 const uint32_t opcode = OpcodeAsUnsigned (&success);
2466 if (!success)
2467 return false;
2468
2469 uint32_t Rn; // the first operand
2470 uint32_t Rm; // the second operand
Johnny Chen34075cb2011-02-22 01:56:31 +00002471 ARM_ShifterType shift_t;
2472 uint32_t shift_n; // the shift applied to the value read from Rm
Johnny Chene4a4d302011-02-11 21:53:58 +00002473 switch (encoding) {
2474 case eEncodingT1:
2475 Rn = Bits32(opcode, 2, 0);
2476 Rm = Bits32(opcode, 5, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002477 shift_t = SRType_LSL;
2478 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002479 break;
2480 case eEncodingT2:
2481 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
2482 Rm = Bits32(opcode, 6, 3);
Johnny Chen34075cb2011-02-22 01:56:31 +00002483 shift_t = SRType_LSL;
2484 shift_n = 0;
Johnny Chene4a4d302011-02-11 21:53:58 +00002485 if (Rn < 8 && Rm < 8)
2486 return false;
2487 if (Rn == 15 || Rm == 15)
2488 return false;
2489 break;
Johnny Chen34075cb2011-02-22 01:56:31 +00002490 case eEncodingA1:
2491 Rn = Bits32(opcode, 19, 16);
2492 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00002493 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chened32e7c2011-02-22 23:42:58 +00002494 break;
Johnny Chene4a4d302011-02-11 21:53:58 +00002495 default:
2496 return false;
2497 }
2498 // Read the register value from register Rn.
Johnny Chen34075cb2011-02-22 01:56:31 +00002499 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002500 if (!success)
2501 return false;
Johnny Chen34075cb2011-02-22 01:56:31 +00002502
Johnny Chene4a4d302011-02-11 21:53:58 +00002503 // Read the register value from register Rm.
Johnny Chen34075cb2011-02-22 01:56:31 +00002504 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene4a4d302011-02-11 21:53:58 +00002505 if (!success)
2506 return false;
2507
Johnny Chen34075cb2011-02-22 01:56:31 +00002508 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
2509 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
Johnny Chen10530c22011-02-17 22:37:12 +00002510
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002511 EmulateInstruction::Context context;
2512 context.type = EmulateInstruction::eContextImmediate;
2513 context.SetNoArgs();
Johnny Chen10530c22011-02-17 22:37:12 +00002514 if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
2515 return false;
2516
Johnny Chene4a4d302011-02-11 21:53:58 +00002517 return true;
2518}
2519
Johnny Chen82f16aa2011-02-15 20:10:55 +00002520// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
2521// shifting in copies of its sign bit, and writes the result to the destination register. It can
2522// optionally update the condition flags based on the result.
2523bool
2524EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
2525{
2526#if 0
2527 // ARM pseudo code...
2528 if ConditionPassed() then
2529 EncodingSpecificOperations();
2530 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2531 if d == 15 then // Can only occur for ARM encoding
2532 ALUWritePC(result); // setflags is always FALSE here
2533 else
2534 R[d] = result;
2535 if setflags then
2536 APSR.N = result<31>;
2537 APSR.Z = IsZeroBit(result);
2538 APSR.C = carry;
2539 // APSR.V unchanged
2540#endif
2541
Johnny Chen41a0a152011-02-16 01:27:54 +00002542 return EmulateShiftImm(encoding, SRType_ASR);
2543}
2544
2545// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
2546// shifting in copies of its sign bit, and writes the result to the destination register.
2547// The variable number of bits is read from the bottom byte of a register. It can optionally update
2548// the condition flags based on the result.
2549bool
2550EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
2551{
2552#if 0
2553 // ARM pseudo code...
2554 if ConditionPassed() then
2555 EncodingSpecificOperations();
2556 shift_n = UInt(R[m]<7:0>);
2557 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
2558 R[d] = result;
2559 if setflags then
2560 APSR.N = result<31>;
2561 APSR.Z = IsZeroBit(result);
2562 APSR.C = carry;
2563 // APSR.V unchanged
2564#endif
2565
2566 return EmulateShiftReg(encoding, SRType_ASR);
2567}
2568
2569// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
2570// shifting in zeros, and writes the result to the destination register. It can optionally
2571// update the condition flags based on the result.
2572bool
2573EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
2574{
2575#if 0
2576 // ARM pseudo code...
2577 if ConditionPassed() then
2578 EncodingSpecificOperations();
2579 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2580 if d == 15 then // Can only occur for ARM encoding
2581 ALUWritePC(result); // setflags is always FALSE here
2582 else
2583 R[d] = result;
2584 if setflags then
2585 APSR.N = result<31>;
2586 APSR.Z = IsZeroBit(result);
2587 APSR.C = carry;
2588 // APSR.V unchanged
2589#endif
2590
2591 return EmulateShiftImm(encoding, SRType_LSL);
2592}
2593
2594// Logical Shift Left (register) shifts a register value left by a variable number of bits,
2595// shifting in zeros, and writes the result to the destination register. The variable number
2596// of bits is read from the bottom byte of a register. It can optionally update the condition
2597// flags based on the result.
2598bool
2599EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
2600{
2601#if 0
2602 // ARM pseudo code...
2603 if ConditionPassed() then
2604 EncodingSpecificOperations();
2605 shift_n = UInt(R[m]<7:0>);
2606 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
2607 R[d] = result;
2608 if setflags then
2609 APSR.N = result<31>;
2610 APSR.Z = IsZeroBit(result);
2611 APSR.C = carry;
2612 // APSR.V unchanged
2613#endif
2614
2615 return EmulateShiftReg(encoding, SRType_LSL);
2616}
2617
2618// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
2619// shifting in zeros, and writes the result to the destination register. It can optionally
2620// update the condition flags based on the result.
2621bool
2622EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
2623{
2624#if 0
2625 // ARM pseudo code...
2626 if ConditionPassed() then
2627 EncodingSpecificOperations();
2628 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2629 if d == 15 then // Can only occur for ARM encoding
2630 ALUWritePC(result); // setflags is always FALSE here
2631 else
2632 R[d] = result;
2633 if setflags then
2634 APSR.N = result<31>;
2635 APSR.Z = IsZeroBit(result);
2636 APSR.C = carry;
2637 // APSR.V unchanged
2638#endif
2639
2640 return EmulateShiftImm(encoding, SRType_LSR);
2641}
2642
2643// Logical Shift Right (register) shifts a register value right by a variable number of bits,
2644// shifting in zeros, and writes the result to the destination register. The variable number
2645// of bits is read from the bottom byte of a register. It can optionally update the condition
2646// flags based on the result.
2647bool
2648EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
2649{
2650#if 0
2651 // ARM pseudo code...
2652 if ConditionPassed() then
2653 EncodingSpecificOperations();
2654 shift_n = UInt(R[m]<7:0>);
2655 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
2656 R[d] = result;
2657 if setflags then
2658 APSR.N = result<31>;
2659 APSR.Z = IsZeroBit(result);
2660 APSR.C = carry;
2661 // APSR.V unchanged
2662#endif
2663
2664 return EmulateShiftReg(encoding, SRType_LSR);
2665}
2666
Johnny Cheneeab4852011-02-16 22:14:44 +00002667// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
2668// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2669// It can optionally update the condition flags based on the result.
2670bool
2671EmulateInstructionARM::EmulateRORImm (ARMEncoding encoding)
2672{
2673#if 0
2674 // ARM pseudo code...
2675 if ConditionPassed() then
2676 EncodingSpecificOperations();
2677 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2678 if d == 15 then // Can only occur for ARM encoding
2679 ALUWritePC(result); // setflags is always FALSE here
2680 else
2681 R[d] = result;
2682 if setflags then
2683 APSR.N = result<31>;
2684 APSR.Z = IsZeroBit(result);
2685 APSR.C = carry;
2686 // APSR.V unchanged
2687#endif
2688
2689 return EmulateShiftImm(encoding, SRType_ROR);
2690}
2691
2692// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
2693// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
2694// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
2695// flags based on the result.
2696bool
2697EmulateInstructionARM::EmulateRORReg (ARMEncoding encoding)
2698{
2699#if 0
2700 // ARM pseudo code...
2701 if ConditionPassed() then
2702 EncodingSpecificOperations();
2703 shift_n = UInt(R[m]<7:0>);
2704 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
2705 R[d] = result;
2706 if setflags then
2707 APSR.N = result<31>;
2708 APSR.Z = IsZeroBit(result);
2709 APSR.C = carry;
2710 // APSR.V unchanged
2711#endif
2712
2713 return EmulateShiftReg(encoding, SRType_ROR);
2714}
2715
2716// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
2717// with the carry flag shifted into bit [31].
2718//
2719// RRX can optionally update the condition flags based on the result.
2720// In that case, bit [0] is shifted into the carry flag.
2721bool
2722EmulateInstructionARM::EmulateRRX (ARMEncoding encoding)
2723{
2724#if 0
2725 // ARM pseudo code...
2726 if ConditionPassed() then
2727 EncodingSpecificOperations();
2728 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
2729 if d == 15 then // Can only occur for ARM encoding
2730 ALUWritePC(result); // setflags is always FALSE here
2731 else
2732 R[d] = result;
2733 if setflags then
2734 APSR.N = result<31>;
2735 APSR.Z = IsZeroBit(result);
2736 APSR.C = carry;
2737 // APSR.V unchanged
2738#endif
2739
2740 return EmulateShiftImm(encoding, SRType_RRX);
2741}
2742
Johnny Chen41a0a152011-02-16 01:27:54 +00002743bool
2744EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
2745{
2746 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
2747
Johnny Chen82f16aa2011-02-15 20:10:55 +00002748 bool success = false;
2749 const uint32_t opcode = OpcodeAsUnsigned (&success);
2750 if (!success)
2751 return false;
2752
2753 if (ConditionPassed())
2754 {
Johnny Chene7f89532011-02-15 23:22:46 +00002755 uint32_t Rd; // the destination register
2756 uint32_t Rm; // the first operand register
2757 uint32_t imm5; // encoding for the shift amount
Johnny Chen82f16aa2011-02-15 20:10:55 +00002758 uint32_t carry; // the carry bit after the shift operation
2759 bool setflags;
Johnny Cheneeab4852011-02-16 22:14:44 +00002760
2761 // Special case handling!
2762 // A8.6.139 ROR (immediate) -- Encoding T1
2763 if (shift_type == SRType_ROR && encoding == eEncodingT1)
2764 {
2765 // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
2766 // have the same decoding of bit fields as the other Thumb2 shift operations.
2767 encoding = eEncodingT2;
2768 }
2769
Johnny Chen82f16aa2011-02-15 20:10:55 +00002770 switch (encoding) {
2771 case eEncodingT1:
Johnny Cheneeab4852011-02-16 22:14:44 +00002772 // Due to the above special case handling!
2773 assert(shift_type != SRType_ROR);
2774
Johnny Chen82f16aa2011-02-15 20:10:55 +00002775 Rd = Bits32(opcode, 2, 0);
2776 Rm = Bits32(opcode, 5, 3);
2777 setflags = !InITBlock();
2778 imm5 = Bits32(opcode, 10, 6);
2779 break;
2780 case eEncodingT2:
Johnny Cheneeab4852011-02-16 22:14:44 +00002781 // A8.6.141 RRX
2782 assert(shift_type != SRType_RRX);
2783
Johnny Chen82f16aa2011-02-15 20:10:55 +00002784 Rd = Bits32(opcode, 11, 8);
2785 Rm = Bits32(opcode, 3, 0);
2786 setflags = BitIsSet(opcode, 20);
2787 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
2788 if (BadReg(Rd) || BadReg(Rm))
2789 return false;
2790 break;
2791 case eEncodingA1:
2792 Rd = Bits32(opcode, 15, 12);
2793 Rm = Bits32(opcode, 3, 0);
2794 setflags = BitIsSet(opcode, 20);
2795 imm5 = Bits32(opcode, 11, 7);
2796 break;
2797 default:
2798 return false;
2799 }
2800
Johnny Cheneeab4852011-02-16 22:14:44 +00002801 // A8.6.139 ROR (immediate)
2802 if (shift_type == SRType_ROR && imm5 == 0)
2803 shift_type = SRType_RRX;
2804
Johnny Chen82f16aa2011-02-15 20:10:55 +00002805 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002806 uint32_t value = ReadCoreReg (Rm, &success);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002807 if (!success)
2808 return false;
2809
Johnny Cheneeab4852011-02-16 22:14:44 +00002810 // Decode the shift amount if not RRX.
2811 uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
Johnny Chen82f16aa2011-02-15 20:10:55 +00002812
Johnny Chene97c0d52011-02-18 19:32:20 +00002813 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chen82f16aa2011-02-15 20:10:55 +00002814
2815 // The context specifies that an immediate is to be moved into Rd.
2816 EmulateInstruction::Context context;
2817 context.type = EmulateInstruction::eContextImmediate;
2818 context.SetNoArgs ();
Johnny Chen82f16aa2011-02-15 20:10:55 +00002819
Johnny Chen10530c22011-02-17 22:37:12 +00002820 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chenca67d1c2011-02-17 01:35:27 +00002821 return false;
Johnny Chen82f16aa2011-02-15 20:10:55 +00002822 }
2823 return true;
2824}
2825
Johnny Chene7f89532011-02-15 23:22:46 +00002826bool
Johnny Chen41a0a152011-02-16 01:27:54 +00002827EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
Johnny Chene7f89532011-02-15 23:22:46 +00002828{
Johnny Chen41a0a152011-02-16 01:27:54 +00002829 assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
Johnny Chene7f89532011-02-15 23:22:46 +00002830
2831 bool success = false;
2832 const uint32_t opcode = OpcodeAsUnsigned (&success);
2833 if (!success)
2834 return false;
2835
2836 if (ConditionPassed())
2837 {
2838 uint32_t Rd; // the destination register
2839 uint32_t Rn; // the first operand register
2840 uint32_t Rm; // the register whose bottom byte contains the amount to shift by
2841 uint32_t carry; // the carry bit after the shift operation
2842 bool setflags;
2843 switch (encoding) {
2844 case eEncodingT1:
2845 Rd = Bits32(opcode, 2, 0);
2846 Rn = Rd;
2847 Rm = Bits32(opcode, 5, 3);
2848 setflags = !InITBlock();
2849 break;
2850 case eEncodingT2:
2851 Rd = Bits32(opcode, 11, 8);
2852 Rn = Bits32(opcode, 19, 16);
2853 Rm = Bits32(opcode, 3, 0);
2854 setflags = BitIsSet(opcode, 20);
2855 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
2856 return false;
2857 break;
2858 case eEncodingA1:
2859 Rd = Bits32(opcode, 15, 12);
2860 Rn = Bits32(opcode, 3, 0);
2861 Rm = Bits32(opcode, 11, 8);
2862 setflags = BitIsSet(opcode, 20);
2863 if (Rd == 15 || Rn == 15 || Rm == 15)
2864 return false;
2865 break;
2866 default:
2867 return false;
2868 }
2869
2870 // Get the first operand.
Johnny Chene39f22d2011-02-19 01:36:13 +00002871 uint32_t value = ReadCoreReg (Rn, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002872 if (!success)
2873 return false;
2874 // Get the Rm register content.
Johnny Chene39f22d2011-02-19 01:36:13 +00002875 uint32_t val = ReadCoreReg (Rm, &success);
Johnny Chene7f89532011-02-15 23:22:46 +00002876 if (!success)
2877 return false;
2878
2879 // Get the shift amount.
2880 uint32_t amt = Bits32(val, 7, 0);
2881
Johnny Chene97c0d52011-02-18 19:32:20 +00002882 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry);
Johnny Chene7f89532011-02-15 23:22:46 +00002883
2884 // The context specifies that an immediate is to be moved into Rd.
2885 EmulateInstruction::Context context;
2886 context.type = EmulateInstruction::eContextImmediate;
2887 context.SetNoArgs ();
2888
Johnny Chen10530c22011-02-17 22:37:12 +00002889 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
Johnny Chene7f89532011-02-15 23:22:46 +00002890 return false;
Johnny Chene7f89532011-02-15 23:22:46 +00002891 }
2892 return true;
2893}
2894
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002895// LDM loads multiple registers from consecutive memory locations, using an
Caroline Tice713c2662011-02-11 17:59:55 +00002896// address from a base register. Optionally the address just above the highest of those locations
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002897// can be written back to the base register.
2898bool
2899EmulateInstructionARM::EmulateLDM (ARMEncoding encoding)
2900{
2901#if 0
2902 // ARM pseudo code...
2903 if ConditionPassed()
2904 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
2905 address = R[n];
2906
2907 for i = 0 to 14
2908 if registers<i> == '1' then
2909 R[i] = MemA[address, 4]; address = address + 4;
2910 if registers<15> == '1' then
2911 LoadWritePC (MemA[address, 4]);
2912
2913 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
2914 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
2915
2916#endif
2917
2918 bool success = false;
2919 const uint32_t opcode = OpcodeAsUnsigned (&success);
2920 if (!success)
2921 return false;
2922
2923 if (ConditionPassed())
2924 {
2925 uint32_t n;
2926 uint32_t registers = 0;
2927 bool wback;
2928 const uint32_t addr_byte_size = GetAddressByteSize();
2929 switch (encoding)
2930 {
2931 case eEncodingT1:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002932 // n = UInt(Rn); registers = ’00000000’:register_list; wback = (registers<n> == ’0’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002933 n = Bits32 (opcode, 10, 8);
2934 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002935 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002936 wback = BitIsClear (registers, n);
2937 // if BitCount(registers) < 1 then UNPREDICTABLE;
2938 if (BitCount(registers) < 1)
2939 return false;
2940 break;
2941 case eEncodingT2:
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002942 // if W == ’1’ && Rn == ’1101’ then SEE POP;
2943 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002944 n = Bits32 (opcode, 19, 16);
2945 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002946 registers = registers & 0xdfff; // Make sure bit 13 is zero.
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002947 wback = BitIsSet (opcode, 21);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002948
2949 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002950 if ((n == 15)
2951 || (BitCount (registers) < 2)
2952 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
2953 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002954
2955 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00002956 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002957 return false;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002958
2959 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002960 if (wback
2961 && BitIsSet (registers, n))
2962 return false;
2963 break;
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00002964
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002965 case eEncodingA1:
2966 n = Bits32 (opcode, 19, 16);
2967 registers = Bits32 (opcode, 15, 0);
2968 wback = BitIsSet (opcode, 21);
2969 if ((n == 15)
2970 || (BitCount (registers) < 1))
2971 return false;
2972 break;
2973 default:
2974 return false;
2975 }
2976
2977 int32_t offset = 0;
2978 const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
2979 if (!success)
2980 return false;
Caroline Tice85aab332011-02-08 23:56:10 +00002981
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002982 EmulateInstruction::Context context;
2983 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2984 Register dwarf_reg;
2985 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
2986 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002987
2988 for (int i = 0; i < 14; ++i)
2989 {
2990 if (BitIsSet (registers, i))
2991 {
Caroline Tice85aab332011-02-08 23:56:10 +00002992 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00002993 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002994 if (wback && (n == 13)) // Pop Instruction
2995 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2996
2997 // R[i] = MemA [address, 4]; address = address + 4;
Caroline Ticecc96eb52011-02-17 19:20:40 +00002998 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00002999 if (!success)
3000 return false;
3001
3002 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3003 return false;
3004
3005 offset += addr_byte_size;
3006 }
3007 }
3008
3009 if (BitIsSet (registers, 15))
3010 {
3011 //LoadWritePC (MemA [address, 4]);
Caroline Tice85aab332011-02-08 23:56:10 +00003012 context.type = EmulateInstruction::eContextRegisterPlusOffset;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003013 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003014 uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003015 if (!success)
3016 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003017 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003018 if (!LoadWritePC(context, data))
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003019 return false;
3020 }
3021
3022 if (wback && BitIsClear (registers, n))
3023 {
Caroline Ticefa172202011-02-11 22:49:54 +00003024 // R[n] = R[n] + 4 * BitCount (registers)
3025 int32_t offset = addr_byte_size * BitCount (registers);
3026 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003027 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003028
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003029 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
3030 return false;
3031 }
3032 if (wback && BitIsSet (registers, n))
3033 // R[n] bits(32) UNKNOWN;
Caroline Tice713c2662011-02-11 17:59:55 +00003034 return WriteBits32Unknown (n);
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003035 }
3036 return true;
3037}
Caroline Tice713c2662011-02-11 17:59:55 +00003038
3039// LDMDA loads multiple registers from consecutive memory locations using an address from a base registers.
3040// The consecutive memorty locations end at this address and the address just below the lowest of those locations
3041// can optionally be written back tot he base registers.
3042bool
3043EmulateInstructionARM::EmulateLDMDA (ARMEncoding encoding)
3044{
3045#if 0
3046 // ARM pseudo code...
3047 if ConditionPassed() then
3048 EncodingSpecificOperations();
3049 address = R[n] - 4*BitCount(registers) + 4;
Caroline Ticeb9f76c32011-02-08 22:24:38 +00003050
Caroline Tice713c2662011-02-11 17:59:55 +00003051 for i = 0 to 14
3052 if registers<i> == ’1’ then
3053 R[i] = MemA[address,4]; address = address + 4;
3054
3055 if registers<15> == ’1’ then
3056 LoadWritePC(MemA[address,4]);
3057
3058 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3059 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3060#endif
3061
3062 bool success = false;
3063 const uint32_t opcode = OpcodeAsUnsigned (&success);
3064 if (!success)
3065 return false;
3066
3067 if (ConditionPassed())
3068 {
3069 uint32_t n;
3070 uint32_t registers = 0;
3071 bool wback;
3072 const uint32_t addr_byte_size = GetAddressByteSize();
3073
3074 // EncodingSpecificOperations();
3075 switch (encoding)
3076 {
3077 case eEncodingA1:
3078 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3079 n = Bits32 (opcode, 19, 16);
3080 registers = Bits32 (opcode, 15, 0);
3081 wback = BitIsSet (opcode, 21);
3082
3083 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3084 if ((n == 15) || (BitCount (registers) < 1))
3085 return false;
3086
3087 break;
3088
3089 default:
3090 return false;
3091 }
3092 // address = R[n] - 4*BitCount(registers) + 4;
3093
3094 int32_t offset = 0;
3095 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3096
3097 if (!success)
3098 return false;
3099
3100 address = address - (addr_byte_size * BitCount (registers)) + addr_byte_size;
3101
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003102 EmulateInstruction::Context context;
3103 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3104 Register dwarf_reg;
3105 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3106 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice713c2662011-02-11 17:59:55 +00003107
3108 // for i = 0 to 14
3109 for (int i = 0; i < 14; ++i)
3110 {
3111 // if registers<i> == ’1’ then
3112 if (BitIsSet (registers, i))
3113 {
3114 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003115 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003116 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003117 if (!success)
3118 return false;
3119 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3120 return false;
3121 offset += addr_byte_size;
3122 }
3123 }
3124
3125 // if registers<15> == ’1’ then
3126 // LoadWritePC(MemA[address,4]);
3127 if (BitIsSet (registers, 15))
3128 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003129 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003130 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice713c2662011-02-11 17:59:55 +00003131 if (!success)
3132 return false;
Johnny Chen44c10f02011-02-11 19:37:03 +00003133 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003134 if (!LoadWritePC(context, data))
Caroline Tice713c2662011-02-11 17:59:55 +00003135 return false;
3136 }
3137
3138 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3139 if (wback && BitIsClear (registers, n))
3140 {
Caroline Tice713c2662011-02-11 17:59:55 +00003141 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3142 if (!success)
3143 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003144
3145 offset = (addr_byte_size * BitCount (registers)) * -1;
3146 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003147 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003148 addr = addr + offset;
Caroline Tice713c2662011-02-11 17:59:55 +00003149 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3150 return false;
3151 }
3152
3153 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3154 if (wback && BitIsSet (registers, n))
3155 return WriteBits32Unknown (n);
3156 }
3157 return true;
3158}
3159
3160// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The
3161// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can
3162// be optionally written back to the base register.
Caroline Tice0b29e242011-02-08 23:16:02 +00003163bool
3164EmulateInstructionARM::EmulateLDMDB (ARMEncoding encoding)
3165{
3166#if 0
3167 // ARM pseudo code...
3168 if ConditionPassed() then
3169 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3170 address = R[n] - 4*BitCount(registers);
3171
3172 for i = 0 to 14
3173 if registers<i> == ’1’ then
3174 R[i] = MemA[address,4]; address = address + 4;
3175 if registers<15> == ’1’ then
3176 LoadWritePC(MemA[address,4]);
3177
3178 if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3179 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3180#endif
3181
3182 bool success = false;
3183 const uint32_t opcode = OpcodeAsUnsigned (&success);
3184 if (!success)
3185 return false;
3186
3187 if (ConditionPassed())
3188 {
3189 uint32_t n;
3190 uint32_t registers = 0;
3191 bool wback;
3192 const uint32_t addr_byte_size = GetAddressByteSize();
3193 switch (encoding)
3194 {
3195 case eEncodingT1:
3196 // n = UInt(Rn); registers = P:M:’0’:register_list; wback = (W == ’1’);
3197 n = Bits32 (opcode, 19, 16);
3198 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003199 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
Caroline Tice0b29e242011-02-08 23:16:02 +00003200 wback = BitIsSet (opcode, 21);
3201
3202 // if n == 15 || BitCount(registers) < 2 || (P == ’1’ && M == ’1’) then UNPREDICTABLE;
3203 if ((n == 15)
3204 || (BitCount (registers) < 2)
3205 || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
3206 return false;
3207
3208 // if registers<15> == ’1’ && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
Johnny Chen098ae2d2011-02-12 00:50:05 +00003209 if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
Caroline Tice0b29e242011-02-08 23:16:02 +00003210 return false;
3211
3212 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3213 if (wback && BitIsSet (registers, n))
3214 return false;
3215
3216 break;
3217
3218 case eEncodingA1:
3219 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3220 n = Bits32 (opcode, 19, 16);
3221 registers = Bits32 (opcode, 15, 0);
3222 wback = BitIsSet (opcode, 21);
3223
3224 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3225 if ((n == 15) || (BitCount (registers) < 1))
3226 return false;
3227
3228 break;
3229
3230 default:
3231 return false;
3232 }
3233
Caroline Tice713c2662011-02-11 17:59:55 +00003234 // address = R[n] - 4*BitCount(registers);
3235
Caroline Tice0b29e242011-02-08 23:16:02 +00003236 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003237 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3238
3239 if (!success)
3240 return false;
3241
3242 address = address - (addr_byte_size * BitCount (registers));
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003243 EmulateInstruction::Context context;
3244 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3245 Register dwarf_reg;
3246 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3247 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice0b29e242011-02-08 23:16:02 +00003248
3249 for (int i = 0; i < 14; ++i)
3250 {
3251 if (BitIsSet (registers, i))
3252 {
3253 // R[i] = MemA[address,4]; address = address + 4;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003254 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003255 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003256 if (!success)
3257 return false;
3258
3259 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3260 return false;
3261
3262 offset += addr_byte_size;
3263 }
3264 }
3265
3266 // if registers<15> == ’1’ then
3267 // LoadWritePC(MemA[address,4]);
3268 if (BitIsSet (registers, 15))
3269 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003270 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003271 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice0b29e242011-02-08 23:16:02 +00003272 if (!success)
3273 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003274 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003275 if (!LoadWritePC(context, data))
Caroline Tice0b29e242011-02-08 23:16:02 +00003276 return false;
3277 }
3278
3279 // if wback && registers<n> == ’0’ then R[n] = R[n] - 4*BitCount(registers);
3280 if (wback && BitIsClear (registers, n))
3281 {
Caroline Tice0b29e242011-02-08 23:16:02 +00003282 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3283 if (!success)
3284 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003285
3286 offset = (addr_byte_size * BitCount (registers)) * -1;
3287 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003288 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003289 addr = addr + offset;
Caroline Tice0b29e242011-02-08 23:16:02 +00003290 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3291 return false;
3292 }
3293
3294 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3295 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003296 return WriteBits32Unknown (n);
Caroline Tice0b29e242011-02-08 23:16:02 +00003297 }
3298 return true;
3299}
Caroline Tice85aab332011-02-08 23:56:10 +00003300
Caroline Tice713c2662011-02-11 17:59:55 +00003301// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The
3302// consecutive memory locations start just above this address, and thea ddress of the last of those locations can
3303// optinoally be written back to the base register.
Caroline Tice85aab332011-02-08 23:56:10 +00003304bool
3305EmulateInstructionARM::EmulateLDMIB (ARMEncoding encoding)
3306{
3307#if 0
3308 if ConditionPassed() then
3309 EncodingSpecificOperations();
3310 address = R[n] + 4;
3311
3312 for i = 0 to 14
3313 if registers<i> == ’1’ then
3314 R[i] = MemA[address,4]; address = address + 4;
3315 if registers<15> == ’1’ then
3316 LoadWritePC(MemA[address,4]);
3317
3318 if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3319 if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN;
3320#endif
3321
3322 bool success = false;
3323 const uint32_t opcode = OpcodeAsUnsigned (&success);
3324 if (!success)
3325 return false;
3326
3327 if (ConditionPassed())
3328 {
3329 uint32_t n;
3330 uint32_t registers = 0;
3331 bool wback;
3332 const uint32_t addr_byte_size = GetAddressByteSize();
3333 switch (encoding)
3334 {
3335 case eEncodingA1:
3336 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3337 n = Bits32 (opcode, 19, 16);
3338 registers = Bits32 (opcode, 15, 0);
3339 wback = BitIsSet (opcode, 21);
3340
3341 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3342 if ((n == 15) || (BitCount (registers) < 1))
3343 return false;
3344
3345 break;
3346 default:
3347 return false;
3348 }
3349 // address = R[n] + 4;
3350
3351 int32_t offset = 0;
Caroline Tice713c2662011-02-11 17:59:55 +00003352 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3353
3354 if (!success)
3355 return false;
3356
3357 address = address + addr_byte_size;
Caroline Tice85aab332011-02-08 23:56:10 +00003358
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003359 EmulateInstruction::Context context;
3360 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3361 Register dwarf_reg;
3362 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3363 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Tice85aab332011-02-08 23:56:10 +00003364
3365 for (int i = 0; i < 14; ++i)
3366 {
3367 if (BitIsSet (registers, i))
3368 {
3369 // R[i] = MemA[address,4]; address = address + 4;
3370
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003371 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003372 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003373 if (!success)
3374 return false;
3375
3376 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
3377 return false;
3378
3379 offset += addr_byte_size;
3380 }
3381 }
3382
3383 // if registers<15> == ’1’ then
3384 // LoadWritePC(MemA[address,4]);
3385 if (BitIsSet (registers, 15))
3386 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003387 context.SetRegisterPlusOffset (dwarf_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003388 uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
Caroline Tice85aab332011-02-08 23:56:10 +00003389 if (!success)
3390 return false;
Johnny Chene62b50d2011-02-09 22:02:17 +00003391 // In ARMv5T and above, this is an interworking branch.
Johnny Chen668b4512011-02-15 21:08:58 +00003392 if (!LoadWritePC(context, data))
Caroline Tice85aab332011-02-08 23:56:10 +00003393 return false;
3394 }
3395
3396 // if wback && registers<n> == ’0’ then R[n] = R[n] + 4*BitCount(registers);
3397 if (wback && BitIsClear (registers, n))
3398 {
Caroline Tice85aab332011-02-08 23:56:10 +00003399 addr_t addr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3400 if (!success)
3401 return false;
Caroline Ticefa172202011-02-11 22:49:54 +00003402
3403 offset = addr_byte_size * BitCount (registers);
3404 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003405 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003406 addr = addr + offset;
Caroline Tice85aab332011-02-08 23:56:10 +00003407 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
3408 return false;
3409 }
3410
3411 // if wback && registers<n> == ’1’ then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3412 if (wback && BitIsSet (registers, n))
Caroline Tice713c2662011-02-11 17:59:55 +00003413 return WriteBits32Unknown (n);
Caroline Tice85aab332011-02-08 23:56:10 +00003414 }
3415 return true;
3416}
Caroline Tice0b29e242011-02-08 23:16:02 +00003417
Johnny Chenef21b592011-02-10 01:52:38 +00003418// Load Register (immediate) calculates an address from a base register value and
3419// an immediate offset, loads a word from memory, and writes to a register.
3420// LDR (immediate, Thumb)
3421bool
3422EmulateInstructionARM::EmulateLDRRtRnImm (ARMEncoding encoding)
3423{
3424#if 0
3425 // ARM pseudo code...
3426 if (ConditionPassed())
3427 {
3428 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
3429 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
3430 address = if index then offset_addr else R[n];
3431 data = MemU[address,4];
3432 if wback then R[n] = offset_addr;
3433 if t == 15 then
3434 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
3435 elsif UnalignedSupport() || address<1:0> = '00' then
3436 R[t] = data;
3437 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
3438 }
3439#endif
3440
3441 bool success = false;
3442 const uint32_t opcode = OpcodeAsUnsigned (&success);
3443 if (!success)
3444 return false;
3445
3446 if (ConditionPassed())
3447 {
3448 uint32_t Rt; // the destination register
3449 uint32_t Rn; // the base register
3450 uint32_t imm32; // the immediate offset used to form the address
3451 addr_t offset_addr; // the offset address
3452 addr_t address; // the calculated address
3453 uint32_t data; // the literal data value from memory load
3454 bool add, index, wback;
3455 switch (encoding) {
3456 case eEncodingT1:
3457 Rt = Bits32(opcode, 5, 3);
3458 Rn = Bits32(opcode, 2, 0);
3459 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
3460 // index = TRUE; add = TRUE; wback = FALSE
3461 add = true;
3462 index = true;
3463 wback = false;
3464 break;
3465 default:
3466 return false;
3467 }
3468 uint32_t base = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
3469 if (!success)
3470 return false;
3471 if (add)
3472 offset_addr = base + imm32;
3473 else
3474 offset_addr = base - imm32;
3475
3476 address = (index ? offset_addr : base);
3477
3478 if (wback)
3479 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003480 EmulateInstruction::Context ctx;
3481 ctx.type = EmulateInstruction::eContextRegisterPlusOffset;
3482 Register dwarf_reg;
3483 dwarf_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + Rn);
3484 ctx.SetRegisterPlusOffset (dwarf_reg, (int32_t) (offset_addr - base));
3485
Johnny Chenef21b592011-02-10 01:52:38 +00003486 if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
3487 return false;
3488 }
3489
3490 // Prepare to write to the Rt register.
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003491 EmulateInstruction::Context context;
3492 context.type = EmulateInstruction::eContextImmediate;
3493 context.SetNoArgs ();
Johnny Chenef21b592011-02-10 01:52:38 +00003494
3495 // Read memory from the address.
Caroline Ticecc96eb52011-02-17 19:20:40 +00003496 data = MemURead(context, address, 4, 0, &success);
Johnny Chenef21b592011-02-10 01:52:38 +00003497 if (!success)
3498 return false;
Johnny Chenef21b592011-02-10 01:52:38 +00003499
3500 if (Rt == 15)
3501 {
3502 if (Bits32(address, 1, 0) == 0)
3503 {
Johnny Chen668b4512011-02-15 21:08:58 +00003504 if (!LoadWritePC(context, data))
Johnny Chenef21b592011-02-10 01:52:38 +00003505 return false;
3506 }
3507 else
3508 return false;
3509 }
3510 else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
3511 {
3512 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
3513 return false;
3514 }
3515 else
3516 return false;
3517 }
3518 return true;
3519}
3520
Caroline Ticeaf556562011-02-15 18:42:15 +00003521// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address
3522// from a base register. The consecutive memory locations start at this address, and teh address just above the last
3523// of those locations can optionally be written back to the base register.
Caroline Ticefa172202011-02-11 22:49:54 +00003524bool
3525EmulateInstructionARM::EmulateSTM (ARMEncoding encoding)
3526{
3527#if 0
3528 if ConditionPassed() then
3529 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3530 address = R[n];
3531
3532 for i = 0 to 14
3533 if registers<i> == ’1’ then
3534 if i == n && wback && i != LowestSetBit(registers) then
3535 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3536 else
3537 MemA[address,4] = R[i];
3538 address = address + 4;
3539
3540 if registers<15> == ’1’ then // Only possible for encoding A1
3541 MemA[address,4] = PCStoreValue();
3542 if wback then R[n] = R[n] + 4*BitCount(registers);
3543#endif
3544
3545 bool success = false;
3546 const uint32_t opcode = OpcodeAsUnsigned (&success);
3547 if (!success)
3548 return false;
3549
3550 if (ConditionPassed ())
3551 {
3552 uint32_t n;
3553 uint32_t registers = 0;
3554 bool wback;
3555 const uint32_t addr_byte_size = GetAddressByteSize();
3556
3557 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3558 switch (encoding)
3559 {
3560 case eEncodingT1:
3561 // n = UInt(Rn); registers = ’00000000’:register_list; wback = TRUE;
3562 n = Bits32 (opcode, 10, 8);
3563 registers = Bits32 (opcode, 7, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003564 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003565 wback = true;
3566
3567 // if BitCount(registers) < 1 then UNPREDICTABLE;
3568 if (BitCount (registers) < 1)
3569 return false;
3570
3571 break;
3572
3573 case eEncodingT2:
3574 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3575 n = Bits32 (opcode, 19, 16);
3576 registers = Bits32 (opcode, 15, 0);
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003577 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
Caroline Ticefa172202011-02-11 22:49:54 +00003578 wback = BitIsSet (opcode, 21);
3579
3580 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3581 if ((n == 15) || (BitCount (registers) < 2))
3582 return false;
3583
3584 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3585 if (wback && BitIsSet (registers, n))
3586 return false;
3587
3588 break;
3589
3590 case eEncodingA1:
3591 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3592 n = Bits32 (opcode, 19, 16);
3593 registers = Bits32 (opcode, 15, 0);
3594 wback = BitIsSet (opcode, 21);
3595
3596 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3597 if ((n == 15) || (BitCount (registers) < 1))
3598 return false;
3599
3600 break;
3601
3602 default:
3603 return false;
3604 }
3605
3606 // address = R[n];
3607 int32_t offset = 0;
3608 const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3609 if (!success)
3610 return false;
3611
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003612 EmulateInstruction::Context context;
3613 context.type = EmulateInstruction::eContextRegisterStore;
3614 Register base_reg;
3615 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
Caroline Ticefa172202011-02-11 22:49:54 +00003616
3617 // for i = 0 to 14
3618 for (int i = 0; i < 14; ++i)
3619 {
3620 int lowest_set_bit = 14;
3621 // if registers<i> == ’1’ then
3622 if (BitIsSet (registers, i))
3623 {
3624 if (i < lowest_set_bit)
3625 lowest_set_bit = i;
3626 // if i == n && wback && i != LowestSetBit(registers) then
3627 if ((i == n) && wback && (i != lowest_set_bit))
3628 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
3629 WriteBits32UnknownToMemory (address + offset);
3630 else
3631 {
3632 // MemA[address,4] = R[i];
3633 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3634 if (!success)
3635 return false;
3636
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003637 Register data_reg;
3638 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3639 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003640 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003641 return false;
3642 }
3643
3644 // address = address + 4;
3645 offset += addr_byte_size;
3646 }
3647 }
3648
3649 // if registers<15> == ’1’ then // Only possible for encoding A1
3650 // MemA[address,4] = PCStoreValue();
3651 if (BitIsSet (registers, 15))
3652 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003653 Register pc_reg;
3654 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3655 context.SetRegisterPlusOffset (pc_reg, 8);
Caroline Ticefa172202011-02-11 22:49:54 +00003656 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3657 if (!success)
3658 return false;
3659
Caroline Ticecc96eb52011-02-17 19:20:40 +00003660 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticefa172202011-02-11 22:49:54 +00003661 return false;
3662 }
3663
3664 // if wback then R[n] = R[n] + 4*BitCount(registers);
3665 if (wback)
3666 {
3667 offset = addr_byte_size * BitCount (registers);
3668 context.type = EmulateInstruction::eContextAdjustBaseRegister;
Caroline Tice9bfe7f22011-02-14 23:03:21 +00003669 context.SetImmediateSigned (offset);
Caroline Ticefa172202011-02-11 22:49:54 +00003670 addr_t data = address + offset;
3671 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3672 return false;
3673 }
3674 }
3675 return true;
3676}
3677
Caroline Ticeaf556562011-02-15 18:42:15 +00003678// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
3679// from a base register. The consecutive memory locations end at this address, and the address just below the lowest
3680// of those locations can optionally be written back to the base register.
Caroline Tice1511f502011-02-15 00:19:42 +00003681bool
3682EmulateInstructionARM::EmulateSTMDA (ARMEncoding encoding)
3683{
3684#if 0
3685 if ConditionPassed() then
3686 EncodingSpecificOperations();
3687 address = R[n] - 4*BitCount(registers) + 4;
3688
3689 for i = 0 to 14
3690 if registers<i> == ’1’ then
3691 if i == n && wback && i != LowestSetBit(registers) then
3692 MemA[address,4] = bits(32) UNKNOWN;
3693 else
3694 MemA[address,4] = R[i];
3695 address = address + 4;
3696
3697 if registers<15> == ’1’ then
3698 MemA[address,4] = PCStoreValue();
3699
3700 if wback then R[n] = R[n] - 4*BitCount(registers);
3701#endif
3702
3703 bool success = false;
3704 const uint32_t opcode = OpcodeAsUnsigned (&success);
3705 if (!success)
3706 return false;
3707
3708 if (ConditionPassed ())
3709 {
3710 uint32_t n;
3711 uint32_t registers = 0;
3712 bool wback;
3713 const uint32_t addr_byte_size = GetAddressByteSize();
3714
3715 // EncodingSpecificOperations();
3716 switch (encoding)
3717 {
3718 case eEncodingA1:
3719 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3720 n = Bits32 (opcode, 19, 16);
3721 registers = Bits32 (opcode, 15, 0);
3722 wback = BitIsSet (opcode, 21);
3723
3724 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3725 if ((n == 15) || (BitCount (registers) < 1))
3726 return false;
3727 break;
3728 default:
3729 return false;
3730 }
3731
3732 // address = R[n] - 4*BitCount(registers) + 4;
3733 int32_t offset = 0;
3734 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3735 if (!success)
3736 return false;
3737
3738 address = address - (addr_byte_size * BitCount (registers)) + 4;
3739
3740 EmulateInstruction::Context context;
3741 context.type = EmulateInstruction::eContextRegisterStore;
3742 Register base_reg;
3743 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3744
3745 // for i = 0 to 14
3746 for (int i = 0; i < 14; ++i)
3747 {
3748 int lowest_bit_set = 14;
3749 // if registers<i> == ’1’ then
3750 if (BitIsSet (registers, i))
3751 {
3752 if (i < lowest_bit_set)
3753 lowest_bit_set = i;
3754 //if i == n && wback && i != LowestSetBit(registers) then
3755 if ((i == n) && wback && (i != lowest_bit_set))
3756 // MemA[address,4] = bits(32) UNKNOWN;
3757 WriteBits32UnknownToMemory (address + offset);
3758 else
3759 {
3760 // MemA[address,4] = R[i];
3761 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3762 if (!success)
3763 return false;
3764
3765 Register data_reg;
3766 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3767 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003768 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003769 return false;
3770 }
3771
3772 // address = address + 4;
3773 offset += addr_byte_size;
3774 }
3775 }
3776
3777 // if registers<15> == ’1’ then
3778 // MemA[address,4] = PCStoreValue();
3779 if (BitIsSet (registers, 15))
3780 {
3781 Register pc_reg;
3782 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3783 context.SetRegisterPlusOffset (pc_reg, 8);
3784 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3785 if (!success)
3786 return false;
3787
Caroline Ticecc96eb52011-02-17 19:20:40 +00003788 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Tice1511f502011-02-15 00:19:42 +00003789 return false;
3790 }
3791
3792 // if wback then R[n] = R[n] - 4*BitCount(registers);
3793 if (wback)
3794 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003795 offset = (addr_byte_size * BitCount (registers)) * -1;
Caroline Tice1511f502011-02-15 00:19:42 +00003796 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3797 context.SetImmediateSigned (offset);
3798 addr_t data = address + offset;
3799 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3800 return false;
3801 }
3802 }
3803 return true;
3804}
3805
Caroline Ticeaf556562011-02-15 18:42:15 +00003806// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
3807// from a base register. The consecutive memory locations end just below this address, and the address of the first of
3808// those locations can optionally be written back to the base register.
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003809bool
3810EmulateInstructionARM::EmulateSTMDB (ARMEncoding encoding)
3811{
3812#if 0
3813 if ConditionPassed() then
3814 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3815 address = R[n] - 4*BitCount(registers);
3816
3817 for i = 0 to 14
3818 if registers<i> == ’1’ then
3819 if i == n && wback && i != LowestSetBit(registers) then
3820 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3821 else
3822 MemA[address,4] = R[i];
3823 address = address + 4;
3824
3825 if registers<15> == ’1’ then // Only possible for encoding A1
3826 MemA[address,4] = PCStoreValue();
3827
3828 if wback then R[n] = R[n] - 4*BitCount(registers);
3829#endif
3830
3831
3832 bool success = false;
3833 const uint32_t opcode = OpcodeAsUnsigned (&success);
3834 if (!success)
3835 return false;
3836
3837 if (ConditionPassed ())
3838 {
3839 uint32_t n;
3840 uint32_t registers = 0;
3841 bool wback;
3842 const uint32_t addr_byte_size = GetAddressByteSize();
3843
3844 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
3845 switch (encoding)
3846 {
3847 case eEncodingT1:
3848 // if W == ’1’ && Rn == ’1101’ then SEE PUSH;
3849 if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
3850 {
3851 // See PUSH
3852 }
3853 // n = UInt(Rn); registers = ’0’:M:’0’:register_list; wback = (W == ’1’);
3854 n = Bits32 (opcode, 19, 16);
3855 registers = Bits32 (opcode, 15, 0);
3856 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
3857 wback = BitIsSet (opcode, 21);
3858 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
3859 if ((n == 15) || BitCount (registers) < 2)
3860 return false;
3861 // if wback && registers<n> == ’1’ then UNPREDICTABLE;
3862 if (wback && BitIsSet (registers, n))
3863 return false;
3864 break;
3865
3866 case eEncodingA1:
3867 // if W == ’1’ && Rn == ’1101’ && BitCount(register_list) >= 2 then SEE PUSH;
3868 if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
3869 {
3870 // See Push
3871 }
3872 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
3873 n = Bits32 (opcode, 19, 16);
3874 registers = Bits32 (opcode, 15, 0);
3875 wback = BitIsSet (opcode, 21);
3876 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
3877 if ((n == 15) || BitCount (registers) < 1)
3878 return false;
3879 break;
3880
3881 default:
3882 return false;
3883 }
3884
3885 // address = R[n] - 4*BitCount(registers);
3886
3887 int32_t offset = 0;
3888 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3889 if (!success)
3890 return false;
3891
3892 address = address - (addr_byte_size * BitCount (registers));
3893
3894 EmulateInstruction::Context context;
3895 context.type = EmulateInstruction::eContextRegisterStore;
3896 Register base_reg;
3897 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
3898
3899 // for i = 0 to 14
3900 for (int i = 0; i < 14; ++i)
3901 {
3902 uint32_t lowest_set_bit = 14;
3903 // if registers<i> == ’1’ then
3904 if (BitIsSet (registers, i))
3905 {
3906 if (i < lowest_set_bit)
3907 lowest_set_bit = i;
3908 // if i == n && wback && i != LowestSetBit(registers) then
3909 if ((i == n) && wback && (i != lowest_set_bit))
3910 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
3911 WriteBits32UnknownToMemory (address + offset);
3912 else
3913 {
3914 // MemA[address,4] = R[i];
3915 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
3916 if (!success)
3917 return false;
3918
3919 Register data_reg;
3920 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
3921 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00003922 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003923 return false;
3924 }
3925
3926 // address = address + 4;
3927 offset += addr_byte_size;
3928 }
3929 }
3930
3931 // if registers<15> == ’1’ then // Only possible for encoding A1
3932 // MemA[address,4] = PCStoreValue();
3933 if (BitIsSet (registers, 15))
3934 {
3935 Register pc_reg;
3936 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
3937 context.SetRegisterPlusOffset (pc_reg, 8);
3938 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
3939 if (!success)
3940 return false;
3941
Caroline Ticecc96eb52011-02-17 19:20:40 +00003942 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00003943 return false;
3944 }
3945
3946 // if wback then R[n] = R[n] - 4*BitCount(registers);
3947 if (wback)
3948 {
Caroline Ticeaf556562011-02-15 18:42:15 +00003949 offset = (addr_byte_size * BitCount (registers)) * -1;
3950 context.type = EmulateInstruction::eContextAdjustBaseRegister;
3951 context.SetImmediateSigned (offset);
3952 addr_t data = address + offset;
3953 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
3954 return false;
3955 }
3956 }
3957 return true;
3958}
3959
3960// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
3961// from a base register. The consecutive memory locations start just above this address, and the address of the last
3962// of those locations can optionally be written back to the base register.
3963bool
3964EmulateInstructionARM::EmulateSTMIB (ARMEncoding encoding)
3965{
3966#if 0
3967 if ConditionPassed() then
3968 EncodingSpecificOperations();
3969 address = R[n] + 4;
3970
3971 for i = 0 to 14
3972 if registers<i> == ’1’ then
3973 if i == n && wback && i != LowestSetBit(registers) then
3974 MemA[address,4] = bits(32) UNKNOWN;
3975 else
3976 MemA[address,4] = R[i];
3977 address = address + 4;
3978
3979 if registers<15> == ’1’ then
3980 MemA[address,4] = PCStoreValue();
3981
3982 if wback then R[n] = R[n] + 4*BitCount(registers);
3983#endif
3984
3985 bool success = false;
3986 const uint32_t opcode = OpcodeAsUnsigned (&success);
3987 if (!success)
3988 return false;
3989
3990 if (ConditionPassed())
3991 {
3992 uint32_t n;
3993 uint32_t registers = 0;
3994 bool wback;
3995 const uint32_t addr_byte_size = GetAddressByteSize();
3996
3997 // EncodingSpecificOperations();
3998 switch (encoding)
3999 {
4000 case eEncodingA1:
4001 // n = UInt(Rn); registers = register_list; wback = (W == ’1’);
4002 n = Bits32 (opcode, 19, 16);
4003 registers = Bits32 (opcode, 15, 0);
4004 wback = BitIsSet (opcode, 21);
4005
4006 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4007 if ((n == 15) && (BitCount (registers) < 1))
4008 return false;
4009 break;
4010 default:
4011 return false;
4012 }
4013 // address = R[n] + 4;
4014
4015 int32_t offset = 0;
4016 addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4017 if (!success)
4018 return false;
4019
4020 address = address + addr_byte_size;
4021
4022 EmulateInstruction::Context context;
4023 context.type = EmulateInstruction::eContextRegisterStore;
4024 Register base_reg;
4025 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4026
4027 uint32_t lowest_set_bit = 14;
4028 // for i = 0 to 14
4029 for (int i = 0; i < 14; ++i)
4030 {
4031 // if registers<i> == ’1’ then
4032 if (BitIsSet (registers, i))
4033 {
4034 if (i < lowest_set_bit)
4035 lowest_set_bit = i;
4036 // if i == n && wback && i != LowestSetBit(registers) then
4037 if ((i == n) && wback && (i != lowest_set_bit))
4038 // MemA[address,4] = bits(32) UNKNOWN;
4039 WriteBits32UnknownToMemory (address + offset);
4040 // else
4041 else
4042 {
4043 // MemA[address,4] = R[i];
4044 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
4045 if (!success)
4046 return false;
4047
4048 Register data_reg;
4049 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + i);
4050 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004051 if (!MemAWrite (context, address + offset, data, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004052 return false;
4053 }
4054
4055 // address = address + 4;
4056 offset += addr_byte_size;
4057 }
4058 }
4059
4060 // if registers<15> == ’1’ then
4061 // MemA[address,4] = PCStoreValue();
4062 if (BitIsSet (registers, 15))
4063 {
4064 Register pc_reg;
4065 pc_reg.SetRegister (eRegisterKindDWARF, dwarf_pc);
4066 context.SetRegisterPlusOffset (pc_reg, 8);
4067 const uint32_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4068 if (!success)
4069 return false;
4070
Caroline Ticecc96eb52011-02-17 19:20:40 +00004071 if (!MemAWrite (context, address + offset, pc + 8, addr_byte_size))
Caroline Ticeaf556562011-02-15 18:42:15 +00004072 return false;
4073 }
4074
4075 // if wback then R[n] = R[n] + 4*BitCount(registers);
4076 if (wback)
4077 {
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004078 offset = addr_byte_size * BitCount (registers);
4079 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4080 context.SetImmediateSigned (offset);
4081 addr_t data = address + offset;
4082 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
4083 return false;
4084 }
4085 }
4086 return true;
4087}
Caroline Tice7fac8572011-02-15 22:53:54 +00004088
4089// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
4090// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing.
4091bool
4092EmulateInstructionARM::EmulateSTRThumb (ARMEncoding encoding)
4093{
4094#if 0
4095 if ConditionPassed() then
4096 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4097 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4098 address = if index then offset_addr else R[n];
4099 if UnalignedSupport() || address<1:0> == ’00’ then
4100 MemU[address,4] = R[t];
4101 else // Can only occur before ARMv7
4102 MemU[address,4] = bits(32) UNKNOWN;
4103 if wback then R[n] = offset_addr;
4104#endif
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00004105
Caroline Tice7fac8572011-02-15 22:53:54 +00004106 bool success = false;
4107 const uint32_t opcode = OpcodeAsUnsigned (&success);
4108 if (!success)
4109 return false;
4110
4111 if (ConditionPassed())
4112 {
4113 const uint32_t addr_byte_size = GetAddressByteSize();
4114
4115 uint32_t t;
4116 uint32_t n;
4117 uint32_t imm32;
4118 bool index;
4119 bool add;
4120 bool wback;
4121 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4122 switch (encoding)
4123 {
4124 case eEncodingT1:
4125 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’00’, 32);
4126 t = Bits32 (opcode, 2, 0);
4127 n = Bits32 (opcode, 5, 3);
4128 imm32 = Bits32 (opcode, 10, 6) << 2;
4129
4130 // index = TRUE; add = TRUE; wback = FALSE;
4131 index = true;
4132 add = false;
4133 wback = false;
4134 break;
4135
4136 case eEncodingT2:
4137 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:’00’, 32);
4138 t = Bits32 (opcode, 10, 8);
4139 n = 13;
4140 imm32 = Bits32 (opcode, 7, 0) << 2;
4141
4142 // index = TRUE; add = TRUE; wback = FALSE;
4143 index = true;
4144 add = true;
4145 wback = false;
4146 break;
4147
4148 case eEncodingT3:
4149 // if Rn == ’1111’ then UNDEFINED;
4150 if (Bits32 (opcode, 19, 16) == 15)
4151 return false;
4152
4153 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4154 t = Bits32 (opcode, 15, 12);
4155 n = Bits32 (opcode, 19, 16);
4156 imm32 = Bits32 (opcode, 11, 0);
4157
4158 // index = TRUE; add = TRUE; wback = FALSE;
4159 index = true;
4160 add = true;
4161 wback = false;
4162
4163 // if t == 15 then UNPREDICTABLE;
4164 if (t == 15)
4165 return false;
4166 break;
4167
4168 case eEncodingT4:
4169 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRT;
4170 // if Rn == ’1101’ && P == ’1’ && U == ’0’ && W == ’1’ && imm8 == ’00000100’ then SEE PUSH;
4171 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4172 if ((Bits32 (opcode, 19, 16) == 15)
4173 || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
4174 return false;
4175
4176 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4177 t = Bits32 (opcode, 15, 12);
4178 n = Bits32 (opcode, 19, 16);
4179 imm32 = Bits32 (opcode, 7, 0);
4180
4181 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4182 index = BitIsSet (opcode, 10);
4183 add = BitIsSet (opcode, 9);
4184 wback = BitIsSet (opcode, 8);
4185
4186 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
4187 if ((t == 15) || (wback && (n == t)))
4188 return false;
4189 break;
4190
4191 default:
4192 return false;
4193 }
4194
4195 addr_t offset_addr;
4196 addr_t address;
4197
4198 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4199 uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4200 if (!success)
4201 return false;
4202
4203 if (add)
4204 offset_addr = base_address + imm32;
4205 else
4206 offset_addr = base_address - imm32;
4207
4208 // address = if index then offset_addr else R[n];
4209 if (index)
4210 address = offset_addr;
4211 else
4212 address = base_address;
4213
4214 EmulateInstruction::Context context;
4215 context.type = eContextRegisterStore;
4216 Register base_reg;
4217 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4218
4219 // if UnalignedSupport() || address<1:0> == ’00’ then
4220 if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
4221 {
4222 // MemU[address,4] = R[t];
4223 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4224 if (!success)
4225 return false;
4226
4227 Register data_reg;
4228 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4229 int32_t offset = address - base_address;
4230 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004231 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice7fac8572011-02-15 22:53:54 +00004232 return false;
4233 }
4234 else
4235 {
4236 // MemU[address,4] = bits(32) UNKNOWN;
4237 WriteBits32UnknownToMemory (address);
4238 }
4239
4240 // if wback then R[n] = offset_addr;
4241 if (wback)
4242 {
4243 context.type = eContextRegisterLoad;
4244 context.SetAddress (offset_addr);
4245 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4246 return false;
4247 }
4248 }
4249 return true;
4250}
Caroline Ticeaf556562011-02-15 18:42:15 +00004251
Caroline Tice3fd63e92011-02-16 00:33:43 +00004252// STR (Store Register) calculates an address from a base register value and an offset register value, stores a
4253// word from a register to memory. The offset register value can optionally be shifted.
4254bool
4255EmulateInstructionARM::EmulateSTRRegister (ARMEncoding encoding)
4256{
4257#if 0
4258 if ConditionPassed() then
4259 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4260 offset = Shift(R[m], shift_t, shift_n, APSR.C);
4261 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4262 address = if index then offset_addr else R[n];
4263 if t == 15 then // Only possible for encoding A1
4264 data = PCStoreValue();
4265 else
4266 data = R[t];
4267 if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4268 MemU[address,4] = data;
4269 else // Can only occur before ARMv7
4270 MemU[address,4] = bits(32) UNKNOWN;
4271 if wback then R[n] = offset_addr;
4272#endif
4273
4274 bool success = false;
4275 const uint32_t opcode = OpcodeAsUnsigned (&success);
4276 if (!success)
4277 return false;
4278
4279 if (ConditionPassed())
4280 {
4281 const uint32_t addr_byte_size = GetAddressByteSize();
4282
4283 uint32_t t;
4284 uint32_t n;
4285 uint32_t m;
4286 ARM_ShifterType shift_t;
4287 uint32_t shift_n;
4288 bool index;
4289 bool add;
4290 bool wback;
4291
4292 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
4293 switch (encoding)
4294 {
4295 case eEncodingT1:
4296 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
4297 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4298 t = Bits32 (opcode, 2, 0);
4299 n = Bits32 (opcode, 5, 3);
4300 m = Bits32 (opcode, 8, 6);
4301
4302 // index = TRUE; add = TRUE; wback = FALSE;
4303 index = true;
4304 add = true;
4305 wback = false;
4306
4307 // (shift_t, shift_n) = (SRType_LSL, 0);
4308 shift_t = SRType_LSL;
4309 shift_n = 0;
4310 break;
4311
4312 case eEncodingT2:
4313 // if Rn == ’1111’ then UNDEFINED;
4314 if (Bits32 (opcode, 19, 16) == 15)
4315 return false;
4316
4317 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4318 t = Bits32 (opcode, 15, 12);
4319 n = Bits32 (opcode, 19, 16);
4320 m = Bits32 (opcode, 3, 0);
4321
4322 // index = TRUE; add = TRUE; wback = FALSE;
4323 index = true;
4324 add = true;
4325 wback = false;
4326
4327 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
4328 shift_t = SRType_LSL;
4329 shift_n = Bits32 (opcode, 5, 4);
4330
4331 // if t == 15 || BadReg(m) then UNPREDICTABLE;
4332 if ((t == 15) || (BadReg (m)))
4333 return false;
4334 break;
4335
4336 case eEncodingA1:
4337 {
4338 // if P == ’0’ && W == ’1’ then SEE STRT;
4339 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
4340 t = Bits32 (opcode, 15, 12);
4341 n = Bits32 (opcode, 19, 16);
4342 m = Bits32 (opcode, 3, 0);
4343
4344 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
4345 index = BitIsSet (opcode, 24);
4346 add = BitIsSet (opcode, 23);
4347 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
4348
4349 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
4350 uint32_t typ = Bits32 (opcode, 6, 5);
4351 uint32_t imm5 = Bits32 (opcode, 11, 7);
4352 shift_n = DecodeImmShift(typ, imm5, shift_t);
4353
4354 // if m == 15 then UNPREDICTABLE;
4355 if (m == 15)
4356 return false;
4357
4358 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
4359 if (wback && ((n == 15) || (n == t)))
4360 return false;
4361
4362 break;
4363 }
4364 default:
4365 return false;
4366 }
4367
4368 addr_t offset_addr;
4369 addr_t address;
4370 int32_t offset = 0;
4371
4372 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4373 if (!success)
4374 return false;
4375
4376 uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
4377 if (!success)
4378 return false;
4379
4380 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
Johnny Chene97c0d52011-02-18 19:32:20 +00004381 offset = Shift (Rm_data, shift_t, shift_n, APSR_C);
Caroline Tice3fd63e92011-02-16 00:33:43 +00004382
4383 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
4384 if (add)
4385 offset_addr = base_address + offset;
4386 else
4387 offset_addr = base_address - offset;
4388
4389 // address = if index then offset_addr else R[n];
4390 if (index)
4391 address = offset_addr;
4392 else
4393 address = base_address;
4394
4395 uint32_t data;
4396 // if t == 15 then // Only possible for encoding A1
4397 if (t == 15)
4398 // data = PCStoreValue();
4399 data = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
4400 else
4401 // data = R[t];
4402 data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4403
4404 if (!success)
4405 return false;
4406
4407 EmulateInstruction::Context context;
4408 context.type = eContextRegisterStore;
4409
4410 // if UnalignedSupport() || address<1:0> == ’00’ || CurrentInstrSet() == InstrSet_ARM then
4411 if (UnalignedSupport ()
4412 || (BitIsClear (address, 1) && BitIsClear (address, 0))
4413 || CurrentInstrSet() == eModeARM)
4414 {
4415 // MemU[address,4] = data;
4416
4417 Register base_reg;
4418 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4419
4420 Register data_reg;
4421 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4422
4423 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
Caroline Ticecc96eb52011-02-17 19:20:40 +00004424 if (!MemUWrite (context, address, data, addr_byte_size))
Caroline Tice3fd63e92011-02-16 00:33:43 +00004425 return false;
4426
4427 }
4428 else
4429 // MemU[address,4] = bits(32) UNKNOWN;
4430 WriteBits32UnknownToMemory (address);
4431
4432 // if wback then R[n] = offset_addr;
4433 if (wback)
4434 {
4435 context.type = eContextRegisterLoad;
4436 context.SetAddress (offset_addr);
4437 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4438 return false;
4439 }
4440
4441 }
4442 return true;
4443}
Caroline Tice73a29de2011-02-16 20:22:22 +00004444
4445bool
4446EmulateInstructionARM::EmulateSTRBThumb (ARMEncoding encoding)
4447{
4448#if 0
4449 if ConditionPassed() then
4450 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4451 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4452 address = if index then offset_addr else R[n];
4453 MemU[address,1] = R[t]<7:0>;
4454 if wback then R[n] = offset_addr;
4455#endif
4456
4457
4458 bool success = false;
4459 const uint32_t opcode = OpcodeAsUnsigned (&success);
4460 if (!success)
4461 return false;
4462
4463 if (ConditionPassed ())
4464 {
4465 uint32_t t;
4466 uint32_t n;
4467 uint32_t imm32;
4468 bool index;
4469 bool add;
4470 bool wback;
4471 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4472 switch (encoding)
4473 {
4474 case eEncodingT1:
4475 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
4476 t = Bits32 (opcode, 2, 0);
4477 n = Bits32 (opcode, 5, 3);
4478 imm32 = Bits32 (opcode, 10, 6);
4479
4480 // index = TRUE; add = TRUE; wback = FALSE;
4481 index = true;
4482 add = true;
4483 wback = false;
4484 break;
4485
4486 case eEncodingT2:
4487 // if Rn == ’1111’ then UNDEFINED;
4488 if (Bits32 (opcode, 19, 16) == 15)
4489 return false;
4490
4491 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4492 t = Bits32 (opcode, 15, 12);
4493 n = Bits32 (opcode, 19, 16);
4494 imm32 = Bits32 (opcode, 11, 0);
4495
4496 // index = TRUE; add = TRUE; wback = FALSE;
4497 index = true;
4498 add = true;
4499 wback = false;
4500
4501 // if BadReg(t) then UNPREDICTABLE;
4502 if (BadReg (t))
4503 return false;
4504 break;
4505
4506 case eEncodingT3:
4507 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE STRBT;
4508 // if Rn == ’1111’ || (P == ’0’ && W == ’0’) then UNDEFINED;
4509 if (Bits32 (opcode, 19, 16) == 15)
4510 return false;
4511
4512 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4513 t = Bits32 (opcode, 15, 12);
4514 n = Bits32 (opcode, 19, 16);
4515 imm32 = Bits32 (opcode, 7, 0);
4516
4517 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
4518 index = BitIsSet (opcode, 10);
4519 add = BitIsSet (opcode, 9);
4520 wback = BitIsSet (opcode, 8);
4521
4522 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
4523 if ((BadReg (t)) || (wback && (n == t)))
4524 return false;
4525 break;
4526
4527 default:
4528 return false;
4529 }
4530
4531 addr_t offset_addr;
4532 addr_t address;
4533 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4534 if (!success)
4535 return false;
4536
4537 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4538 if (add)
4539 offset_addr = base_address + imm32;
4540 else
4541 offset_addr = base_address - imm32;
4542
4543 // address = if index then offset_addr else R[n];
4544 if (index)
4545 address = offset_addr;
4546 else
4547 address = base_address;
4548
Caroline Ticecc96eb52011-02-17 19:20:40 +00004549 // MemU[address,1] = R[t]<7:0>
Caroline Tice73a29de2011-02-16 20:22:22 +00004550 Register base_reg;
4551 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
4552
4553 Register data_reg;
4554 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
4555
4556 EmulateInstruction::Context context;
4557 context.type = eContextRegisterStore;
4558 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
4559
4560 uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
4561 if (!success)
4562 return false;
4563
4564 data = Bits32 (data, 7, 0);
4565
Caroline Ticecc96eb52011-02-17 19:20:40 +00004566 if (!MemUWrite (context, address, data, 1))
Caroline Tice73a29de2011-02-16 20:22:22 +00004567 return false;
4568
4569 // if wback then R[n] = offset_addr;
4570 if (wback)
4571 {
4572 context.type = eContextRegisterLoad;
4573 context.SetAddress (offset_addr);
4574 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
4575 return false;
4576 }
4577
4578 }
4579
4580 return true;
4581}
Caroline Tice3fd63e92011-02-16 00:33:43 +00004582
Johnny Chen157b9592011-02-18 21:13:05 +00004583// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
4584// and writes the result to the destination register. It can optionally update the condition flags
4585// based on the result.
4586bool
4587EmulateInstructionARM::EmulateADCImm (ARMEncoding encoding)
4588{
4589#if 0
4590 // ARM pseudo code...
4591 if ConditionPassed() then
4592 EncodingSpecificOperations();
4593 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
4594 if d == 15 then // Can only occur for ARM encoding
4595 ALUWritePC(result); // setflags is always FALSE here
4596 else
4597 R[d] = result;
4598 if setflags then
4599 APSR.N = result<31>;
4600 APSR.Z = IsZeroBit(result);
4601 APSR.C = carry;
4602 APSR.V = overflow;
4603#endif
4604
4605 bool success = false;
4606 const uint32_t opcode = OpcodeAsUnsigned (&success);
4607 if (!success)
4608 return false;
4609
4610 if (ConditionPassed())
4611 {
4612 uint32_t Rd, Rn;
4613 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
4614 bool setflags;
4615 switch (encoding)
4616 {
4617 case eEncodingT1:
4618 Rd = Bits32(opcode, 11, 8);
4619 Rn = Bits32(opcode, 19, 16);
4620 setflags = BitIsSet(opcode, 20);
4621 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
4622 if (BadReg(Rd) || BadReg(Rn))
4623 return false;
4624 break;
4625 case eEncodingA1:
4626 Rd = Bits32(opcode, 15, 12);
4627 Rn = Bits32(opcode, 19, 16);
4628 setflags = BitIsSet(opcode, 20);
4629 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4630 // TODO: Emulate SUBS PC, LR and related instructions.
4631 if (Rd == 15 && setflags)
4632 return false;
4633 break;
4634 default:
4635 return false;
4636 }
4637
4638 // Read the first operand.
4639 int32_t val1 = ReadCoreReg(Rn, &success);
4640 if (!success)
4641 return false;
4642
4643 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
4644
4645 EmulateInstruction::Context context;
4646 context.type = EmulateInstruction::eContextImmediate;
4647 context.SetNoArgs ();
4648
4649 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4650 return false;
4651 }
4652 return true;
4653}
4654
4655// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
4656// register value, and writes the result to the destination register. It can optionally update the
4657// condition flags based on the result.
4658bool
4659EmulateInstructionARM::EmulateADCReg (ARMEncoding encoding)
4660{
4661#if 0
4662 // ARM pseudo code...
4663 if ConditionPassed() then
4664 EncodingSpecificOperations();
4665 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
4666 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
4667 if d == 15 then // Can only occur for ARM encoding
4668 ALUWritePC(result); // setflags is always FALSE here
4669 else
4670 R[d] = result;
4671 if setflags then
4672 APSR.N = result<31>;
4673 APSR.Z = IsZeroBit(result);
4674 APSR.C = carry;
4675 APSR.V = overflow;
4676#endif
4677
4678 bool success = false;
4679 const uint32_t opcode = OpcodeAsUnsigned (&success);
4680 if (!success)
4681 return false;
4682
4683 if (ConditionPassed())
4684 {
4685 uint32_t Rd, Rn, Rm;
4686 ARM_ShifterType shift_t;
4687 uint32_t shift_n; // the shift applied to the value read from Rm
4688 bool setflags;
4689 switch (encoding)
4690 {
4691 case eEncodingT1:
4692 Rd = Rn = Bits32(opcode, 2, 0);
4693 Rm = Bits32(opcode, 5, 3);
4694 setflags = !InITBlock();
4695 shift_t = SRType_LSL;
4696 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004697 break;
Johnny Chen157b9592011-02-18 21:13:05 +00004698 case eEncodingT2:
4699 Rd = Bits32(opcode, 11, 8);
4700 Rn = Bits32(opcode, 19, 16);
4701 Rm = Bits32(opcode, 3, 0);
4702 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004703 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004704 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
4705 return false;
4706 break;
4707 case eEncodingA1:
4708 Rd = Bits32(opcode, 15, 12);
4709 Rn = Bits32(opcode, 19, 16);
4710 Rm = Bits32(opcode, 3, 0);
4711 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004712 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen157b9592011-02-18 21:13:05 +00004713 // TODO: Emulate SUBS PC, LR and related instructions.
4714 if (Rd == 15 && setflags)
4715 return false;
4716 break;
4717 default:
4718 return false;
4719 }
4720
4721 // Read the first operand.
4722 int32_t val1 = ReadCoreReg(Rn, &success);
4723 if (!success)
4724 return false;
4725
4726 // Read the second operand.
4727 int32_t val2 = ReadCoreReg(Rm, &success);
4728 if (!success)
4729 return false;
4730
4731 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
4732 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
4733
4734 EmulateInstruction::Context context;
4735 context.type = EmulateInstruction::eContextImmediate;
4736 context.SetNoArgs ();
4737
4738 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
4739 return false;
4740 }
4741 return true;
4742}
4743
Johnny Chena695f952011-02-23 21:24:25 +00004744// This instruction adds an immediate value to the PC value to form a PC-relative address,
4745// and writes the result to the destination register.
4746bool
4747EmulateInstructionARM::EmulateADR (ARMEncoding encoding)
4748{
4749#if 0
4750 // ARM pseudo code...
4751 if ConditionPassed() then
4752 EncodingSpecificOperations();
4753 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
4754 if d == 15 then // Can only occur for ARM encodings
4755 ALUWritePC(result);
4756 else
4757 R[d] = result;
4758#endif
4759
4760 bool success = false;
4761 const uint32_t opcode = OpcodeAsUnsigned (&success);
4762 if (!success)
4763 return false;
4764
4765 if (ConditionPassed())
4766 {
4767 uint32_t Rd;
4768 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
4769 bool add;
4770 switch (encoding)
4771 {
4772 case eEncodingT1:
4773 Rd = Bits32(opcode, 10, 8);
4774 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
4775 break;
4776 case eEncodingT2:
4777 case eEncodingT3:
4778 Rd = Bits32(opcode, 11, 8);
4779 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
4780 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
4781 if (BadReg(Rd))
4782 return false;
4783 break;
4784 case eEncodingA1:
4785 case eEncodingA2:
4786 Rd = Bits32(opcode, 15, 12);
4787 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
4788 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
4789 break;
4790 default:
4791 return false;
4792 }
4793
4794 // Read the PC value.
4795 uint32_t pc = ReadCoreReg(PC_REG, &success);
4796 if (!success)
4797 return false;
4798
4799 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
4800
4801 EmulateInstruction::Context context;
4802 context.type = EmulateInstruction::eContextImmediate;
4803 context.SetNoArgs ();
4804
4805 if (!WriteCoreReg(context, result, Rd))
4806 return false;
4807 }
4808 return true;
4809}
4810
Johnny Chene97c0d52011-02-18 19:32:20 +00004811// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
4812// to the destination register. It can optionally update the condition flags based on the result.
4813bool
4814EmulateInstructionARM::EmulateANDImm (ARMEncoding encoding)
4815{
4816#if 0
4817 // ARM pseudo code...
4818 if ConditionPassed() then
4819 EncodingSpecificOperations();
4820 result = R[n] AND imm32;
4821 if d == 15 then // Can only occur for ARM encoding
4822 ALUWritePC(result); // setflags is always FALSE here
4823 else
4824 R[d] = result;
4825 if setflags then
4826 APSR.N = result<31>;
4827 APSR.Z = IsZeroBit(result);
4828 APSR.C = carry;
4829 // APSR.V unchanged
4830#endif
4831
4832 bool success = false;
4833 const uint32_t opcode = OpcodeAsUnsigned (&success);
4834 if (!success)
4835 return false;
4836
4837 if (ConditionPassed())
4838 {
4839 uint32_t Rd, Rn;
4840 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
4841 bool setflags;
4842 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
4843 switch (encoding)
4844 {
4845 case eEncodingT1:
4846 Rd = Bits32(opcode, 11, 8);
4847 Rn = Bits32(opcode, 19, 16);
4848 setflags = BitIsSet(opcode, 20);
4849 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
Johnny Chende3cce32011-02-21 21:24:49 +00004850 // if Rd == '1111' && S == '1' then SEE TST (immediate);
Johnny Chene97c0d52011-02-18 19:32:20 +00004851 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004852 return EmulateTSTImm(eEncodingT1);
Johnny Chene97c0d52011-02-18 19:32:20 +00004853 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
4854 return false;
4855 break;
4856 case eEncodingA1:
4857 Rd = Bits32(opcode, 15, 12);
4858 Rn = Bits32(opcode, 19, 16);
4859 setflags = BitIsSet(opcode, 20);
4860 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
4861 // TODO: Emulate SUBS PC, LR and related instructions.
4862 if (Rd == 15 && setflags)
4863 return false;
4864 break;
4865 default:
4866 return false;
4867 }
4868
Johnny Chene97c0d52011-02-18 19:32:20 +00004869 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004870 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004871 if (!success)
4872 return false;
4873
4874 uint32_t result = val1 & imm32;
4875
4876 EmulateInstruction::Context context;
4877 context.type = EmulateInstruction::eContextImmediate;
4878 context.SetNoArgs ();
4879
4880 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4881 return false;
4882 }
4883 return true;
4884}
4885
4886// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
4887// and writes the result to the destination register. It can optionally update the condition flags
4888// based on the result.
4889bool
4890EmulateInstructionARM::EmulateANDReg (ARMEncoding encoding)
4891{
4892#if 0
4893 // ARM pseudo code...
4894 if ConditionPassed() then
4895 EncodingSpecificOperations();
4896 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
4897 result = R[n] AND shifted;
4898 if d == 15 then // Can only occur for ARM encoding
4899 ALUWritePC(result); // setflags is always FALSE here
4900 else
4901 R[d] = result;
4902 if setflags then
4903 APSR.N = result<31>;
4904 APSR.Z = IsZeroBit(result);
4905 APSR.C = carry;
4906 // APSR.V unchanged
4907#endif
4908
4909 bool success = false;
4910 const uint32_t opcode = OpcodeAsUnsigned (&success);
4911 if (!success)
4912 return false;
4913
4914 if (ConditionPassed())
4915 {
4916 uint32_t Rd, Rn, Rm;
4917 ARM_ShifterType shift_t;
4918 uint32_t shift_n; // the shift applied to the value read from Rm
4919 bool setflags;
4920 uint32_t carry;
4921 switch (encoding)
4922 {
4923 case eEncodingT1:
4924 Rd = Rn = Bits32(opcode, 2, 0);
4925 Rm = Bits32(opcode, 5, 3);
4926 setflags = !InITBlock();
4927 shift_t = SRType_LSL;
4928 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00004929 break;
Johnny Chene97c0d52011-02-18 19:32:20 +00004930 case eEncodingT2:
4931 Rd = Bits32(opcode, 11, 8);
4932 Rn = Bits32(opcode, 19, 16);
4933 Rm = Bits32(opcode, 3, 0);
4934 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004935 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00004936 // if Rd == '1111' && S == '1' then SEE TST (register);
Johnny Chene97c0d52011-02-18 19:32:20 +00004937 if (Rd == 15 && setflags)
Johnny Chende3cce32011-02-21 21:24:49 +00004938 return EmulateTSTReg(eEncodingT2);
Johnny Chene97c0d52011-02-18 19:32:20 +00004939 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
4940 return false;
4941 break;
4942 case eEncodingA1:
4943 Rd = Bits32(opcode, 15, 12);
4944 Rn = Bits32(opcode, 19, 16);
4945 Rm = Bits32(opcode, 3, 0);
4946 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00004947 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chene97c0d52011-02-18 19:32:20 +00004948 // TODO: Emulate SUBS PC, LR and related instructions.
4949 if (Rd == 15 && setflags)
4950 return false;
4951 break;
4952 default:
4953 return false;
4954 }
4955
Johnny Chene97c0d52011-02-18 19:32:20 +00004956 // Read the first operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004957 uint32_t val1 = ReadCoreReg(Rn, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004958 if (!success)
4959 return false;
4960
4961 // Read the second operand.
Johnny Chen157b9592011-02-18 21:13:05 +00004962 uint32_t val2 = ReadCoreReg(Rm, &success);
Johnny Chene97c0d52011-02-18 19:32:20 +00004963 if (!success)
4964 return false;
4965
4966 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
4967 uint32_t result = val1 & shifted;
4968
4969 EmulateInstruction::Context context;
4970 context.type = EmulateInstruction::eContextImmediate;
4971 context.SetNoArgs ();
4972
4973 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
4974 return false;
4975 }
4976 return true;
4977}
4978
Johnny Chenb9f02cf2011-02-24 01:15:17 +00004979// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
4980// immediate value, and writes the result to the destination register. It can optionally update the
4981// condition flags based on the result.
4982bool
4983EmulateInstructionARM::EmulateBICImm (ARMEncoding encoding)
4984{
4985#if 0
4986 // ARM pseudo code...
4987 if ConditionPassed() then
4988 EncodingSpecificOperations();
4989 result = R[n] AND NOT(imm32);
4990 if d == 15 then // Can only occur for ARM encoding
4991 ALUWritePC(result); // setflags is always FALSE here
4992 else
4993 R[d] = result;
4994 if setflags then
4995 APSR.N = result<31>;
4996 APSR.Z = IsZeroBit(result);
4997 APSR.C = carry;
4998 // APSR.V unchanged
4999#endif
5000
5001 bool success = false;
5002 const uint32_t opcode = OpcodeAsUnsigned (&success);
5003 if (!success)
5004 return false;
5005
5006 if (ConditionPassed())
5007 {
5008 uint32_t Rd, Rn;
5009 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
5010 bool setflags;
5011 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
5012 switch (encoding)
5013 {
5014 case eEncodingT1:
5015 Rd = Bits32(opcode, 11, 8);
5016 Rn = Bits32(opcode, 19, 16);
5017 setflags = BitIsSet(opcode, 20);
5018 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
5019 if (BadReg(Rd) || BadReg(Rn))
5020 return false;
5021 break;
5022 case eEncodingA1:
5023 Rd = Bits32(opcode, 15, 12);
5024 Rn = Bits32(opcode, 19, 16);
5025 setflags = BitIsSet(opcode, 20);
5026 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
5027 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5028 // TODO: Emulate SUBS PC, LR and related instructions.
5029 if (Rd == 15 && setflags)
5030 return false;
5031 break;
5032 default:
5033 return false;
5034 }
5035
5036 // Read the first operand.
5037 uint32_t val1 = ReadCoreReg(Rn, &success);
5038 if (!success)
5039 return false;
5040
5041 uint32_t result = val1 & ~imm32;
5042
5043 EmulateInstruction::Context context;
5044 context.type = EmulateInstruction::eContextImmediate;
5045 context.SetNoArgs ();
5046
5047 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5048 return false;
5049 }
5050 return true;
5051}
5052
5053// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
5054// optionally-shifted register value, and writes the result to the destination register.
5055// It can optionally update the condition flags based on the result.
5056bool
5057EmulateInstructionARM::EmulateBICReg (ARMEncoding encoding)
5058{
5059#if 0
5060 // ARM pseudo code...
5061 if ConditionPassed() then
5062 EncodingSpecificOperations();
5063 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
5064 result = R[n] AND NOT(shifted);
5065 if d == 15 then // Can only occur for ARM encoding
5066 ALUWritePC(result); // setflags is always FALSE here
5067 else
5068 R[d] = result;
5069 if setflags then
5070 APSR.N = result<31>;
5071 APSR.Z = IsZeroBit(result);
5072 APSR.C = carry;
5073 // APSR.V unchanged
5074#endif
5075
5076 bool success = false;
5077 const uint32_t opcode = OpcodeAsUnsigned (&success);
5078 if (!success)
5079 return false;
5080
5081 if (ConditionPassed())
5082 {
5083 uint32_t Rd, Rn, Rm;
5084 ARM_ShifterType shift_t;
5085 uint32_t shift_n; // the shift applied to the value read from Rm
5086 bool setflags;
5087 uint32_t carry;
5088 switch (encoding)
5089 {
5090 case eEncodingT1:
5091 Rd = Rn = Bits32(opcode, 2, 0);
5092 Rm = Bits32(opcode, 5, 3);
5093 setflags = !InITBlock();
5094 shift_t = SRType_LSL;
5095 shift_n = 0;
5096 break;
5097 case eEncodingT2:
5098 Rd = Bits32(opcode, 11, 8);
5099 Rn = Bits32(opcode, 19, 16);
5100 Rm = Bits32(opcode, 3, 0);
5101 setflags = BitIsSet(opcode, 20);
5102 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5103 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5104 return false;
5105 break;
5106 case eEncodingA1:
5107 Rd = Bits32(opcode, 15, 12);
5108 Rn = Bits32(opcode, 19, 16);
5109 Rm = Bits32(opcode, 3, 0);
5110 setflags = BitIsSet(opcode, 20);
5111 shift_n = DecodeImmShiftARM(opcode, shift_t);
5112 // if Rd == ‘1111’ && S == ‘1’ then SEE SUBS PC, LR and related instructions;
5113 // TODO: Emulate SUBS PC, LR and related instructions.
5114 if (Rd == 15 && setflags)
5115 return false;
5116 break;
5117 default:
5118 return false;
5119 }
5120
5121 // Read the first operand.
5122 uint32_t val1 = ReadCoreReg(Rn, &success);
5123 if (!success)
5124 return false;
5125
5126 // Read the second operand.
5127 uint32_t val2 = ReadCoreReg(Rm, &success);
5128 if (!success)
5129 return false;
5130
5131 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
5132 uint32_t result = val1 & ~shifted;
5133
5134 EmulateInstruction::Context context;
5135 context.type = EmulateInstruction::eContextImmediate;
5136 context.SetNoArgs ();
5137
5138 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
5139 return false;
5140 }
5141 return true;
5142}
5143
Caroline Tice4d729c52011-02-18 00:55:53 +00005144// 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 +00005145// 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 +00005146bool
5147EmulateInstructionARM::EmulateLDRImmediateARM (ARMEncoding encoding)
5148{
5149#if 0
5150 if ConditionPassed() then
5151 EncodingSpecificOperations();
5152 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5153 address = if index then offset_addr else R[n];
5154 data = MemU[address,4];
5155 if wback then R[n] = offset_addr;
5156 if t == 15 then
5157 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5158 elsif UnalignedSupport() || address<1:0> = ’00’ then
5159 R[t] = data;
5160 else // Can only apply before ARMv7
5161 R[t] = ROR(data, 8*UInt(address<1:0>));
5162#endif
5163
5164 bool success = false;
5165 const uint32_t opcode = OpcodeAsUnsigned (&success);
5166 if (!success)
5167 return false;
5168
5169 if (ConditionPassed ())
5170 {
5171 const uint32_t addr_byte_size = GetAddressByteSize();
5172
5173 uint32_t t;
5174 uint32_t n;
5175 uint32_t imm32;
5176 bool index;
5177 bool add;
5178 bool wback;
5179
5180 switch (encoding)
5181 {
5182 case eEncodingA1:
5183 // if Rn == ’1111’ then SEE LDR (literal);
5184 // if P == ’0’ && W == ’1’ then SEE LDRT;
5185 // if Rn == ’1101’ && P == ’0’ && U == ’1’ && W == ’0’ && imm12 == ’000000000100’ then SEE POP;
5186 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5187 t = Bits32 (opcode, 15, 12);
5188 n = Bits32 (opcode, 19, 16);
5189 imm32 = Bits32 (opcode, 11, 0);
5190
5191 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5192 index = BitIsSet (opcode, 24);
5193 add = BitIsSet (opcode, 23);
5194 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5195
5196 // if wback && n == t then UNPREDICTABLE;
5197 if (wback && (n == t))
5198 return false;
5199
5200 break;
5201
5202 default:
5203 return false;
5204 }
5205
5206 addr_t address;
5207 addr_t offset_addr;
5208 addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5209 if (!success)
5210 return false;
5211
5212 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5213 if (add)
5214 offset_addr = base_address + imm32;
5215 else
5216 offset_addr = base_address - imm32;
5217
5218 // address = if index then offset_addr else R[n];
5219 if (index)
5220 address = offset_addr;
5221 else
5222 address = base_address;
5223
5224 // data = MemU[address,4];
5225
5226 Register base_reg;
5227 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5228
5229 EmulateInstruction::Context context;
5230 context.type = eContextRegisterLoad;
5231 context.SetRegisterPlusOffset (base_reg, address - base_address);
5232
5233 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5234 if (!success)
5235 return false;
5236
5237 // if wback then R[n] = offset_addr;
5238 if (wback)
5239 {
5240 context.type = eContextAdjustBaseRegister;
5241 context.SetAddress (offset_addr);
5242 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5243 return false;
5244 }
5245
5246 // if t == 15 then
5247 if (t == 15)
5248 {
5249 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5250 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5251 {
5252 // LoadWritePC (data);
5253 context.type = eContextRegisterLoad;
5254 context.SetRegisterPlusOffset (base_reg, address - base_address);
5255 LoadWritePC (context, data);
5256 }
5257 else
5258 return false;
5259 }
5260 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5261 else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5262 {
5263 // R[t] = data;
5264 context.type = eContextRegisterLoad;
5265 context.SetRegisterPlusOffset (base_reg, address - base_address);
5266 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5267 return false;
5268 }
5269 // else // Can only apply before ARMv7
5270 else
5271 {
5272 // R[t] = ROR(data, 8*UInt(address<1:0>));
5273 data = ROR (data, Bits32 (address, 1, 0));
5274 context.type = eContextRegisterLoad;
5275 context.SetImmediate (data);
5276 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5277 return false;
5278 }
5279
5280 }
5281 return true;
5282}
5283
Caroline Ticefe479112011-02-18 18:52:37 +00005284// LDR (register) calculates an address from a base register value and an offset register value, loads a word
5285// from memory, and writes it to a resgister. The offset register value can optionally be shifted.
5286bool
5287EmulateInstructionARM::EmulateLDRRegister (ARMEncoding encoding)
5288{
5289#if 0
5290 if ConditionPassed() then
5291 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5292 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5293 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5294 address = if index then offset_addr else R[n];
5295 data = MemU[address,4];
5296 if wback then R[n] = offset_addr;
5297 if t == 15 then
5298 if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5299 elsif UnalignedSupport() || address<1:0> = ’00’ then
5300 R[t] = data;
5301 else // Can only apply before ARMv7
5302 if CurrentInstrSet() == InstrSet_ARM then
5303 R[t] = ROR(data, 8*UInt(address<1:0>));
5304 else
5305 R[t] = bits(32) UNKNOWN;
5306#endif
5307
5308 bool success = false;
5309 const uint32_t opcode = OpcodeAsUnsigned (&success);
5310 if (!success)
5311 return false;
5312
5313 if (ConditionPassed ())
5314 {
5315 const uint32_t addr_byte_size = GetAddressByteSize();
5316
5317 uint32_t t;
5318 uint32_t n;
5319 uint32_t m;
5320 bool index;
5321 bool add;
5322 bool wback;
5323 ARM_ShifterType shift_t;
5324 uint32_t shift_n;
5325
5326 switch (encoding)
5327 {
5328 case eEncodingT1:
5329 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
5330 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5331 t = Bits32 (opcode, 2, 0);
5332 n = Bits32 (opcode, 5, 3);
5333 m = Bits32 (opcode, 8, 6);
5334
5335 // index = TRUE; add = TRUE; wback = FALSE;
5336 index = true;
5337 add = true;
5338 wback = false;
5339
5340 // (shift_t, shift_n) = (SRType_LSL, 0);
5341 shift_t = SRType_LSL;
5342 shift_n = 0;
5343
5344 break;
5345
5346 case eEncodingT2:
5347 // if Rn == ’1111’ then SEE LDR (literal);
5348 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5349 t = Bits32 (opcode, 15, 12);
5350 n = Bits32 (opcode, 19, 16);
5351 m = Bits32 (opcode, 3, 0);
5352
5353 // index = TRUE; add = TRUE; wback = FALSE;
5354 index = true;
5355 add = true;
5356 wback = false;
5357
5358 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5359 shift_t = SRType_LSL;
5360 shift_n = Bits32 (opcode, 5, 4);
5361
5362 // if BadReg(m) then UNPREDICTABLE;
5363 if (BadReg (m))
5364 return false;
5365
5366 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
5367 if ((t == 15) && InITBlock() && !LastInITBlock())
5368 return false;
5369
5370 break;
5371
5372 case eEncodingA1:
5373 {
5374 // if P == ’0’ && W == ’1’ then SEE LDRT;
5375 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5376 t = Bits32 (opcode, 15, 12);
5377 n = Bits32 (opcode, 19, 16);
5378 m = Bits32 (opcode, 3, 0);
5379
5380 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5381 index = BitIsSet (opcode, 24);
5382 add = BitIsSet (opcode, 23);
5383 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5384
5385 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5386 uint32_t type = Bits32 (opcode, 6, 5);
5387 uint32_t imm5 = Bits32 (opcode, 11, 7);
5388 shift_n = DecodeImmShift (type, imm5, shift_t);
5389
5390 // if m == 15 then UNPREDICTABLE;
5391 if (m == 15)
5392 return false;
5393
5394 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5395 if (wback && ((n == 15) || (n == t)))
5396 return false;
5397 }
5398 break;
5399
5400
5401 default:
5402 return false;
5403 }
5404
5405 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5406 if (!success)
5407 return false;
5408
5409 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5410 if (!success)
5411 return false;
5412
5413 addr_t offset_addr;
5414 addr_t address;
5415
5416 // 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 +00005417 addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_inst_cpsr, APSR_C));
Caroline Ticefe479112011-02-18 18:52:37 +00005418
5419 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5420 if (add)
5421 offset_addr = Rn + offset;
5422 else
5423 offset_addr = Rn - offset;
5424
5425 // address = if index then offset_addr else R[n];
5426 if (index)
5427 address = offset_addr;
5428 else
5429 address = Rn;
5430
5431 // data = MemU[address,4];
5432 Register base_reg;
5433 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5434
5435 EmulateInstruction::Context context;
5436 context.type = eContextRegisterLoad;
5437 context.SetRegisterPlusOffset (base_reg, address - Rn);
5438
5439 uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
5440 if (!success)
5441 return false;
5442
5443 // if wback then R[n] = offset_addr;
5444 if (wback)
5445 {
5446 context.type = eContextAdjustBaseRegister;
5447 context.SetAddress (offset_addr);
5448 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5449 return false;
5450 }
5451
5452 // if t == 15 then
5453 if (t == 15)
5454 {
5455 // if address<1:0> == ’00’ then LoadWritePC(data); else UNPREDICTABLE;
5456 if (BitIsClear (address, 1) && BitIsClear (address, 0))
5457 {
5458 context.type = eContextRegisterLoad;
5459 context.SetRegisterPlusOffset (base_reg, address - Rn);
5460 LoadWritePC (context, data);
5461 }
5462 else
5463 return false;
5464 }
5465 // elsif UnalignedSupport() || address<1:0> = ’00’ then
5466 else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
5467 {
5468 // R[t] = data;
5469 context.type = eContextRegisterLoad;
5470 context.SetRegisterPlusOffset (base_reg, address - Rn);
5471 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5472 return false;
5473 }
5474 else // Can only apply before ARMv7
5475 {
5476 // if CurrentInstrSet() == InstrSet_ARM then
5477 if (CurrentInstrSet () == eModeARM)
5478 {
5479 // R[t] = ROR(data, 8*UInt(address<1:0>));
5480 data = ROR (data, Bits32 (address, 1, 0));
5481 context.type = eContextRegisterLoad;
5482 context.SetImmediate (data);
5483 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5484 return false;
5485 }
5486 else
5487 {
5488 // R[t] = bits(32) UNKNOWN;
5489 WriteBits32Unknown (t);
5490 }
5491 }
5492 }
5493 return true;
5494}
Caroline Tice21b604b2011-02-18 21:06:04 +00005495
5496// LDRB (immediate, Thumb)
5497bool
5498EmulateInstructionARM::EmulateLDRBImmediate (ARMEncoding encoding)
5499{
5500#if 0
5501 if ConditionPassed() then
5502 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5503 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5504 address = if index then offset_addr else R[n];
5505 R[t] = ZeroExtend(MemU[address,1], 32);
5506 if wback then R[n] = offset_addr;
5507#endif
5508
5509 bool success = false;
5510 const uint32_t opcode = OpcodeAsUnsigned (&success);
5511 if (!success)
5512 return false;
5513
5514 if (ConditionPassed ())
5515 {
5516 uint32_t t;
5517 uint32_t n;
5518 uint32_t imm32;
5519 bool index;
5520 bool add;
5521 bool wback;
5522
5523 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5524 switch (encoding)
5525 {
5526 case eEncodingT1:
5527 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5528 t = Bits32 (opcode, 2, 0);
5529 n = Bits32 (opcode, 5, 3);
5530 imm32 = Bits32 (opcode, 10, 6);
5531
5532 // index = TRUE; add = TRUE; wback = FALSE;
5533 index = true;
5534 add = true;
5535 wback= false;
5536
5537 break;
5538
5539 case eEncodingT2:
5540 // if Rt == ’1111’ then SEE PLD;
5541 // if Rn == ’1111’ then SEE LDRB (literal);
5542 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5543 t = Bits32 (opcode, 15, 12);
5544 n = Bits32 (opcode, 19, 16);
5545 imm32 = Bits32 (opcode, 11, 0);
5546
5547 // index = TRUE; add = TRUE; wback = FALSE;
5548 index = true;
5549 add = true;
5550 wback = false;
5551
5552 // if t == 13 then UNPREDICTABLE;
5553 if (t == 13)
5554 return false;
5555
5556 break;
5557
5558 case eEncodingT3:
5559 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLD;
5560 // if Rn == ’1111’ then SEE LDRB (literal);
5561 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRBT;
5562 // if P == ’0’ && W == ’0’ then UNDEFINED;
5563 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5564 return false;
5565
5566 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5567 t = Bits32 (opcode, 15, 12);
5568 n = Bits32 (opcode, 19, 16);
5569 imm32 = Bits32 (opcode, 7, 0);
5570
5571 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5572 index = BitIsSet (opcode, 10);
5573 add = BitIsSet (opcode, 9);
5574 wback = BitIsSet (opcode, 8);
5575
5576 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5577 if (BadReg (t) || (wback && (n == t)))
5578 return false;
5579
5580 break;
5581
5582 default:
5583 return false;
5584 }
5585
5586 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5587 if (!success)
5588 return false;
5589
5590 addr_t address;
5591 addr_t offset_addr;
5592
5593 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5594 if (add)
5595 offset_addr = Rn + imm32;
5596 else
5597 offset_addr = Rn - imm32;
5598
5599 // address = if index then offset_addr else R[n];
5600 if (index)
5601 address = offset_addr;
5602 else
5603 address = Rn;
5604
5605 // R[t] = ZeroExtend(MemU[address,1], 32);
5606 Register base_reg;
5607 Register data_reg;
5608 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5609 data_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + t);
5610
5611 EmulateInstruction::Context context;
5612 context.type = eContextRegisterLoad;
5613 context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
5614
5615 uint64_t data = MemURead (context, address, 1, 0, &success);
5616 if (!success)
5617 return false;
5618
5619 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5620 return false;
5621
5622 // if wback then R[n] = offset_addr;
5623 if (wback)
5624 {
5625 context.type = eContextAdjustBaseRegister;
5626 context.SetAddress (offset_addr);
5627 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5628 return false;
5629 }
5630 }
5631 return true;
5632}
Caroline Ticef55261f2011-02-18 22:24:22 +00005633
5634// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
5635// zero-extends it to form a 32-bit word and writes it to a register.
5636bool
5637EmulateInstructionARM::EmulateLDRBLiteral (ARMEncoding encoding)
5638{
5639#if 0
5640 if ConditionPassed() then
5641 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
5642 base = Align(PC,4);
5643 address = if add then (base + imm32) else (base - imm32);
5644 R[t] = ZeroExtend(MemU[address,1], 32);
5645#endif
5646
5647 bool success = false;
5648 const uint32_t opcode = OpcodeAsUnsigned (&success);
5649 if (!success)
5650 return false;
5651
5652 if (ConditionPassed ())
5653 {
5654 uint32_t t;
5655 uint32_t imm32;
5656 bool add;
5657 switch (encoding)
5658 {
5659 case eEncodingT1:
5660 // if Rt == ’1111’ then SEE PLD;
5661 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5662 t = Bits32 (opcode, 15, 12);
5663 imm32 = Bits32 (opcode, 11, 0);
5664 add = BitIsSet (opcode, 23);
5665
5666 // if t == 13 then UNPREDICTABLE;
5667 if (t == 13)
5668 return false;
5669
5670 break;
5671
5672 case eEncodingA1:
5673 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
5674 t = Bits32 (opcode, 15, 12);
5675 imm32 = Bits32 (opcode, 11, 0);
5676 add = BitIsSet (opcode, 23);
5677
5678 // if t == 15 then UNPREDICTABLE;
5679 if (t == 15)
5680 return false;
5681 break;
5682
5683 default:
5684 return false;
5685 }
5686
5687 // base = Align(PC,4);
5688 uint32_t pc_val = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
5689 if (!success)
5690 return false;
5691
5692 uint32_t base = AlignPC (pc_val);
5693
5694 addr_t address;
5695 // address = if add then (base + imm32) else (base - imm32);
5696 if (add)
5697 address = base + imm32;
5698 else
5699 address = base - imm32;
5700
5701 // R[t] = ZeroExtend(MemU[address,1], 32);
5702 EmulateInstruction::Context context;
5703 context.type = eContextRelativeBranchImmediate;
5704 context.SetImmediate (address - base);
5705
5706 uint64_t data = MemURead (context, address, 1, 0, &success);
5707 if (!success)
5708 return false;
5709
5710 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5711 return false;
5712 }
5713 return true;
5714}
Caroline Tice30fec122011-02-18 23:52:21 +00005715
5716// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
5717// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
5718// optionally be shifted.
5719bool
5720EmulateInstructionARM::EmulateLDRBRegister (ARMEncoding encoding)
5721{
5722#if 0
5723 if ConditionPassed() then
5724 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5725 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5726 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5727 address = if index then offset_addr else R[n];
5728 R[t] = ZeroExtend(MemU[address,1],32);
5729 if wback then R[n] = offset_addr;
5730#endif
5731
5732 bool success = false;
5733 const uint32_t opcode = OpcodeAsUnsigned (&success);
5734 if (!success)
5735 return false;
5736
5737 if (ConditionPassed ())
5738 {
5739 uint32_t t;
5740 uint32_t n;
5741 uint32_t m;
5742 bool index;
5743 bool add;
5744 bool wback;
5745 ARM_ShifterType shift_t;
5746 uint32_t shift_n;
5747
5748 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5749 switch (encoding)
5750 {
5751 case eEncodingT1:
5752 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5753 t = Bits32 (opcode, 2, 0);
5754 n = Bits32 (opcode, 5, 3);
5755 m = Bits32 (opcode, 8, 6);
5756
5757 // index = TRUE; add = TRUE; wback = FALSE;
5758 index = true;
5759 add = true;
5760 wback = false;
5761
5762 // (shift_t, shift_n) = (SRType_LSL, 0);
5763 shift_t = SRType_LSL;
5764 shift_n = 0;
5765 break;
5766
5767 case eEncodingT2:
5768 // if Rt == ’1111’ then SEE PLD;
5769 // if Rn == ’1111’ then SEE LDRB (literal);
5770 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5771 t = Bits32 (opcode, 15, 12);
5772 n = Bits32 (opcode, 19, 16);
5773 m = Bits32 (opcode, 3, 0);
5774
5775 // index = TRUE; add = TRUE; wback = FALSE;
5776 index = true;
5777 add = true;
5778 wback = false;
5779
5780 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5781 shift_t = SRType_LSL;
5782 shift_n = Bits32 (opcode, 5, 4);
5783
5784 // if t == 13 || BadReg(m) then UNPREDICTABLE;
5785 if ((t == 13) || BadReg (m))
5786 return false;
5787 break;
5788
5789 case eEncodingA1:
5790 {
5791 // if P == ’0’ && W == ’1’ then SEE LDRBT;
5792 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5793 t = Bits32 (opcode, 15, 12);
5794 n = Bits32 (opcode, 19, 16);
5795 m = Bits32 (opcode, 3, 0);
5796
5797 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
5798 index = BitIsSet (opcode, 24);
5799 add = BitIsSet (opcode, 23);
5800 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
5801
5802 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5803 uint32_t type = Bits32 (opcode, 6, 5);
5804 uint32_t imm5 = Bits32 (opcode, 11, 7);
5805 shift_n = DecodeImmShift (type, imm5, shift_t);
5806
5807 // if t == 15 || m == 15 then UNPREDICTABLE;
5808 if ((t == 15) || (m == 15))
5809 return false;
5810
5811 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5812 if (wback && ((n == 15) || (n == t)))
5813 return false;
5814 }
5815 break;
5816
5817 default:
5818 return false;
5819 }
5820
5821 addr_t offset_addr;
5822 addr_t address;
5823
5824 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5825 uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5826 if (!success)
5827 return false;
5828
5829 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
5830
5831 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5832 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5833 if (!success)
5834 return false;
5835
5836 if (add)
5837 offset_addr = Rn + offset;
5838 else
5839 offset_addr = Rn - offset;
5840
5841 // address = if index then offset_addr else R[n];
5842 if (index)
5843 address = offset_addr;
5844 else
5845 address = Rn;
5846
5847 // R[t] = ZeroExtend(MemU[address,1],32);
5848 Register base_reg;
5849 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5850
5851 EmulateInstruction::Context context;
5852 context.type = eContextRegisterLoad;
5853 context.SetRegisterPlusOffset (base_reg, address - Rn);
5854
5855 uint64_t data = MemURead (context, address, 1, 0, &success);
5856 if (!success)
5857 return false;
5858
5859 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
5860 return false;
5861
5862 // if wback then R[n] = offset_addr;
5863 if (wback)
5864 {
5865 context.type = eContextAdjustBaseRegister;
5866 context.SetAddress (offset_addr);
5867 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
5868 return false;
5869 }
5870 }
5871 return true;
5872}
Caroline Tice0491b3b2011-02-28 22:39:58 +00005873
5874// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a
5875// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset,
5876// post-indexed, or pre-indexed addressing.
5877bool
5878EmulateInstructionARM::EmulateLDRHImmediate (ARMEncoding encoding)
5879{
5880#if 0
5881 if ConditionPassed() then
5882 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5883 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5884 address = if index then offset_addr else R[n];
5885 data = MemU[address,2];
5886 if wback then R[n] = offset_addr;
5887 if UnalignedSupport() || address<0> = ’0’ then
5888 R[t] = ZeroExtend(data, 32);
5889 else // Can only apply before ARMv7
5890 R[t] = bits(32) UNKNOWN;
5891#endif
5892
5893
5894 bool success = false;
5895 const uint32_t opcode = OpcodeAsUnsigned (&success);
5896 if (!success)
5897 return false;
5898
5899 if (ConditionPassed())
5900 {
5901 uint32_t t;
5902 uint32_t n;
5903 uint32_t imm32;
5904 bool index;
5905 bool add;
5906 bool wback;
5907
5908 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5909 switch (encoding)
5910 {
5911 case eEncodingT1:
5912 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:’0’, 32);
5913 t = Bits32 (opcode, 2, 0);
5914 n = Bits32 (opcode, 5, 3);
5915 imm32 = Bits32 (opcode, 10, 6) << 1;
5916
5917 // index = TRUE; add = TRUE; wback = FALSE;
5918 index = true;
5919 add = true;
5920 wback = false;
5921
5922 break;
5923
5924 case eEncodingT2:
5925 // if Rt == ’1111’ then SEE "Unallocated memory hints";
5926 // if Rn == ’1111’ then SEE LDRH (literal);
5927 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5928 t = Bits32 (opcode, 15, 12);
5929 n = Bits32 (opcode, 19, 16);
5930 imm32 = Bits32 (opcode, 11, 0);
5931
5932 // index = TRUE; add = TRUE; wback = FALSE;
5933 index = true;
5934 add = true;
5935 wback = false;
5936
5937 // if t == 13 then UNPREDICTABLE;
5938 if (t == 13)
5939 return false;
5940 break;
5941
5942 case eEncodingT3:
5943 // if Rn == ’1111’ then SEE LDRH (literal);
5944 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
5945 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRHT;
5946 // if P == ’0’ && W == ’0’ then UNDEFINED;
5947 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
5948 return false;
5949
5950 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5951 t = Bits32 (opcode, 15, 12);
5952 n = Bits32 (opcode, 19, 16);
5953 imm32 = Bits32 (opcode, 7, 0);
5954
5955 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
5956 index = BitIsSet (opcode, 10);
5957 add = BitIsSet (opcode, 9);
5958 wback = BitIsSet (opcode, 8);
5959
5960 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
5961 if (BadReg (t) || (wback && (n == t)))
5962 return false;
5963 break;
5964
5965 default:
5966 return false;
5967 }
5968
5969 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5970 uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5971 if (!success)
5972 return false;
5973
5974 addr_t offset_addr;
5975 addr_t address;
5976
5977 if (add)
5978 offset_addr = Rn + imm32;
5979 else
5980 offset_addr = Rn - imm32;
5981
5982 // address = if index then offset_addr else R[n];
5983 if (index)
5984 address = offset_addr;
5985 else
5986 address = Rn;
5987
5988 // data = MemU[address,2];
5989 Register base_reg;
5990 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
5991
5992 EmulateInstruction::Context context;
5993 context.type = eContextRegisterLoad;
5994 context.SetRegisterPlusOffset (base_reg, address - Rn);
5995
5996 uint64_t data = MemURead (context, address, 2, 0, &success);
5997 if (!success)
5998 return false;
5999
6000 // if wback then R[n] = offset_addr;
6001 if (wback)
6002 {
6003 context.type = eContextAdjustBaseRegister;
6004 context.SetAddress (offset_addr);
6005 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6006 return false;
6007 }
6008
6009 // if UnalignedSupport() || address<0> = ’0’ then
6010 if (UnalignedSupport () || BitIsClear (address, 0))
6011 {
6012 // R[t] = ZeroExtend(data, 32);
6013 context.type = eContextRegisterLoad;
6014 context.SetRegisterPlusOffset (base_reg, address - Rn);
6015 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6016 return false;
6017 }
6018 else // Can only apply before ARMv7
6019 {
6020 // R[t] = bits(32) UNKNOWN;
6021 WriteBits32Unknown (t);
6022 }
6023 }
6024 return true;
6025}
Caroline Ticefe479112011-02-18 18:52:37 +00006026
Caroline Tice952b5382011-02-28 23:15:24 +00006027// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory,
6028// zero-extends it to form a 32-bit word, and writes it to a register.
6029bool
6030EmulateInstructionARM::EmulateLDRHLiteral (ARMEncoding encoding)
6031{
6032#if 0
6033 if ConditionPassed() then
6034 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6035 base = Align(PC,4);
6036 address = if add then (base + imm32) else (base - imm32);
6037 data = MemU[address,2];
6038 if UnalignedSupport() || address<0> = ’0’ then
6039 R[t] = ZeroExtend(data, 32);
6040 else // Can only apply before ARMv7
6041 R[t] = bits(32) UNKNOWN;
6042#endif
6043
6044
6045 bool success = false;
6046 const uint32_t opcode = OpcodeAsUnsigned (&success);
6047 if (!success)
6048 return false;
6049
6050 if (ConditionPassed())
6051 {
6052 uint32_t t;
6053 uint32_t imm32;
6054 bool add;
6055
6056 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6057 switch (encoding)
6058 {
6059 case eEncodingT1:
6060 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6061 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6062 t = Bits32 (opcode, 15, 12);
6063 imm32 = Bits32 (opcode, 11, 0);
6064 add = BitIsSet (opcode, 23);
6065
6066 // if t == 13 then UNPREDICTABLE;
6067 if (t == 13)
6068 return false;
6069
6070 break;
6071
6072 case eEncodingA1:
6073 {
6074 uint32_t imm4H = Bits32 (opcode, 11, 8);
6075 uint32_t imm4L = Bits32 (opcode, 3, 0);
6076
6077 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6078 t = Bits32 (opcode, 15, 12);
6079 imm32 = (imm4H << 4) & imm4L;
6080 add = BitIsSet (opcode, 23);
6081
6082 // if t == 15 then UNPREDICTABLE;
6083 if (t == 15)
6084 return false;
6085 break;
6086 }
6087
6088 default:
6089 return false;
6090 }
6091
6092 // base = Align(PC,4);
6093 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
6094 if (!success)
6095 return false;
6096
6097 addr_t base = AlignPC (pc_value);
6098 addr_t address;
6099
6100 // address = if add then (base + imm32) else (base - imm32);
6101 if (add)
6102 address = base + imm32;
6103 else
6104 address = base - imm32;
6105
6106 // data = MemU[address,2];
6107 Register base_reg;
6108 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6109
6110 EmulateInstruction::Context context;
6111 context.type = eContextRegisterLoad;
6112 context.SetRegisterPlusOffset (base_reg, address - base);
6113
6114 uint64_t data = MemURead (context, address, 2, 0, &success);
6115 if (!success)
6116 return false;
6117
6118
6119 // if UnalignedSupport() || address<0> = ’0’ then
6120 if (UnalignedSupport () || BitIsClear (address, 0))
6121 {
6122 // R[t] = ZeroExtend(data, 32);
6123 context.type = eContextRegisterLoad;
6124 context.SetRegisterPlusOffset (base_reg, address - base);
6125 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6126 return false;
6127
6128 }
6129 else // Can only apply before ARMv7
6130 {
6131 // R[t] = bits(32) UNKNOWN;
6132 WriteBits32Unknown (t);
6133 }
6134 }
6135 return true;
6136}
6137
Johnny Chen2115b412011-02-21 23:42:44 +00006138// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
6139// and writes the result to the destination register. It can optionally update the condition flags based on
6140// the result.
6141bool
6142EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
6143{
6144#if 0
6145 // ARM pseudo code...
6146 if ConditionPassed() then
6147 EncodingSpecificOperations();
6148 result = R[n] EOR imm32;
6149 if d == 15 then // Can only occur for ARM encoding
6150 ALUWritePC(result); // setflags is always FALSE here
6151 else
6152 R[d] = result;
6153 if setflags then
6154 APSR.N = result<31>;
6155 APSR.Z = IsZeroBit(result);
6156 APSR.C = carry;
6157 // APSR.V unchanged
6158#endif
6159
6160 bool success = false;
6161 const uint32_t opcode = OpcodeAsUnsigned (&success);
6162 if (!success)
6163 return false;
6164
6165 if (ConditionPassed())
6166 {
6167 uint32_t Rd, Rn;
6168 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
6169 bool setflags;
6170 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6171 switch (encoding)
6172 {
6173 case eEncodingT1:
6174 Rd = Bits32(opcode, 11, 8);
6175 Rn = Bits32(opcode, 19, 16);
6176 setflags = BitIsSet(opcode, 20);
6177 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6178 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
6179 if (Rd == 15 && setflags)
6180 return EmulateTEQImm(eEncodingT1);
6181 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
6182 return false;
6183 break;
6184 case eEncodingA1:
6185 Rd = Bits32(opcode, 15, 12);
6186 Rn = Bits32(opcode, 19, 16);
6187 setflags = BitIsSet(opcode, 20);
6188 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6189 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6190 // TODO: Emulate SUBS PC, LR and related instructions.
6191 if (Rd == 15 && setflags)
6192 return false;
6193 break;
6194 default:
6195 return false;
6196 }
6197
6198 // Read the first operand.
6199 uint32_t val1 = ReadCoreReg(Rn, &success);
6200 if (!success)
6201 return false;
6202
6203 uint32_t result = val1 ^ imm32;
6204
6205 EmulateInstruction::Context context;
6206 context.type = EmulateInstruction::eContextImmediate;
6207 context.SetNoArgs ();
6208
6209 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6210 return false;
6211 }
6212 return true;
6213}
6214
6215// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
6216// optionally-shifted register value, and writes the result to the destination register.
6217// It can optionally update the condition flags based on the result.
6218bool
6219EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
6220{
6221#if 0
6222 // ARM pseudo code...
6223 if ConditionPassed() then
6224 EncodingSpecificOperations();
6225 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6226 result = R[n] EOR shifted;
6227 if d == 15 then // Can only occur for ARM encoding
6228 ALUWritePC(result); // setflags is always FALSE here
6229 else
6230 R[d] = result;
6231 if setflags then
6232 APSR.N = result<31>;
6233 APSR.Z = IsZeroBit(result);
6234 APSR.C = carry;
6235 // APSR.V unchanged
6236#endif
6237
6238 bool success = false;
6239 const uint32_t opcode = OpcodeAsUnsigned (&success);
6240 if (!success)
6241 return false;
6242
6243 if (ConditionPassed())
6244 {
6245 uint32_t Rd, Rn, Rm;
6246 ARM_ShifterType shift_t;
6247 uint32_t shift_n; // the shift applied to the value read from Rm
6248 bool setflags;
6249 uint32_t carry;
6250 switch (encoding)
6251 {
6252 case eEncodingT1:
6253 Rd = Rn = Bits32(opcode, 2, 0);
6254 Rm = Bits32(opcode, 5, 3);
6255 setflags = !InITBlock();
6256 shift_t = SRType_LSL;
6257 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00006258 break;
Johnny Chen2115b412011-02-21 23:42:44 +00006259 case eEncodingT2:
6260 Rd = Bits32(opcode, 11, 8);
6261 Rn = Bits32(opcode, 19, 16);
6262 Rm = Bits32(opcode, 3, 0);
6263 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00006264 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6265 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00006266 if (Rd == 15 && setflags)
6267 return EmulateTEQReg(eEncodingT1);
6268 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
6269 return false;
6270 break;
6271 case eEncodingA1:
6272 Rd = Bits32(opcode, 15, 12);
6273 Rn = Bits32(opcode, 19, 16);
6274 Rm = Bits32(opcode, 3, 0);
6275 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00006276 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00006277 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6278 // TODO: Emulate SUBS PC, LR and related instructions.
6279 if (Rd == 15 && setflags)
6280 return false;
6281 break;
6282 default:
6283 return false;
6284 }
6285
6286 // Read the first operand.
6287 uint32_t val1 = ReadCoreReg(Rn, &success);
6288 if (!success)
6289 return false;
6290
6291 // Read the second operand.
6292 uint32_t val2 = ReadCoreReg(Rm, &success);
6293 if (!success)
6294 return false;
6295
6296 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
6297 uint32_t result = val1 ^ shifted;
6298
6299 EmulateInstruction::Context context;
6300 context.type = EmulateInstruction::eContextImmediate;
6301 context.SetNoArgs ();
6302
6303 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6304 return false;
6305 }
6306 return true;
6307}
6308
Johnny Chen7c5234d2011-02-18 23:41:11 +00006309// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
6310// writes the result to the destination register. It can optionally update the condition flags based
6311// on the result.
6312bool
6313EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
6314{
6315#if 0
6316 // ARM pseudo code...
6317 if ConditionPassed() then
6318 EncodingSpecificOperations();
6319 result = R[n] OR imm32;
6320 if d == 15 then // Can only occur for ARM encoding
6321 ALUWritePC(result); // setflags is always FALSE here
6322 else
6323 R[d] = result;
6324 if setflags then
6325 APSR.N = result<31>;
6326 APSR.Z = IsZeroBit(result);
6327 APSR.C = carry;
6328 // APSR.V unchanged
6329#endif
6330
6331 bool success = false;
6332 const uint32_t opcode = OpcodeAsUnsigned (&success);
6333 if (!success)
6334 return false;
6335
6336 if (ConditionPassed())
6337 {
6338 uint32_t Rd, Rn;
6339 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
6340 bool setflags;
6341 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6342 switch (encoding)
6343 {
6344 case eEncodingT1:
6345 Rd = Bits32(opcode, 11, 8);
6346 Rn = Bits32(opcode, 19, 16);
6347 setflags = BitIsSet(opcode, 20);
6348 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6349 // if Rn == ‘1111’ then SEE MOV (immediate);
6350 if (Rn == 15)
6351 return EmulateMOVRdImm(eEncodingT2);
6352 if (BadReg(Rd) || Rn == 13)
6353 return false;
6354 break;
6355 case eEncodingA1:
6356 Rd = Bits32(opcode, 15, 12);
6357 Rn = Bits32(opcode, 19, 16);
6358 setflags = BitIsSet(opcode, 20);
6359 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6360 // TODO: Emulate SUBS PC, LR and related instructions.
6361 if (Rd == 15 && setflags)
6362 return false;
6363 break;
6364 default:
6365 return false;
6366 }
6367
6368 // Read the first operand.
6369 uint32_t val1 = ReadCoreReg(Rn, &success);
6370 if (!success)
6371 return false;
6372
6373 uint32_t result = val1 | imm32;
6374
6375 EmulateInstruction::Context context;
6376 context.type = EmulateInstruction::eContextImmediate;
6377 context.SetNoArgs ();
6378
6379 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6380 return false;
6381 }
6382 return true;
6383}
6384
6385// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
6386// value, and writes the result to the destination register. It can optionally update the condition flags based
6387// on the result.
6388bool
6389EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
6390{
6391#if 0
6392 // ARM pseudo code...
6393 if ConditionPassed() then
6394 EncodingSpecificOperations();
6395 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6396 result = R[n] OR shifted;
6397 if d == 15 then // Can only occur for ARM encoding
6398 ALUWritePC(result); // setflags is always FALSE here
6399 else
6400 R[d] = result;
6401 if setflags then
6402 APSR.N = result<31>;
6403 APSR.Z = IsZeroBit(result);
6404 APSR.C = carry;
6405 // APSR.V unchanged
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 Rd, Rn, Rm;
6416 ARM_ShifterType shift_t;
6417 uint32_t shift_n; // the shift applied to the value read from Rm
6418 bool setflags;
6419 uint32_t carry;
6420 switch (encoding)
6421 {
6422 case eEncodingT1:
6423 Rd = Rn = Bits32(opcode, 2, 0);
6424 Rm = Bits32(opcode, 5, 3);
6425 setflags = !InITBlock();
6426 shift_t = SRType_LSL;
6427 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00006428 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00006429 case eEncodingT2:
6430 Rd = Bits32(opcode, 11, 8);
6431 Rn = Bits32(opcode, 19, 16);
6432 Rm = Bits32(opcode, 3, 0);
6433 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00006434 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6435 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00006436 if (Rn == 15)
6437 return EmulateMOVRdRm(eEncodingT3);
6438 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
6439 return false;
6440 break;
6441 case eEncodingA1:
6442 Rd = Bits32(opcode, 15, 12);
6443 Rn = Bits32(opcode, 19, 16);
6444 Rm = Bits32(opcode, 3, 0);
6445 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00006446 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00006447 // TODO: Emulate SUBS PC, LR and related instructions.
6448 if (Rd == 15 && setflags)
6449 return false;
6450 break;
6451 default:
6452 return false;
6453 }
6454
6455 // Read the first operand.
6456 uint32_t val1 = ReadCoreReg(Rn, &success);
6457 if (!success)
6458 return false;
6459
6460 // Read the second operand.
6461 uint32_t val2 = ReadCoreReg(Rm, &success);
6462 if (!success)
6463 return false;
6464
6465 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00006466 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00006467
6468 EmulateInstruction::Context context;
6469 context.type = EmulateInstruction::eContextImmediate;
6470 context.SetNoArgs ();
6471
6472 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6473 return false;
6474 }
6475 return true;
6476}
6477
Johnny Chened32e7c2011-02-22 23:42:58 +00006478// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
6479// the destination register. It can optionally update the condition flags based on the result.
6480bool
6481EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
6482{
6483#if 0
6484 // ARM pseudo code...
6485 if ConditionPassed() then
6486 EncodingSpecificOperations();
6487 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
6488 if d == 15 then // Can only occur for ARM encoding
6489 ALUWritePC(result); // setflags is always FALSE here
6490 else
6491 R[d] = result;
6492 if setflags then
6493 APSR.N = result<31>;
6494 APSR.Z = IsZeroBit(result);
6495 APSR.C = carry;
6496 APSR.V = overflow;
6497#endif
6498
6499 bool success = false;
6500 const uint32_t opcode = OpcodeAsUnsigned (&success);
6501 if (!success)
6502 return false;
6503
6504 uint32_t Rd; // the destination register
6505 uint32_t Rn; // the first operand
6506 bool setflags;
6507 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6508 switch (encoding) {
6509 case eEncodingT1:
6510 Rd = Bits32(opcode, 2, 0);
6511 Rn = Bits32(opcode, 5, 3);
6512 setflags = !InITBlock();
6513 imm32 = 0;
6514 break;
6515 case eEncodingT2:
6516 Rd = Bits32(opcode, 11, 8);
6517 Rn = Bits32(opcode, 19, 16);
6518 setflags = BitIsSet(opcode, 20);
6519 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6520 if (BadReg(Rd) || BadReg(Rn))
6521 return false;
6522 break;
6523 case eEncodingA1:
6524 Rd = Bits32(opcode, 15, 12);
6525 Rn = Bits32(opcode, 19, 16);
6526 setflags = BitIsSet(opcode, 20);
6527 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6528 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6529 // TODO: Emulate SUBS PC, LR and related instructions.
6530 if (Rd == 15 && setflags)
6531 return false;
6532 break;
6533 default:
6534 return false;
6535 }
6536 // Read the register value from the operand register Rn.
6537 uint32_t reg_val = ReadCoreReg(Rn, &success);
6538 if (!success)
6539 return false;
6540
6541 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
6542
6543 EmulateInstruction::Context context;
6544 context.type = EmulateInstruction::eContextImmediate;
6545 context.SetNoArgs ();
6546
6547 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6548 return false;
6549
6550 return true;
6551}
6552
6553// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
6554// result to the destination register. It can optionally update the condition flags based on the result.
6555bool
6556EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
6557{
6558#if 0
6559 // ARM pseudo code...
6560 if ConditionPassed() then
6561 EncodingSpecificOperations();
6562 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6563 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
6564 if d == 15 then // Can only occur for ARM encoding
6565 ALUWritePC(result); // setflags is always FALSE here
6566 else
6567 R[d] = result;
6568 if setflags then
6569 APSR.N = result<31>;
6570 APSR.Z = IsZeroBit(result);
6571 APSR.C = carry;
6572 APSR.V = overflow;
6573#endif
6574
6575 bool success = false;
6576 const uint32_t opcode = OpcodeAsUnsigned (&success);
6577 if (!success)
6578 return false;
6579
6580 uint32_t Rd; // the destination register
6581 uint32_t Rn; // the first operand
6582 uint32_t Rm; // the second operand
6583 bool setflags;
6584 ARM_ShifterType shift_t;
6585 uint32_t shift_n; // the shift applied to the value read from Rm
6586 switch (encoding) {
6587 case eEncodingT1:
6588 Rd = Bits32(opcode, 11, 8);
6589 Rn = Bits32(opcode, 19, 16);
6590 Rm = Bits32(opcode, 3, 0);
6591 setflags = BitIsSet(opcode, 20);
6592 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6593 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
6594 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6595 return false;
6596 break;
6597 case eEncodingA1:
6598 Rd = Bits32(opcode, 15, 12);
6599 Rn = Bits32(opcode, 19, 16);
6600 Rm = Bits32(opcode, 3, 0);
6601 setflags = BitIsSet(opcode, 20);
6602 shift_n = DecodeImmShiftARM(opcode, shift_t);
6603 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6604 // TODO: Emulate SUBS PC, LR and related instructions.
6605 if (Rd == 15 && setflags)
6606 return false;
6607 break;
6608 default:
6609 return false;
6610 }
6611 // Read the register value from register Rn.
6612 uint32_t val1 = ReadCoreReg(Rn, &success);
6613 if (!success)
6614 return false;
6615
6616 // Read the register value from register Rm.
6617 uint32_t val2 = ReadCoreReg(Rm, &success);
6618 if (!success)
6619 return false;
6620
6621 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6622 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
6623
6624 EmulateInstruction::Context context;
6625 context.type = EmulateInstruction::eContextImmediate;
6626 context.SetNoArgs();
6627 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6628 return false;
6629
6630 return true;
6631}
6632
Johnny Chen90e607b2011-02-23 00:07:09 +00006633// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
6634// an immediate value, and writes the result to the destination register. It can optionally update the condition
6635// flags based on the result.
6636bool
6637EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
6638{
6639#if 0
6640 // ARM pseudo code...
6641 if ConditionPassed() then
6642 EncodingSpecificOperations();
6643 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
6644 if d == 15 then
6645 ALUWritePC(result); // setflags is always FALSE here
6646 else
6647 R[d] = result;
6648 if setflags then
6649 APSR.N = result<31>;
6650 APSR.Z = IsZeroBit(result);
6651 APSR.C = carry;
6652 APSR.V = overflow;
6653#endif
6654
6655 bool success = false;
6656 const uint32_t opcode = OpcodeAsUnsigned (&success);
6657 if (!success)
6658 return false;
6659
6660 uint32_t Rd; // the destination register
6661 uint32_t Rn; // the first operand
6662 bool setflags;
6663 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6664 switch (encoding) {
6665 case eEncodingA1:
6666 Rd = Bits32(opcode, 15, 12);
6667 Rn = Bits32(opcode, 19, 16);
6668 setflags = BitIsSet(opcode, 20);
6669 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6670 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6671 // TODO: Emulate SUBS PC, LR and related instructions.
6672 if (Rd == 15 && setflags)
6673 return false;
6674 break;
6675 default:
6676 return false;
6677 }
6678 // Read the register value from the operand register Rn.
6679 uint32_t reg_val = ReadCoreReg(Rn, &success);
6680 if (!success)
6681 return false;
6682
6683 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
6684
6685 EmulateInstruction::Context context;
6686 context.type = EmulateInstruction::eContextImmediate;
6687 context.SetNoArgs ();
6688
6689 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6690 return false;
6691
6692 return true;
6693}
6694
6695// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
6696// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
6697// condition flags based on the result.
6698bool
6699EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
6700{
6701#if 0
6702 // ARM pseudo code...
6703 if ConditionPassed() then
6704 EncodingSpecificOperations();
6705 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6706 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
6707 if d == 15 then
6708 ALUWritePC(result); // setflags is always FALSE here
6709 else
6710 R[d] = result;
6711 if setflags then
6712 APSR.N = result<31>;
6713 APSR.Z = IsZeroBit(result);
6714 APSR.C = carry;
6715 APSR.V = overflow;
6716#endif
6717
6718 bool success = false;
6719 const uint32_t opcode = OpcodeAsUnsigned (&success);
6720 if (!success)
6721 return false;
6722
6723 uint32_t Rd; // the destination register
6724 uint32_t Rn; // the first operand
6725 uint32_t Rm; // the second operand
6726 bool setflags;
6727 ARM_ShifterType shift_t;
6728 uint32_t shift_n; // the shift applied to the value read from Rm
6729 switch (encoding) {
6730 case eEncodingA1:
6731 Rd = Bits32(opcode, 15, 12);
6732 Rn = Bits32(opcode, 19, 16);
6733 Rm = Bits32(opcode, 3, 0);
6734 setflags = BitIsSet(opcode, 20);
6735 shift_n = DecodeImmShiftARM(opcode, shift_t);
6736 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6737 // TODO: Emulate SUBS PC, LR and related instructions.
6738 if (Rd == 15 && setflags)
6739 return false;
6740 break;
6741 default:
6742 return false;
6743 }
6744 // Read the register value from register Rn.
6745 uint32_t val1 = ReadCoreReg(Rn, &success);
6746 if (!success)
6747 return false;
6748
6749 // Read the register value from register Rm.
6750 uint32_t val2 = ReadCoreReg(Rm, &success);
6751 if (!success)
6752 return false;
6753
6754 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6755 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
6756
6757 EmulateInstruction::Context context;
6758 context.type = EmulateInstruction::eContextImmediate;
6759 context.SetNoArgs();
6760 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6761 return false;
6762
6763 return true;
6764}
6765
Johnny Chen9b381772011-02-23 01:01:21 +00006766// Subtract with Carry (immediate) subtracts an immediate value and the value of
6767// NOT (Carry flag) from a register value, and writes the result to the destination register.
6768// It can optionally update the condition flags based on the result.
6769bool
6770EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
6771{
6772#if 0
6773 // ARM pseudo code...
6774 if ConditionPassed() then
6775 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00006776 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00006777 if d == 15 then // Can only occur for ARM encoding
6778 ALUWritePC(result); // setflags is always FALSE here
6779 else
6780 R[d] = result;
6781 if setflags then
6782 APSR.N = result<31>;
6783 APSR.Z = IsZeroBit(result);
6784 APSR.C = carry;
6785 APSR.V = overflow;
6786#endif
6787
6788 bool success = false;
6789 const uint32_t opcode = OpcodeAsUnsigned (&success);
6790 if (!success)
6791 return false;
6792
6793 uint32_t Rd; // the destination register
6794 uint32_t Rn; // the first operand
6795 bool setflags;
6796 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
6797 switch (encoding) {
6798 case eEncodingT1:
6799 Rd = Bits32(opcode, 11, 8);
6800 Rn = Bits32(opcode, 19, 16);
6801 setflags = BitIsSet(opcode, 20);
6802 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6803 if (BadReg(Rd) || BadReg(Rn))
6804 return false;
6805 break;
6806 case eEncodingA1:
6807 Rd = Bits32(opcode, 15, 12);
6808 Rn = Bits32(opcode, 19, 16);
6809 setflags = BitIsSet(opcode, 20);
6810 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
6811 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6812 // TODO: Emulate SUBS PC, LR and related instructions.
6813 if (Rd == 15 && setflags)
6814 return false;
6815 break;
6816 default:
6817 return false;
6818 }
6819 // Read the register value from the operand register Rn.
6820 uint32_t reg_val = ReadCoreReg(Rn, &success);
6821 if (!success)
6822 return false;
6823
6824 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
6825
6826 EmulateInstruction::Context context;
6827 context.type = EmulateInstruction::eContextImmediate;
6828 context.SetNoArgs ();
6829
6830 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6831 return false;
6832
6833 return true;
6834}
6835
6836// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
6837// NOT (Carry flag) from a register value, and writes the result to the destination register.
6838// It can optionally update the condition flags based on the result.
6839bool
6840EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
6841{
6842#if 0
6843 // ARM pseudo code...
6844 if ConditionPassed() then
6845 EncodingSpecificOperations();
6846 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
6847 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
6848 if d == 15 then // Can only occur for ARM encoding
6849 ALUWritePC(result); // setflags is always FALSE here
6850 else
6851 R[d] = result;
6852 if setflags then
6853 APSR.N = result<31>;
6854 APSR.Z = IsZeroBit(result);
6855 APSR.C = carry;
6856 APSR.V = overflow;
6857#endif
6858
6859 bool success = false;
6860 const uint32_t opcode = OpcodeAsUnsigned (&success);
6861 if (!success)
6862 return false;
6863
6864 uint32_t Rd; // the destination register
6865 uint32_t Rn; // the first operand
6866 uint32_t Rm; // the second operand
6867 bool setflags;
6868 ARM_ShifterType shift_t;
6869 uint32_t shift_n; // the shift applied to the value read from Rm
6870 switch (encoding) {
6871 case eEncodingT1:
6872 Rd = Rn = Bits32(opcode, 2, 0);
6873 Rm = Bits32(opcode, 5, 3);
6874 setflags = !InITBlock();
6875 shift_t = SRType_LSL;
6876 shift_n = 0;
6877 break;
6878 case eEncodingT2:
6879 Rd = Bits32(opcode, 11, 8);
6880 Rn = Bits32(opcode, 19, 16);
6881 Rm = Bits32(opcode, 3, 0);
6882 setflags = BitIsSet(opcode, 20);
6883 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6884 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6885 return false;
6886 break;
6887 case eEncodingA1:
6888 Rd = Bits32(opcode, 15, 12);
6889 Rn = Bits32(opcode, 19, 16);
6890 Rm = Bits32(opcode, 3, 0);
6891 setflags = BitIsSet(opcode, 20);
6892 shift_n = DecodeImmShiftARM(opcode, shift_t);
6893 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
6894 // TODO: Emulate SUBS PC, LR and related instructions.
6895 if (Rd == 15 && setflags)
6896 return false;
6897 break;
6898 default:
6899 return false;
6900 }
6901 // Read the register value from register Rn.
6902 uint32_t val1 = ReadCoreReg(Rn, &success);
6903 if (!success)
6904 return false;
6905
6906 // Read the register value from register Rm.
6907 uint32_t val2 = ReadCoreReg(Rm, &success);
6908 if (!success)
6909 return false;
6910
6911 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
6912 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
6913
6914 EmulateInstruction::Context context;
6915 context.type = EmulateInstruction::eContextImmediate;
6916 context.SetNoArgs();
6917 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
6918 return false;
6919
6920 return true;
6921}
6922
Johnny Chen15a7a6b2011-02-23 23:47:56 +00006923// This instruction subtracts an immediate value from a register value, and writes the result
6924// to the destination register. It can optionally update the condition flags based on the result.
6925bool
6926EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
6927{
6928#if 0
6929 // ARM pseudo code...
6930 if ConditionPassed() then
6931 EncodingSpecificOperations();
6932 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
6933 R[d] = result;
6934 if setflags then
6935 APSR.N = result<31>;
6936 APSR.Z = IsZeroBit(result);
6937 APSR.C = carry;
6938 APSR.V = overflow;
6939#endif
6940
6941 bool success = false;
6942 const uint32_t opcode = OpcodeAsUnsigned (&success);
6943 if (!success)
6944 return false;
6945
6946 uint32_t Rd; // the destination register
6947 uint32_t Rn; // the first operand
6948 bool setflags;
6949 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
6950 switch (encoding) {
6951 case eEncodingT1:
6952 Rd = Bits32(opcode, 2, 0);
6953 Rn = Bits32(opcode, 5, 3);
6954 setflags = !InITBlock();
6955 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
6956 break;
6957 case eEncodingT2:
6958 Rd = Rn = Bits32(opcode, 10, 8);
6959 setflags = !InITBlock();
6960 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
6961 break;
6962 case eEncodingT3:
6963 Rd = Bits32(opcode, 11, 8);
6964 Rn = Bits32(opcode, 19, 16);
6965 setflags = BitIsSet(opcode, 20);
6966 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
6967
6968 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
6969 if (Rd == 15 && setflags)
6970 return EmulateCMPImm(eEncodingT2);
6971
6972 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
6973 if (Rn == 13)
6974 return EmulateSUBSPImm(eEncodingT2);
6975
6976 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
6977 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
6978 return false;
6979 break;
6980 case eEncodingT4:
6981 Rd = Bits32(opcode, 11, 8);
6982 Rn = Bits32(opcode, 19, 16);
6983 setflags = BitIsSet(opcode, 20);
6984 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
6985
6986 // if Rn == '1111' then SEE ADR;
6987 if (Rn == 15)
6988 return EmulateADR(eEncodingT2);
6989
6990 // if Rn == '1101' then SEE SUB (SP minus immediate);
6991 if (Rn == 13)
6992 return EmulateSUBSPImm(eEncodingT3);
6993
6994 if (BadReg(Rd))
6995 return false;
6996 break;
6997 default:
6998 return false;
6999 }
7000 // Read the register value from the operand register Rn.
7001 uint32_t reg_val = ReadCoreReg(Rn, &success);
7002 if (!success)
7003 return false;
7004
7005 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
7006
7007 EmulateInstruction::Context context;
7008 context.type = EmulateInstruction::eContextImmediate;
7009 context.SetNoArgs ();
7010
7011 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7012 return false;
7013
7014 return true;
7015}
7016
7017// This instruction subtracts an immediate value from a register value, and writes the result
7018// to the destination register. It can optionally update the condition flags based on the result.
7019bool
7020EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
7021{
7022#if 0
7023 // ARM pseudo code...
7024 if ConditionPassed() then
7025 EncodingSpecificOperations();
7026 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
7027 if d == 15 then
7028 ALUWritePC(result); // setflags is always FALSE here
7029 else
7030 R[d] = result;
7031 if setflags then
7032 APSR.N = result<31>;
7033 APSR.Z = IsZeroBit(result);
7034 APSR.C = carry;
7035 APSR.V = overflow;
7036#endif
7037
7038 bool success = false;
7039 const uint32_t opcode = OpcodeAsUnsigned (&success);
7040 if (!success)
7041 return false;
7042
7043 uint32_t Rd; // the destination register
7044 uint32_t Rn; // the first operand
7045 bool setflags;
7046 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
7047 switch (encoding) {
7048 case eEncodingA1:
7049 Rd = Bits32(opcode, 15, 12);
7050 Rn = Bits32(opcode, 19, 16);
7051 setflags = BitIsSet(opcode, 20);
7052 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7053
7054 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
7055 if (Rn == 15 && !setflags)
7056 return EmulateADR(eEncodingA2);
7057
7058 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
7059 if (Rn == 13)
7060 return EmulateSUBSPImm(eEncodingA1);
7061
7062 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7063 // TODO: Emulate SUBS PC, LR and related instructions.
7064 if (Rd == 15 && setflags)
7065 return false;
7066 break;
7067 default:
7068 return false;
7069 }
7070 // Read the register value from the operand register Rn.
7071 uint32_t reg_val = ReadCoreReg(Rn, &success);
7072 if (!success)
7073 return false;
7074
7075 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
7076
7077 EmulateInstruction::Context context;
7078 context.type = EmulateInstruction::eContextImmediate;
7079 context.SetNoArgs ();
7080
7081 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7082 return false;
7083
7084 return true;
7085}
7086
Johnny Chen2115b412011-02-21 23:42:44 +00007087// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
7088// immediate value. It updates the condition flags based on the result, and discards the result.
7089bool
7090EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
7091{
7092#if 0
7093 // ARM pseudo code...
7094 if ConditionPassed() then
7095 EncodingSpecificOperations();
7096 result = R[n] EOR imm32;
7097 APSR.N = result<31>;
7098 APSR.Z = IsZeroBit(result);
7099 APSR.C = carry;
7100 // APSR.V unchanged
7101#endif
7102
7103 bool success = false;
7104 const uint32_t opcode = OpcodeAsUnsigned (&success);
7105 if (!success)
7106 return false;
7107
7108 if (ConditionPassed())
7109 {
7110 uint32_t Rn;
7111 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
7112 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7113 switch (encoding)
7114 {
7115 case eEncodingT1:
7116 Rn = Bits32(opcode, 19, 16);
7117 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7118 if (BadReg(Rn))
7119 return false;
7120 break;
7121 case eEncodingA1:
7122 Rn = Bits32(opcode, 19, 16);
7123 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7124 break;
7125 default:
7126 return false;
7127 }
7128
7129 // Read the first operand.
7130 uint32_t val1 = ReadCoreReg(Rn, &success);
7131 if (!success)
7132 return false;
7133
7134 uint32_t result = val1 ^ imm32;
7135
7136 EmulateInstruction::Context context;
7137 context.type = EmulateInstruction::eContextImmediate;
7138 context.SetNoArgs ();
7139
7140 if (!WriteFlags(context, result, carry))
7141 return false;
7142 }
7143 return true;
7144}
7145
7146// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
7147// optionally-shifted register value. It updates the condition flags based on the result, and discards
7148// the result.
7149bool
7150EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
7151{
7152#if 0
7153 // ARM pseudo code...
7154 if ConditionPassed() then
7155 EncodingSpecificOperations();
7156 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7157 result = R[n] EOR shifted;
7158 APSR.N = result<31>;
7159 APSR.Z = IsZeroBit(result);
7160 APSR.C = carry;
7161 // APSR.V unchanged
7162#endif
7163
7164 bool success = false;
7165 const uint32_t opcode = OpcodeAsUnsigned (&success);
7166 if (!success)
7167 return false;
7168
7169 if (ConditionPassed())
7170 {
7171 uint32_t Rn, Rm;
7172 ARM_ShifterType shift_t;
7173 uint32_t shift_n; // the shift applied to the value read from Rm
7174 uint32_t carry;
7175 switch (encoding)
7176 {
7177 case eEncodingT1:
7178 Rn = Bits32(opcode, 19, 16);
7179 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00007180 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00007181 if (BadReg(Rn) || BadReg(Rm))
7182 return false;
7183 break;
7184 case eEncodingA1:
7185 Rn = Bits32(opcode, 19, 16);
7186 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00007187 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00007188 break;
7189 default:
7190 return false;
7191 }
7192
7193 // Read the first operand.
7194 uint32_t val1 = ReadCoreReg(Rn, &success);
7195 if (!success)
7196 return false;
7197
7198 // Read the second operand.
7199 uint32_t val2 = ReadCoreReg(Rm, &success);
7200 if (!success)
7201 return false;
7202
7203 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
7204 uint32_t result = val1 ^ shifted;
7205
7206 EmulateInstruction::Context context;
7207 context.type = EmulateInstruction::eContextImmediate;
7208 context.SetNoArgs ();
7209
7210 if (!WriteFlags(context, result, carry))
7211 return false;
7212 }
7213 return true;
7214}
7215
Johnny Chende3cce32011-02-21 21:24:49 +00007216// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
7217// It updates the condition flags based on the result, and discards the result.
7218bool
7219EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
7220{
7221#if 0
7222 // ARM pseudo code...
7223 if ConditionPassed() then
7224 EncodingSpecificOperations();
7225 result = R[n] AND imm32;
7226 APSR.N = result<31>;
7227 APSR.Z = IsZeroBit(result);
7228 APSR.C = carry;
7229 // APSR.V unchanged
7230#endif
7231
7232 bool success = false;
7233 const uint32_t opcode = OpcodeAsUnsigned (&success);
7234 if (!success)
7235 return false;
7236
7237 if (ConditionPassed())
7238 {
7239 uint32_t Rn;
7240 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
7241 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7242 switch (encoding)
7243 {
7244 case eEncodingT1:
7245 Rn = Bits32(opcode, 19, 16);
7246 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7247 if (BadReg(Rn))
7248 return false;
7249 break;
7250 case eEncodingA1:
7251 Rn = Bits32(opcode, 19, 16);
7252 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7253 break;
7254 default:
7255 return false;
7256 }
7257
7258 // Read the first operand.
7259 uint32_t val1 = ReadCoreReg(Rn, &success);
7260 if (!success)
7261 return false;
7262
7263 uint32_t result = val1 & imm32;
7264
7265 EmulateInstruction::Context context;
7266 context.type = EmulateInstruction::eContextImmediate;
7267 context.SetNoArgs ();
7268
7269 if (!WriteFlags(context, result, carry))
7270 return false;
7271 }
7272 return true;
7273}
7274
7275// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
7276// It updates the condition flags based on the result, and discards the result.
7277bool
7278EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
7279{
7280#if 0
7281 // ARM pseudo code...
7282 if ConditionPassed() then
7283 EncodingSpecificOperations();
7284 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7285 result = R[n] AND shifted;
7286 APSR.N = result<31>;
7287 APSR.Z = IsZeroBit(result);
7288 APSR.C = carry;
7289 // APSR.V unchanged
7290#endif
7291
7292 bool success = false;
7293 const uint32_t opcode = OpcodeAsUnsigned (&success);
7294 if (!success)
7295 return false;
7296
7297 if (ConditionPassed())
7298 {
7299 uint32_t Rn, Rm;
7300 ARM_ShifterType shift_t;
7301 uint32_t shift_n; // the shift applied to the value read from Rm
7302 uint32_t carry;
7303 switch (encoding)
7304 {
7305 case eEncodingT1:
7306 Rn = Bits32(opcode, 2, 0);
7307 Rm = Bits32(opcode, 5, 3);
7308 shift_t = SRType_LSL;
7309 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007310 break;
Johnny Chende3cce32011-02-21 21:24:49 +00007311 case eEncodingT2:
7312 Rn = Bits32(opcode, 19, 16);
7313 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00007314 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00007315 if (BadReg(Rn) || BadReg(Rm))
7316 return false;
7317 break;
7318 case eEncodingA1:
7319 Rn = Bits32(opcode, 19, 16);
7320 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00007321 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00007322 break;
7323 default:
7324 return false;
7325 }
7326
7327 // Read the first operand.
7328 uint32_t val1 = ReadCoreReg(Rn, &success);
7329 if (!success)
7330 return false;
7331
7332 // Read the second operand.
7333 uint32_t val2 = ReadCoreReg(Rm, &success);
7334 if (!success)
7335 return false;
7336
7337 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
7338 uint32_t result = val1 & shifted;
7339
7340 EmulateInstruction::Context context;
7341 context.type = EmulateInstruction::eContextImmediate;
7342 context.SetNoArgs ();
7343
7344 if (!WriteFlags(context, result, carry))
7345 return false;
7346 }
7347 return true;
7348}
7349
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007350EmulateInstructionARM::ARMOpcode*
7351EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00007352{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007353 static ARMOpcode
7354 g_arm_opcodes[] =
7355 {
7356 //----------------------------------------------------------------------
7357 // Prologue instructions
7358 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00007359
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007360 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00007361 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
7362 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00007363
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007364 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00007365 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00007366 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00007367 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00007368 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
7369 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00007370 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00007371
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007372 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00007373 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00007374
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007375 // push one register
7376 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00007377 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00007378
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007379 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00007380 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
7381 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00007382
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007383 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00007384 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007385 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00007386
Johnny Chen9f687722011-02-18 00:02:28 +00007387 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
7388 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00007389 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00007390 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
7391
7392 //----------------------------------------------------------------------
7393 // Supervisor Call (previously Software Interrupt)
7394 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00007395 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
7396
7397 //----------------------------------------------------------------------
7398 // Branch instructions
7399 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00007400 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00007401 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
7402 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
7403 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
7404 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00007405 // for example, "bx lr"
7406 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00007407 // bxj
7408 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00007409
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007410 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00007411 // Data-processing instructions
7412 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00007413 // adc (immediate)
7414 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
7415 // adc (register)
7416 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00007417 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00007418 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00007419 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00007420 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00007421 // adr
7422 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
7423 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007424 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00007425 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007426 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00007427 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00007428 // bic (immediate)
7429 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
7430 // bic (register)
7431 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00007432 // eor (immediate)
7433 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
7434 // eor (register)
7435 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00007436 // orr (immediate)
7437 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
7438 // orr (register)
7439 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00007440 // rsb (immediate)
7441 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
7442 // rsb (register)
7443 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00007444 // rsc (immediate)
7445 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
7446 // rsc (register)
7447 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00007448 // sbc (immediate)
7449 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
7450 // sbc (register)
7451 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00007452 // sub (immediate, ARM)
7453 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00007454 // sub (sp minus immediate)
7455 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00007456 // teq (immediate)
7457 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
7458 // teq (register)
7459 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00007460 // tst (immediate)
7461 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
7462 // tst (register)
7463 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
7464
7465
Johnny Chen01d61572011-02-25 00:23:25 +00007466 // mov (register)
7467 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00007468 // mvn (immediate)
7469 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
7470 // mvn (register)
7471 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00007472 // cmn (immediate)
7473 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
7474 // cmn (register)
7475 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007476 // cmp (immediate)
7477 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
7478 // cmp (register)
7479 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00007480 // asr (immediate)
7481 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007482 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00007483 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007484 // lsl (immediate)
7485 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
7486 // lsl (register)
7487 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
7488 // lsr (immediate)
7489 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
7490 // lsr (register)
7491 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00007492 // rrx is a special case encoding of ror (immediate)
7493 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
7494 // ror (immediate)
7495 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
7496 // ror (register)
7497 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00007498
7499 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007500 // Load instructions
7501 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00007502 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00007503 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00007504 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00007505 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00007506 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00007507 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00007508 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00007509 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00007510 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Ticefa172202011-02-11 22:49:54 +00007511
7512 //----------------------------------------------------------------------
7513 // Store instructions
7514 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00007515 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00007516 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00007517 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00007518 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
7519 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00007520
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007521
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007522 };
7523 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
7524
7525 for (size_t i=0; i<k_num_arm_opcodes; ++i)
7526 {
7527 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
7528 return &g_arm_opcodes[i];
7529 }
7530 return NULL;
7531}
Greg Clayton64c84432011-01-21 22:02:52 +00007532
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007533
7534EmulateInstructionARM::ARMOpcode*
7535EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00007536{
Johnny Chenfdd179e2011-01-31 20:09:28 +00007537
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007538 static ARMOpcode
7539 g_thumb_opcodes[] =
7540 {
7541 //----------------------------------------------------------------------
7542 // Prologue instructions
7543 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00007544
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007545 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00007546 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
7547 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
7548 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00007549
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007550 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00007551 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00007552 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00007553 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00007554 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00007555 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00007556
Johnny Chen864a8e82011-02-18 00:07:39 +00007557 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00007558 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00007559
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007560 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00007561 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00007562 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00007563 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
7564 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00007565
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007566 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00007567 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
7568 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00007569
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007570 //----------------------------------------------------------------------
7571 // Epilogue instructions
7572 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00007573
Johnny Chen864a8e82011-02-18 00:07:39 +00007574 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00007575 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
7576 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
7577 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00007578 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
7579 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00007580
7581 //----------------------------------------------------------------------
7582 // Supervisor Call (previously Software Interrupt)
7583 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00007584 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
7585
7586 //----------------------------------------------------------------------
7587 // If Then makes up to four following instructions conditional.
7588 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00007589 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
7590
7591 //----------------------------------------------------------------------
7592 // Branch instructions
7593 //----------------------------------------------------------------------
7594 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
7595 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00007596 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00007597 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00007598 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00007599 // J1 == J2 == 1
7600 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
7601 // J1 == J2 == 1
7602 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
7603 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00007604 // for example, "bx lr"
7605 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00007606 // bxj
7607 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00007608 // compare and branch
7609 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00007610 // table branch byte
7611 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
7612 // table branch halfword
7613 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007614
7615 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00007616 // Data-processing instructions
7617 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00007618 // adc (immediate)
7619 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
7620 // adc (register)
7621 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
7622 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
7623 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00007624 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00007625 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00007626 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00007627 // adr
7628 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
7629 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
7630 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007631 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00007632 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00007633 // and (register)
7634 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
7635 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00007636 // bic (immediate)
7637 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
7638 // bic (register)
7639 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
7640 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00007641 // eor (immediate)
7642 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
7643 // eor (register)
7644 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
7645 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00007646 // orr (immediate)
7647 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
7648 // orr (register)
7649 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
7650 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00007651 // rsb (immediate)
7652 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
7653 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
7654 // rsb (register)
7655 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00007656 // sbc (immediate)
7657 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
7658 // sbc (register)
7659 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
7660 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00007661 // sub (immediate, Thumb)
7662 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
7663 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
7664 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
7665 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00007666 // sub (sp minus immediate)
7667 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
7668 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00007669 // teq (immediate)
7670 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
7671 // teq (register)
7672 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00007673 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00007674 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00007675 // tst (register)
7676 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
7677 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
7678
Johnny Chen7c5234d2011-02-18 23:41:11 +00007679
Johnny Chen338bf542011-02-10 19:29:03 +00007680 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00007681 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00007682 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00007683 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00007684 // mov{s}<c>.w <Rd>, <Rm>
7685 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00007686 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00007687 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
7688 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00007689 // mvn (immediate)
7690 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
7691 // mvn (register)
7692 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
7693 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007694 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00007695 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007696 // cmn (register)
7697 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00007698 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007699 // cmp (immediate)
7700 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00007701 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00007702 // cmp (register) (Rn and Rm both from r0-r7)
7703 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
7704 // cmp (register) (Rn and Rm not both from r0-r7)
7705 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00007706 // asr (immediate)
7707 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00007708 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00007709 // asr (register)
7710 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
7711 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007712 // lsl (immediate)
7713 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
7714 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
7715 // lsl (register)
7716 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
7717 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
7718 // lsr (immediate)
7719 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
7720 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
7721 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00007722 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00007723 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00007724 // rrx is a special case encoding of ror (immediate)
7725 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
7726 // ror (immediate)
7727 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
7728 // ror (register)
7729 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
7730 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00007731
7732 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00007733 // Load instructions
7734 //----------------------------------------------------------------------
7735 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00007736 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00007737 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00007738 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
7739 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00007740 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00007741 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
7742 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00007743 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
7744 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
7745 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00007746 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00007747 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
7748 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00007749 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
7750 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
7751 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00007752 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Ticefa172202011-02-11 22:49:54 +00007753
7754 //----------------------------------------------------------------------
7755 // Store instructions
7756 //----------------------------------------------------------------------
7757 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00007758 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00007759 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00007760 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
7761 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
7762 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
7763 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
7764 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
7765 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
7766 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
7767 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
7768 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00007769 };
7770
7771 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
7772 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
7773 {
7774 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
7775 return &g_thumb_opcodes[i];
7776 }
7777 return NULL;
7778}
Greg Clayton64c84432011-01-21 22:02:52 +00007779
Greg Clayton31e2a382011-01-30 20:03:56 +00007780bool
Greg Clayton395fc332011-02-15 21:59:32 +00007781EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00007782{
7783 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00007784 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00007785 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00007786 {
Greg Clayton395fc332011-02-15 21:59:32 +00007787 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
7788 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
7789 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
7790 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
7791 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
7792 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
7793 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
7794 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
7795 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
7796 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00007797 }
7798 return m_arm_isa != 0;
7799}
7800
7801
Greg Clayton64c84432011-01-21 22:02:52 +00007802bool
7803EmulateInstructionARM::ReadInstruction ()
7804{
7805 bool success = false;
7806 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
7807 if (success)
7808 {
7809 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
7810 if (success)
7811 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00007812 Context read_inst_context;
7813 read_inst_context.type = eContextReadOpcode;
7814 read_inst_context.SetNoArgs ();
7815
Greg Clayton64c84432011-01-21 22:02:52 +00007816 if (m_inst_cpsr & MASK_CPSR_T)
7817 {
7818 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007819 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007820
7821 if (success)
7822 {
7823 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
7824 {
7825 m_inst.opcode_type = eOpcode16;
7826 m_inst.opcode.inst16 = thumb_opcode;
7827 }
7828 else
7829 {
7830 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007831 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007832 }
7833 }
7834 }
7835 else
7836 {
7837 m_inst_mode = eModeARM;
7838 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00007839 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00007840 }
7841 }
7842 }
7843 if (!success)
7844 {
7845 m_inst_mode = eModeInvalid;
7846 m_inst_pc = LLDB_INVALID_ADDRESS;
7847 }
7848 return success;
7849}
7850
Johnny Chenee9b1f72011-02-09 01:00:31 +00007851uint32_t
7852EmulateInstructionARM::ArchVersion ()
7853{
7854 return m_arm_isa;
7855}
7856
Greg Clayton64c84432011-01-21 22:02:52 +00007857bool
7858EmulateInstructionARM::ConditionPassed ()
7859{
7860 if (m_inst_cpsr == 0)
7861 return false;
7862
7863 const uint32_t cond = CurrentCond ();
7864
7865 if (cond == UINT32_MAX)
7866 return false;
7867
7868 bool result = false;
7869 switch (UnsignedBits(cond, 3, 1))
7870 {
7871 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
7872 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
7873 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
7874 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
7875 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
7876 case 5:
7877 {
7878 bool n = (m_inst_cpsr & MASK_CPSR_N);
7879 bool v = (m_inst_cpsr & MASK_CPSR_V);
7880 result = n == v;
7881 }
7882 break;
7883 case 6:
7884 {
7885 bool n = (m_inst_cpsr & MASK_CPSR_N);
7886 bool v = (m_inst_cpsr & MASK_CPSR_V);
7887 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
7888 }
7889 break;
7890 case 7:
7891 result = true;
7892 break;
7893 }
7894
7895 if (cond & 1)
7896 result = !result;
7897 return result;
7898}
7899
Johnny Chen9ee056b2011-02-08 00:06:35 +00007900uint32_t
7901EmulateInstructionARM::CurrentCond ()
7902{
7903 switch (m_inst_mode)
7904 {
7905 default:
7906 case eModeInvalid:
7907 break;
7908
7909 case eModeARM:
7910 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
7911
7912 case eModeThumb:
7913 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
7914 // 'cond' field of the encoding.
7915 if (m_inst.opcode_type == eOpcode16 &&
7916 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
7917 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
7918 {
7919 return Bits32(m_inst.opcode.inst16, 11, 7);
7920 }
7921 else if (m_inst.opcode_type == eOpcode32 &&
7922 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
7923 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
7924 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
7925 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
7926 {
7927 return Bits32(m_inst.opcode.inst32, 25, 22);
7928 }
7929
7930 return m_it_session.GetCond();
7931 }
7932 return UINT32_MAX; // Return invalid value
7933}
7934
Johnny Chen9ee056b2011-02-08 00:06:35 +00007935bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00007936EmulateInstructionARM::InITBlock()
7937{
7938 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
7939}
7940
7941bool
7942EmulateInstructionARM::LastInITBlock()
7943{
7944 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
7945}
7946
7947bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00007948EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
7949{
7950 addr_t target;
7951
Johnny Chenee9b1f72011-02-09 01:00:31 +00007952 // Check the current instruction set.
7953 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007954 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007955 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00007956 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00007957
Johnny Chen9ee056b2011-02-08 00:06:35 +00007958 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00007959 return false;
7960
7961 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007962}
7963
7964// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
7965bool
Johnny Chen668b4512011-02-15 21:08:58 +00007966EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00007967{
7968 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00007969 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
7970 // we want to record it and issue a WriteRegister callback so the clients
7971 // can track the mode changes accordingly.
7972 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00007973
7974 if (BitIsSet(addr, 0))
7975 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007976 if (CurrentInstrSet() != eModeThumb)
7977 {
7978 SelectInstrSet(eModeThumb);
7979 cpsr_changed = true;
7980 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007981 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00007982 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007983 }
7984 else if (BitIsClear(addr, 1))
7985 {
Johnny Chen0f309db2011-02-09 19:11:32 +00007986 if (CurrentInstrSet() != eModeARM)
7987 {
7988 SelectInstrSet(eModeARM);
7989 cpsr_changed = true;
7990 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00007991 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00007992 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00007993 }
7994 else
7995 return false; // address<1:0> == '10' => UNPREDICTABLE
7996
Johnny Chen0f309db2011-02-09 19:11:32 +00007997 if (cpsr_changed)
7998 {
Johnny Chen558133b2011-02-09 23:59:17 +00007999 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00008000 return false;
8001 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00008002 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00008003 return false;
8004
8005 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00008006}
Greg Clayton64c84432011-01-21 22:02:52 +00008007
Johnny Chenee9b1f72011-02-09 01:00:31 +00008008// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
8009bool
Johnny Chen668b4512011-02-15 21:08:58 +00008010EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00008011{
8012 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00008013 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00008014 else
8015 return BranchWritePC((const Context)context, addr);
8016}
8017
Johnny Chen26863dc2011-02-09 23:43:29 +00008018// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
8019bool
Johnny Chen668b4512011-02-15 21:08:58 +00008020EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00008021{
8022 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00008023 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00008024 else
8025 return BranchWritePC((const Context)context, addr);
8026}
8027
Johnny Chenee9b1f72011-02-09 01:00:31 +00008028EmulateInstructionARM::Mode
8029EmulateInstructionARM::CurrentInstrSet ()
8030{
8031 return m_inst_mode;
8032}
8033
8034// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00008035// ReadInstruction() is performed. This function has a side effect of updating
8036// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00008037bool
8038EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
8039{
Johnny Chen558133b2011-02-09 23:59:17 +00008040 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00008041 switch (arm_or_thumb)
8042 {
8043 default:
8044 return false;
8045 eModeARM:
8046 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00008047 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00008048 break;
8049 eModeThumb:
8050 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00008051 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00008052 break;
8053 }
8054 return true;
8055}
8056
Johnny Chenef21b592011-02-10 01:52:38 +00008057// This function returns TRUE if the processor currently provides support for
8058// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
8059// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
8060bool
8061EmulateInstructionARM::UnalignedSupport()
8062{
8063 return (ArchVersion() >= ARMv7);
8064}
8065
Johnny Chenbf6ad172011-02-11 01:29:53 +00008066// The main addition and subtraction instructions can produce status information
8067// about both unsigned carry and signed overflow conditions. This status
8068// information can be used to synthesize multi-word additions and subtractions.
8069EmulateInstructionARM::AddWithCarryResult
8070EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
8071{
8072 uint32_t result;
8073 uint8_t carry_out;
8074 uint8_t overflow;
8075
8076 uint64_t unsigned_sum = x + y + carry_in;
8077 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
8078
8079 result = UnsignedBits(unsigned_sum, 31, 0);
8080 carry_out = (result == unsigned_sum ? 0 : 1);
8081 overflow = ((int32_t)result == signed_sum ? 0 : 1);
8082
8083 AddWithCarryResult res = { result, carry_out, overflow };
8084 return res;
8085}
8086
Johnny Chen157b9592011-02-18 21:13:05 +00008087uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00008088EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00008089{
Johnny Chene39f22d2011-02-19 01:36:13 +00008090 uint32_t reg_kind, reg_num;
8091 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00008092 {
Johnny Chene39f22d2011-02-19 01:36:13 +00008093 case SP_REG:
8094 reg_kind = eRegisterKindGeneric;
8095 reg_num = LLDB_REGNUM_GENERIC_SP;
8096 break;
8097 case LR_REG:
8098 reg_kind = eRegisterKindGeneric;
8099 reg_num = LLDB_REGNUM_GENERIC_RA;
8100 break;
8101 case PC_REG:
8102 reg_kind = eRegisterKindGeneric;
8103 reg_num = LLDB_REGNUM_GENERIC_PC;
8104 break;
8105 default:
8106 if (0 <= num && num < SP_REG)
8107 {
8108 reg_kind = eRegisterKindDWARF;
8109 reg_num = dwarf_r0 + num;
8110 }
Johnny Chen157b9592011-02-18 21:13:05 +00008111 else
Johnny Chene39f22d2011-02-19 01:36:13 +00008112 {
8113 assert(0 && "Invalid register number");
8114 *success = false;
8115 return ~0u;
8116 }
8117 break;
Johnny Chen157b9592011-02-18 21:13:05 +00008118 }
Johnny Chene39f22d2011-02-19 01:36:13 +00008119
8120 // Read our register.
8121 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
8122
8123 // When executing an ARM instruction , PC reads as the address of the current
8124 // instruction plus 8.
8125 // When executing a Thumb instruction , PC reads as the address of the current
8126 // instruction plus 4.
8127 if (num == 15)
8128 {
8129 if (CurrentInstrSet() == eModeARM)
8130 val += 8;
8131 else
8132 val += 4;
8133 }
Johnny Chen157b9592011-02-18 21:13:05 +00008134
8135 return val;
8136}
8137
Johnny Chenca67d1c2011-02-17 01:35:27 +00008138// Write the result to the ARM core register Rd, and optionally update the
8139// condition flags based on the result.
8140//
8141// This helper method tries to encapsulate the following pseudocode from the
8142// ARM Architecture Reference Manual:
8143//
8144// if d == 15 then // Can only occur for encoding A1
8145// ALUWritePC(result); // setflags is always FALSE here
8146// else
8147// R[d] = result;
8148// if setflags then
8149// APSR.N = result<31>;
8150// APSR.Z = IsZeroBit(result);
8151// APSR.C = carry;
8152// // APSR.V unchanged
8153//
8154// In the above case, the API client does not pass in the overflow arg, which
8155// defaults to ~0u.
8156bool
Johnny Chen10530c22011-02-17 22:37:12 +00008157EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
8158 const uint32_t result,
8159 const uint32_t Rd,
8160 bool setflags,
8161 const uint32_t carry,
8162 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00008163{
8164 if (Rd == 15)
8165 {
8166 if (!ALUWritePC (context, result))
8167 return false;
8168 }
8169 else
8170 {
Johnny Chena695f952011-02-23 21:24:25 +00008171 uint32_t reg_kind, reg_num;
8172 switch (Rd)
8173 {
8174 case SP_REG:
8175 reg_kind = eRegisterKindGeneric;
8176 reg_num = LLDB_REGNUM_GENERIC_SP;
8177 break;
8178 case LR_REG:
8179 reg_kind = eRegisterKindGeneric;
8180 reg_num = LLDB_REGNUM_GENERIC_RA;
8181 break;
8182 default:
8183 reg_kind = eRegisterKindDWARF;
8184 reg_num = dwarf_r0 + Rd;
8185 }
8186 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +00008187 return false;
8188 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00008189 return WriteFlags (context, result, carry, overflow);
8190 }
8191 return true;
8192}
8193
8194// This helper method tries to encapsulate the following pseudocode from the
8195// ARM Architecture Reference Manual:
8196//
8197// APSR.N = result<31>;
8198// APSR.Z = IsZeroBit(result);
8199// APSR.C = carry;
8200// APSR.V = overflow
8201//
8202// Default arguments can be specified for carry and overflow parameters, which means
8203// not to update the respective flags.
8204bool
8205EmulateInstructionARM::WriteFlags (Context &context,
8206 const uint32_t result,
8207 const uint32_t carry,
8208 const uint32_t overflow)
8209{
8210 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +00008211 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
8212 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +00008213 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00008214 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +00008215 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00008216 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +00008217 if (m_new_inst_cpsr != m_inst_cpsr)
8218 {
8219 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
8220 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00008221 }
8222 return true;
8223}
8224
Greg Clayton64c84432011-01-21 22:02:52 +00008225bool
8226EmulateInstructionARM::EvaluateInstruction ()
8227{
Johnny Chenc315f862011-02-05 00:46:10 +00008228 // Advance the ITSTATE bits to their values for the next instruction.
8229 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
8230 m_it_session.ITAdvance();
8231
Greg Clayton64c84432011-01-21 22:02:52 +00008232 return false;
8233}