blob: d5b788fa238f598d490a0ebf5dacd5611150f2d3 [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
Caroline Tice0e6bc952011-03-01 18:00:42 +00006043
Caroline Tice952b5382011-02-28 23:15:24 +00006044 bool success = false;
6045 const uint32_t opcode = OpcodeAsUnsigned (&success);
6046 if (!success)
6047 return false;
6048
6049 if (ConditionPassed())
6050 {
6051 uint32_t t;
6052 uint32_t imm32;
6053 bool add;
6054
6055 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6056 switch (encoding)
6057 {
6058 case eEncodingT1:
6059 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6060 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6061 t = Bits32 (opcode, 15, 12);
6062 imm32 = Bits32 (opcode, 11, 0);
6063 add = BitIsSet (opcode, 23);
6064
6065 // if t == 13 then UNPREDICTABLE;
6066 if (t == 13)
6067 return false;
6068
6069 break;
6070
6071 case eEncodingA1:
6072 {
6073 uint32_t imm4H = Bits32 (opcode, 11, 8);
6074 uint32_t imm4L = Bits32 (opcode, 3, 0);
6075
6076 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6077 t = Bits32 (opcode, 15, 12);
6078 imm32 = (imm4H << 4) & imm4L;
6079 add = BitIsSet (opcode, 23);
6080
6081 // if t == 15 then UNPREDICTABLE;
6082 if (t == 15)
6083 return false;
6084 break;
6085 }
6086
6087 default:
6088 return false;
6089 }
6090
6091 // base = Align(PC,4);
6092 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
6093 if (!success)
6094 return false;
6095
6096 addr_t base = AlignPC (pc_value);
6097 addr_t address;
6098
6099 // address = if add then (base + imm32) else (base - imm32);
6100 if (add)
6101 address = base + imm32;
6102 else
6103 address = base - imm32;
6104
6105 // data = MemU[address,2];
6106 Register base_reg;
6107 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6108
6109 EmulateInstruction::Context context;
6110 context.type = eContextRegisterLoad;
6111 context.SetRegisterPlusOffset (base_reg, address - base);
6112
6113 uint64_t data = MemURead (context, address, 2, 0, &success);
6114 if (!success)
6115 return false;
6116
6117
6118 // if UnalignedSupport() || address<0> = ’0’ then
6119 if (UnalignedSupport () || BitIsClear (address, 0))
6120 {
6121 // R[t] = ZeroExtend(data, 32);
6122 context.type = eContextRegisterLoad;
6123 context.SetRegisterPlusOffset (base_reg, address - base);
6124 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6125 return false;
6126
6127 }
6128 else // Can only apply before ARMv7
6129 {
6130 // R[t] = bits(32) UNKNOWN;
6131 WriteBits32Unknown (t);
6132 }
6133 }
6134 return true;
6135}
6136
Caroline Tice0e6bc952011-03-01 18:00:42 +00006137// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword
6138// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can
6139// be shifted left by 0, 1, 2, or 3 bits.
6140bool
6141EmulateInstructionARM::EmulateLDRHRegister (ARMEncoding encoding)
6142{
6143#if 0
6144 if ConditionPassed() then
6145 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6146 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6147 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6148 address = if index then offset_addr else R[n];
6149 data = MemU[address,2];
6150 if wback then R[n] = offset_addr;
6151 if UnalignedSupport() || address<0> = ’0’ then
6152 R[t] = ZeroExtend(data, 32);
6153 else // Can only apply before ARMv7
6154 R[t] = bits(32) UNKNOWN;
6155#endif
6156
6157 bool success = false;
6158 const uint32_t opcode = OpcodeAsUnsigned (&success);
6159 if (!success)
6160 return false;
6161
6162 if (ConditionPassed())
6163 {
6164 uint32_t t;
6165 uint32_t n;
6166 uint32_t m;
6167 bool index;
6168 bool add;
6169 bool wback;
6170 ARM_ShifterType shift_t;
6171 uint32_t shift_n;
6172
6173 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6174 switch (encoding)
6175 {
6176 case eEncodingT1:
6177 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
6178 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6179 t = Bits32 (opcode, 2, 0);
6180 n = Bits32 (opcode, 5, 3);
6181 m = Bits32 (opcode, 8, 6);
6182
6183 // index = TRUE; add = TRUE; wback = FALSE;
6184 index = true;
6185 add = true;
6186 wback = false;
6187
6188 // (shift_t, shift_n) = (SRType_LSL, 0);
6189 shift_t = SRType_LSL;
6190 shift_n = 0;
6191
6192 break;
6193
6194 case eEncodingT2:
6195 // if Rn == ’1111’ then SEE LDRH (literal);
6196 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6197 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6198 t = Bits32 (opcode, 15, 12);
6199 n = Bits32 (opcode, 19, 16);
6200 m = Bits32 (opcode, 3, 0);
6201
6202 // index = TRUE; add = TRUE; wback = FALSE;
6203 index = true;
6204 add = true;
6205 wback = false;
6206
6207 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6208 shift_t = SRType_LSL;
6209 shift_n = Bits32 (opcode, 5, 4);
6210
6211 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6212 if ((t == 13) || BadReg (m))
6213 return false;
6214 break;
6215
6216 case eEncodingA1:
6217 // if P == ’0’ && W == ’1’ then SEE LDRHT;
6218 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6219 t = Bits32 (opcode, 15, 12);
6220 n = Bits32 (opcode, 19, 16);
6221 m = Bits32 (opcode, 3, 0);
6222
6223 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6224 index = BitIsSet (opcode, 24);
6225 add = BitIsSet (opcode, 23);
6226 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6227
6228 // (shift_t, shift_n) = (SRType_LSL, 0);
6229 shift_t = SRType_LSL;
6230 shift_n = 0;
6231
6232 // if t == 15 || m == 15 then UNPREDICTABLE;
6233 if ((t == 15) || (m == 15))
6234 return false;
6235
6236 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6237 if (wback && ((n == 15) || (n == t)))
6238 return false;
6239
6240 break;
6241
6242 default:
6243 return false;
6244 }
6245
6246 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6247
6248 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6249 if (!success)
6250 return false;
6251
6252 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6253
6254 addr_t offset_addr;
6255 addr_t address;
6256
6257 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6258 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6259 if (!success)
6260 return false;
6261
6262 if (add)
6263 offset_addr = Rn + offset;
6264 else
6265 offset_addr = Rn - offset;
6266
6267 // address = if index then offset_addr else R[n];
6268 if (index)
6269 address = offset_addr;
6270 else
6271 address = Rn;
6272
6273 // data = MemU[address,2];
6274 Register base_reg;
6275 Register offset_reg;
6276 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6277 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6278
6279 EmulateInstruction::Context context;
6280 context.type = eContextRegisterLoad;
6281 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6282 uint64_t data = MemURead (context, address, 2, 0, &success);
6283 if (!success)
6284 return false;
6285
6286 // if wback then R[n] = offset_addr;
6287 if (wback)
6288 {
6289 context.type = eContextAdjustBaseRegister;
6290 context.SetAddress (offset_addr);
6291 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6292 return false;
6293 }
6294
6295 // if UnalignedSupport() || address<0> = ’0’ then
6296 if (UnalignedSupport() || BitIsClear (address, 0))
6297 {
6298 // R[t] = ZeroExtend(data, 32);
6299 context.type = eContextRegisterLoad;
6300 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6301 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
6302 return false;
6303 }
6304 else // Can only apply before ARMv7
6305 {
6306 // R[t] = bits(32) UNKNOWN;
6307 WriteBits32Unknown (t);
6308 }
6309 }
6310 return true;
6311}
6312
Caroline Ticea5e28af2011-03-01 21:53:03 +00006313// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from
6314// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed,
6315// or pre-indexed addressing.
6316bool
6317EmulateInstructionARM::EmulateLDRSBImmediate (ARMEncoding encoding)
6318{
6319#if 0
6320 if ConditionPassed() then
6321 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6322 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6323 address = if index then offset_addr else R[n];
6324 R[t] = SignExtend(MemU[address,1], 32);
6325 if wback then R[n] = offset_addr;
6326#endif
6327
6328 bool success = false;
6329 const uint32_t opcode = OpcodeAsUnsigned (&success);
6330 if (!success)
6331 return false;
6332
6333 if (ConditionPassed ())
6334 {
6335 uint32_t t;
6336 uint32_t n;
6337 uint32_t imm32;
6338 bool index;
6339 bool add;
6340 bool wback;
6341
6342 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6343 switch (encoding)
6344 {
6345 case eEncodingT1:
6346 // if Rt == ’1111’ then SEE PLI;
6347 // if Rn == ’1111’ then SEE LDRSB (literal);
6348 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6349 t = Bits32 (opcode, 15, 12);
6350 n = Bits32 (opcode, 19, 16);
6351 imm32 = Bits32 (opcode, 11, 0);
6352
6353 // index = TRUE; add = TRUE; wback = FALSE;
6354 index = true;
6355 add = true;
6356 wback = false;
6357
6358 // if t == 13 then UNPREDICTABLE;
6359 if (t == 13)
6360 return false;
6361
6362 break;
6363
6364 case eEncodingT2:
6365 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE PLI;
6366 // if Rn == ’1111’ then SEE LDRSB (literal);
6367 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSBT;
6368 // if P == ’0’ && W == ’0’ then UNDEFINED;
6369 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6370 return false;
6371
6372 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6373 t = Bits32 (opcode, 15, 12);
6374 n = Bits32 (opcode, 19, 16);
6375 imm32 = Bits32 (opcode, 7, 0);
6376
6377 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6378 index = BitIsSet (opcode, 10);
6379 add = BitIsSet (opcode, 9);
6380 wback = BitIsSet (opcode, 8);
6381
6382 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6383 if (BadReg (t) || (wback && (n == t)))
6384 return false;
6385
6386 break;
6387
6388 case eEncodingA1:
6389 {
6390 // if Rn == ’1111’ then SEE LDRSB (literal);
6391 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6392 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6393 t = Bits32 (opcode, 15, 12);
6394 n = Bits32 (opcode, 19, 16);
6395
6396 uint32_t imm4H = Bits32 (opcode, 11, 8);
6397 uint32_t imm4L = Bits32 (opcode, 3, 0);
6398 imm32 = (imm4H << 4) & imm4L;
6399
6400 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6401 index = BitIsSet (opcode, 24);
6402 add = BitIsSet (opcode, 23);
6403 wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
6404
6405 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6406 if ((t == 15) || (wback && (n == t)))
6407 return false;
6408
6409 break;
6410 }
6411
6412 default:
6413 return false;
6414 }
6415
6416 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6417 if (!success)
6418 return false;
6419
6420 addr_t offset_addr;
6421 addr_t address;
6422
6423 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6424 if (add)
6425 offset_addr = Rn + imm32;
6426 else
6427 offset_addr = Rn - imm32;
6428
6429 // address = if index then offset_addr else R[n];
6430 if (index)
6431 address = offset_addr;
6432 else
6433 address = Rn;
6434
6435 // R[t] = SignExtend(MemU[address,1], 32);
6436 Register base_reg;
6437 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6438
6439 EmulateInstruction::Context context;
6440 context.type = eContextRegisterLoad;
6441 context.SetRegisterPlusOffset (base_reg, address - Rn);
6442
6443 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6444 if (!success)
6445 return false;
6446
6447 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6448 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6449 return false;
6450
6451 // if wback then R[n] = offset_addr;
6452 if (wback)
6453 {
6454 context.type = eContextAdjustBaseRegister;
6455 context.SetAddress (offset_addr);
6456 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6457 return false;
6458 }
6459 }
6460
6461 return true;
6462}
Caroline Tice0e6bc952011-03-01 18:00:42 +00006463
Caroline Tice5f593912011-03-01 22:25:17 +00006464// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory,
6465// sign-extends it to form a 32-bit word, and writes tit to a register.
6466bool
6467EmulateInstructionARM::EmulateLDRSBLiteral (ARMEncoding encoding)
6468{
6469#if 0
6470 if ConditionPassed() then
6471 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6472 base = Align(PC,4);
6473 address = if add then (base + imm32) else (base - imm32);
6474 R[t] = SignExtend(MemU[address,1], 32);
6475#endif
6476
6477 bool success = false;
6478 const uint32_t opcode = OpcodeAsUnsigned (&success);
6479 if (!success)
6480 return false;
6481
6482 if (ConditionPassed ())
6483 {
6484 uint32_t t;
6485 uint32_t imm32;
6486 bool add;
6487
6488 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6489 switch (encoding)
6490 {
6491 case eEncodingT1:
6492 // if Rt == ’1111’ then SEE PLI;
6493 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6494 t = Bits32 (opcode, 15, 12);
6495 imm32 = Bits32 (opcode, 11, 0);
6496 add = BitIsSet (opcode, 23);
6497
6498 // if t == 13 then UNPREDICTABLE;
6499 if (t == 13)
6500 return false;
6501
6502 break;
6503
6504 case eEncodingA1:
6505 {
6506 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6507 t = Bits32 (opcode, 15, 12);
6508 uint32_t imm4H = Bits32 (opcode, 11, 8);
6509 uint32_t imm4L = Bits32 (opcode, 3, 0);
6510 imm32 = (imm4H << 4) & imm4L;
6511 add = BitIsSet (opcode, 23);
6512
6513 // if t == 15 then UNPREDICTABLE;
6514 if (t == 15)
6515 return false;
6516
6517 break;
6518 }
6519
6520 default:
6521 return false;
6522 }
6523
6524 // base = Align(PC,4);
6525 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS,
6526 &success);
6527 if (!success)
6528 return false;
6529 uint64_t base = AlignPC (pc_value);
6530
6531 // address = if add then (base + imm32) else (base - imm32);
6532 addr_t address;
6533 if (add)
6534 address = base + imm32;
6535 else
6536 address = base - imm32;
6537
6538 // R[t] = SignExtend(MemU[address,1], 32);
6539 Register base_reg;
6540 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6541
6542 EmulateInstruction::Context context;
6543 context.type = eContextRegisterLoad;
6544 context.SetRegisterPlusOffset (base_reg, address - base);
6545
6546 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6547 if (!success)
6548 return false;
6549
6550 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6551 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6552 return false;
6553 }
6554 return true;
6555}
6556
Caroline Tice672f3112011-03-01 23:55:59 +00006557// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from
6558// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be
6559// shifted left by 0, 1, 2, or 3 bits.
6560bool
6561EmulateInstructionARM::EmulateLDRSBRegister (ARMEncoding encoding)
6562{
6563#if 0
6564 if ConditionPassed() then
6565 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6566 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6567 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6568 address = if index then offset_addr else R[n];
6569 R[t] = SignExtend(MemU[address,1], 32);
6570 if wback then R[n] = offset_addr;
6571#endif
6572
6573 bool success = false;
6574 const uint32_t opcode = OpcodeAsUnsigned (&success);
6575 if (!success)
6576 return false;
6577
6578 if (ConditionPassed ())
6579 {
6580 uint32_t t;
6581 uint32_t n;
6582 uint32_t m;
6583 bool index;
6584 bool add;
6585 bool wback;
6586 ARM_ShifterType shift_t;
6587 uint32_t shift_n;
6588
6589 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6590 switch (encoding)
6591 {
6592 case eEncodingT1:
6593 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6594 t = Bits32 (opcode, 2, 0);
6595 n = Bits32 (opcode, 5, 3);
6596 m = Bits32 (opcode, 8, 6);
6597
6598 // index = TRUE; add = TRUE; wback = FALSE;
6599 index = true;
6600 add = true;
6601 wback = false;
6602
6603 // (shift_t, shift_n) = (SRType_LSL, 0);
6604 shift_t = SRType_LSL;
6605 shift_n = 0;
6606
6607 break;
6608
6609 case eEncodingT2:
6610 // if Rt == ’1111’ then SEE PLI;
6611 // if Rn == ’1111’ then SEE LDRSB (literal);
6612 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6613 t = Bits32 (opcode, 15, 12);
6614 n = Bits32 (opcode, 19, 16);
6615 m = Bits32 (opcode, 3, 0);
6616
6617 // index = TRUE; add = TRUE; wback = FALSE;
6618 index = true;
6619 add = true;
6620 wback = false;
6621
6622 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6623 shift_t = SRType_LSL;
6624 shift_n = Bits32 (opcode, 5, 4);
6625
6626 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6627 if ((t == 13) || BadReg (m))
6628 return false;
6629 break;
6630
6631 case eEncodingA1:
6632 // if P == ’0’ && W == ’1’ then SEE LDRSBT;
6633 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6634 t = Bits32 (opcode, 15, 12);
6635 n = Bits32 (opcode, 19, 16);
6636 m = Bits32 (opcode, 3, 0);
6637
6638 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6639 index = BitIsSet (opcode, 24);
6640 add = BitIsSet (opcode, 23);
6641 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
6642
6643 // (shift_t, shift_n) = (SRType_LSL, 0);
6644 shift_t = SRType_LSL;
6645 shift_n = 0;
6646
6647 // if t == 15 || m == 15 then UNPREDICTABLE;
6648 if ((t == 15) || (m == 15))
6649 return false;
6650
6651 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6652 if (wback && ((n == 15) || (n == t)))
6653 return false;
6654 break;
6655
6656 default:
6657 return false;
6658 }
6659
6660 uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6661 if (!success)
6662 return false;
6663
6664 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
6665 addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C);
6666
6667 addr_t offset_addr;
6668 addr_t address;
6669
6670 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6671 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6672 if (!success)
6673 return false;
6674
6675 if (add)
6676 offset_addr = Rn + offset;
6677 else
6678 offset_addr = Rn - offset;
6679
6680 // address = if index then offset_addr else R[n];
6681 if (index)
6682 address = offset_addr;
6683 else
6684 address = Rn;
6685
6686 // R[t] = SignExtend(MemU[address,1], 32);
6687 Register base_reg;
6688 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6689 Register offset_reg;
6690 offset_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + m);
6691
6692 EmulateInstruction::Context context;
6693 context.type = eContextRegisterLoad;
6694 context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
6695
6696 uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
6697 if (!success)
6698 return false;
6699
6700 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
6701 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6702 return false;
6703
6704 // if wback then R[n] = offset_addr;
6705 if (wback)
6706 {
6707 context.type = eContextAdjustBaseRegister;
6708 context.SetAddress (offset_addr);
6709 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6710 return false;
6711 }
6712 }
6713 return true;
6714}
6715
Caroline Tice78fb5632011-03-02 00:39:42 +00006716// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from
6717// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or
6718// pre-indexed addressing.
6719bool
6720EmulateInstructionARM::EmulateLDRSHImmediate (ARMEncoding encoding)
6721{
6722#if 0
6723 if ConditionPassed() then
6724 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6725 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6726 address = if index then offset_addr else R[n];
6727 data = MemU[address,2];
6728 if wback then R[n] = offset_addr;
6729 if UnalignedSupport() || address<0> = ’0’ then
6730 R[t] = SignExtend(data, 32);
6731 else // Can only apply before ARMv7
6732 R[t] = bits(32) UNKNOWN;
6733#endif
6734
6735 bool success = false;
6736 const uint32_t opcode = OpcodeAsUnsigned (&success);
6737 if (!success)
6738 return false;
6739
6740 if (ConditionPassed())
6741 {
6742 uint32_t t;
6743 uint32_t n;
6744 uint32_t imm32;
6745 bool index;
6746 bool add;
6747 bool wback;
6748
6749 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6750 switch (encoding)
6751 {
6752 case eEncodingT1:
6753 // if Rn == ’1111’ then SEE LDRSH (literal);
6754 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6755 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6756 t = Bits32 (opcode, 15, 12);
6757 n = Bits32 (opcode, 19, 16);
6758 imm32 = Bits32 (opcode, 11, 0);
6759
6760 // index = TRUE; add = TRUE; wback = FALSE;
6761 index = true;
6762 add = true;
6763 wback = false;
6764
6765 // if t == 13 then UNPREDICTABLE;
6766 if (t == 13)
6767 return false;
6768
6769 break;
6770
6771 case eEncodingT2:
6772 // if Rn == ’1111’ then SEE LDRSH (literal);
6773 // if Rt == ’1111’ && P == ’1’ && U == ’0’ && W == ’0’ then SEE "Unallocated memory hints";
6774 // if P == ’1’ && U == ’1’ && W == ’0’ then SEE LDRSHT;
6775 // if P == ’0’ && W == ’0’ then UNDEFINED;
6776 if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
6777 return false;
6778
6779 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6780 t = Bits32 (opcode, 15, 12);
6781 n = Bits32 (opcode, 19, 16);
6782 imm32 = Bits32 (opcode, 7, 0);
6783
6784 // index = (P == ’1’); add = (U == ’1’); wback = (W == ’1’);
6785 index = BitIsSet (opcode, 10);
6786 add = BitIsSet (opcode, 9);
6787 wback = BitIsSet (opcode, 8);
6788
6789 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6790 if (BadReg (t) || (wback && (n == t)))
6791 return false;
6792
6793 break;
6794
6795 case eEncodingA1:
6796 {
6797 // if Rn == ’1111’ then SEE LDRSH (literal);
6798 // if P == ’0’ && W == ’1’ then SEE LDRSHT;
6799 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
6800 t = Bits32 (opcode, 15, 12);
6801 n = Bits32 (opcode, 19, 16);
6802 uint32_t imm4H = Bits32 (opcode, 11,8);
6803 uint32_t imm4L = Bits32 (opcode, 3, 0);
6804 imm32 = (imm4H << 4) & imm4L;
6805
6806 // index = (P == ’1’); add = (U == ’1’); wback = (P == ’0’) || (W == ’1’);
6807 index = BitIsSet (opcode, 24);
6808 add = BitIsSet (opcode, 23);
6809 wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
6810
6811 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
6812 if ((t == 15) || (wback && (n == t)))
6813 return false;
6814
6815 break;
6816 }
6817
6818 default:
6819 return false;
6820 }
6821
6822 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6823 uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6824 if (!success)
6825 return false;
6826
6827 addr_t offset_addr;
6828 if (add)
6829 offset_addr = Rn + imm32;
6830 else
6831 offset_addr = Rn - imm32;
6832
6833 // address = if index then offset_addr else R[n];
6834 addr_t address;
6835 if (index)
6836 address = offset_addr;
6837 else
6838 address = Rn;
6839
6840 // data = MemU[address,2];
6841 Register base_reg;
6842 base_reg.SetRegister (eRegisterKindDWARF, dwarf_r0 + n);
6843
6844 EmulateInstruction::Context context;
6845 context.type = eContextRegisterLoad;
6846 context.SetRegisterPlusOffset (base_reg, address - Rn);
6847
6848 uint64_t data = MemURead (context, address, 2, 0, &success);
6849 if (!success)
6850 return false;
6851
6852 // if wback then R[n] = offset_addr;
6853 if (wback)
6854 {
6855 context.type = eContextAdjustBaseRegister;
6856 context.SetAddress (offset_addr);
6857 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
6858 return false;
6859 }
6860
6861 // if UnalignedSupport() || address<0> = ’0’ then
6862 if (UnalignedSupport() || BitIsClear (address, 0))
6863 {
6864 // R[t] = SignExtend(data, 32);
6865 int64_t signed_data = llvm::SignExtend64<16>(data);
6866 context.type = eContextRegisterLoad;
6867 context.SetRegisterPlusOffset (base_reg, address - Rn);
6868 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6869 return false;
6870 }
6871 else // Can only apply before ARMv7
6872 {
6873 // R[t] = bits(32) UNKNOWN;
6874 WriteBits32Unknown (t);
6875 }
6876 }
6877 return true;
6878}
6879
Caroline Ticed2fac092011-03-02 19:45:34 +00006880// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory,
6881// sign-extends it to from a 32-bit word, and writes it to a register.
6882bool
6883EmulateInstructionARM::EmulateLDRSHLiteral (ARMEncoding encoding)
6884{
6885#if 0
6886 if ConditionPassed() then
6887 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6888 base = Align(PC,4);
6889 address = if add then (base + imm32) else (base - imm32);
6890 data = MemU[address,2];
6891 if UnalignedSupport() || address<0> = ’0’ then
6892 R[t] = SignExtend(data, 32);
6893 else // Can only apply before ARMv7
6894 R[t] = bits(32) UNKNOWN;
6895#endif
6896
6897 bool success = false;
6898 const uint32_t opcode = OpcodeAsUnsigned (&success);
6899 if (!success)
6900 return false;
6901
6902 if (ConditionPassed())
6903 {
6904 uint32_t t;
6905 uint32_t imm32;
6906 bool add;
6907
6908 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6909 switch (encoding)
6910 {
6911 case eEncodingT1:
6912 // if Rt == ’1111’ then SEE "Unallocated memory hints";
6913 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == ’1’);
6914 t = Bits32 (opcode, 15, 12);
6915 imm32 = Bits32 (opcode, 11, 0);
6916 add = BitIsSet (opcode, 23);
6917
6918 // if t == 13 then UNPREDICTABLE;
6919 if (t == 13)
6920 return false;
6921
6922 break;
6923
6924 case eEncodingA1:
6925 {
6926 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == ’1’);
6927 t = Bits32 (opcode, 15, 12);
6928 uint32_t imm4H = Bits32 (opcode, 11, 8);
6929 uint32_t imm4L = Bits32 (opcode, 3, 0);
6930 imm32 = (imm4H << 4) & imm4L;
6931 add = BitIsSet (opcode, 23);
6932
6933 // if t == 15 then UNPREDICTABLE;
6934 if (t == 15)
6935 return false;
6936
6937 break;
6938 }
6939 default:
6940 return false;
6941 }
6942
6943 // base = Align(PC,4);
6944 uint64_t pc_value = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
6945 if (!success)
6946 return false;
6947
6948 uint64_t base = AlignPC (pc_value);
6949
6950 addr_t address;
6951 // address = if add then (base + imm32) else (base - imm32);
6952 if (add)
6953 address = base + imm32;
6954 else
6955 address = base - imm32;
6956
6957 // data = MemU[address,2];
6958 Register base_reg;
6959 base_reg.SetRegister (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
6960
6961 EmulateInstruction::Context context;
6962 context.type = eContextRegisterLoad;
6963 context.SetRegisterPlusOffset (base_reg, imm32);
6964
6965 uint64_t data = MemURead (context, address, 2, 0, &success);
6966 if (!success)
6967 return false;
6968
6969 // if UnalignedSupport() || address<0> = ’0’ then
6970 if (UnalignedSupport() || BitIsClear (address, 0))
6971 {
6972 // R[t] = SignExtend(data, 32);
6973 int64_t signed_data = llvm::SignExtend64<16>(data);
6974 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
6975 return false;
6976 }
6977 else // Can only apply before ARMv7
6978 {
6979 // R[t] = bits(32) UNKNOWN;
6980 WriteBits32Unknown (t);
6981 }
6982 }
6983 return true;
6984}
6985
Johnny Chen2115b412011-02-21 23:42:44 +00006986// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
6987// and writes the result to the destination register. It can optionally update the condition flags based on
6988// the result.
6989bool
6990EmulateInstructionARM::EmulateEORImm (ARMEncoding encoding)
6991{
6992#if 0
6993 // ARM pseudo code...
6994 if ConditionPassed() then
6995 EncodingSpecificOperations();
6996 result = R[n] EOR imm32;
6997 if d == 15 then // Can only occur for ARM encoding
6998 ALUWritePC(result); // setflags is always FALSE here
6999 else
7000 R[d] = result;
7001 if setflags then
7002 APSR.N = result<31>;
7003 APSR.Z = IsZeroBit(result);
7004 APSR.C = carry;
7005 // APSR.V unchanged
7006#endif
7007
7008 bool success = false;
7009 const uint32_t opcode = OpcodeAsUnsigned (&success);
7010 if (!success)
7011 return false;
7012
7013 if (ConditionPassed())
7014 {
7015 uint32_t Rd, Rn;
7016 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7017 bool setflags;
7018 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7019 switch (encoding)
7020 {
7021 case eEncodingT1:
7022 Rd = Bits32(opcode, 11, 8);
7023 Rn = Bits32(opcode, 19, 16);
7024 setflags = BitIsSet(opcode, 20);
7025 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7026 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
7027 if (Rd == 15 && setflags)
7028 return EmulateTEQImm(eEncodingT1);
7029 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
7030 return false;
7031 break;
7032 case eEncodingA1:
7033 Rd = Bits32(opcode, 15, 12);
7034 Rn = Bits32(opcode, 19, 16);
7035 setflags = BitIsSet(opcode, 20);
7036 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7037 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7038 // TODO: Emulate SUBS PC, LR and related instructions.
7039 if (Rd == 15 && setflags)
7040 return false;
7041 break;
7042 default:
7043 return false;
7044 }
7045
7046 // Read the first operand.
7047 uint32_t val1 = ReadCoreReg(Rn, &success);
7048 if (!success)
7049 return false;
7050
7051 uint32_t result = val1 ^ imm32;
7052
7053 EmulateInstruction::Context context;
7054 context.type = EmulateInstruction::eContextImmediate;
7055 context.SetNoArgs ();
7056
7057 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7058 return false;
7059 }
7060 return true;
7061}
7062
7063// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
7064// optionally-shifted register value, and writes the result to the destination register.
7065// It can optionally update the condition flags based on the result.
7066bool
7067EmulateInstructionARM::EmulateEORReg (ARMEncoding encoding)
7068{
7069#if 0
7070 // ARM pseudo code...
7071 if ConditionPassed() then
7072 EncodingSpecificOperations();
7073 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7074 result = R[n] EOR shifted;
7075 if d == 15 then // Can only occur for ARM encoding
7076 ALUWritePC(result); // setflags is always FALSE here
7077 else
7078 R[d] = result;
7079 if setflags then
7080 APSR.N = result<31>;
7081 APSR.Z = IsZeroBit(result);
7082 APSR.C = carry;
7083 // APSR.V unchanged
7084#endif
7085
7086 bool success = false;
7087 const uint32_t opcode = OpcodeAsUnsigned (&success);
7088 if (!success)
7089 return false;
7090
7091 if (ConditionPassed())
7092 {
7093 uint32_t Rd, Rn, Rm;
7094 ARM_ShifterType shift_t;
7095 uint32_t shift_n; // the shift applied to the value read from Rm
7096 bool setflags;
7097 uint32_t carry;
7098 switch (encoding)
7099 {
7100 case eEncodingT1:
7101 Rd = Rn = Bits32(opcode, 2, 0);
7102 Rm = Bits32(opcode, 5, 3);
7103 setflags = !InITBlock();
7104 shift_t = SRType_LSL;
7105 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007106 break;
Johnny Chen2115b412011-02-21 23:42:44 +00007107 case eEncodingT2:
7108 Rd = Bits32(opcode, 11, 8);
7109 Rn = Bits32(opcode, 19, 16);
7110 Rm = Bits32(opcode, 3, 0);
7111 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007112 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7113 // if Rd == '1111' && S == '1' then SEE TEQ (register);
Johnny Chen2115b412011-02-21 23:42:44 +00007114 if (Rd == 15 && setflags)
7115 return EmulateTEQReg(eEncodingT1);
7116 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
7117 return false;
7118 break;
7119 case eEncodingA1:
7120 Rd = Bits32(opcode, 15, 12);
7121 Rn = Bits32(opcode, 19, 16);
7122 Rm = Bits32(opcode, 3, 0);
7123 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007124 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00007125 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7126 // TODO: Emulate SUBS PC, LR and related instructions.
7127 if (Rd == 15 && setflags)
7128 return false;
7129 break;
7130 default:
7131 return false;
7132 }
7133
7134 // Read the first operand.
7135 uint32_t val1 = ReadCoreReg(Rn, &success);
7136 if (!success)
7137 return false;
7138
7139 // Read the second operand.
7140 uint32_t val2 = ReadCoreReg(Rm, &success);
7141 if (!success)
7142 return false;
7143
7144 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
7145 uint32_t result = val1 ^ shifted;
7146
7147 EmulateInstruction::Context context;
7148 context.type = EmulateInstruction::eContextImmediate;
7149 context.SetNoArgs ();
7150
7151 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7152 return false;
7153 }
7154 return true;
7155}
7156
Johnny Chen7c5234d2011-02-18 23:41:11 +00007157// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
7158// writes the result to the destination register. It can optionally update the condition flags based
7159// on the result.
7160bool
7161EmulateInstructionARM::EmulateORRImm (ARMEncoding encoding)
7162{
7163#if 0
7164 // ARM pseudo code...
7165 if ConditionPassed() then
7166 EncodingSpecificOperations();
7167 result = R[n] OR imm32;
7168 if d == 15 then // Can only occur for ARM encoding
7169 ALUWritePC(result); // setflags is always FALSE here
7170 else
7171 R[d] = result;
7172 if setflags then
7173 APSR.N = result<31>;
7174 APSR.Z = IsZeroBit(result);
7175 APSR.C = carry;
7176 // APSR.V unchanged
7177#endif
7178
7179 bool success = false;
7180 const uint32_t opcode = OpcodeAsUnsigned (&success);
7181 if (!success)
7182 return false;
7183
7184 if (ConditionPassed())
7185 {
7186 uint32_t Rd, Rn;
7187 uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
7188 bool setflags;
7189 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7190 switch (encoding)
7191 {
7192 case eEncodingT1:
7193 Rd = Bits32(opcode, 11, 8);
7194 Rn = Bits32(opcode, 19, 16);
7195 setflags = BitIsSet(opcode, 20);
7196 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7197 // if Rn == ‘1111’ then SEE MOV (immediate);
7198 if (Rn == 15)
7199 return EmulateMOVRdImm(eEncodingT2);
7200 if (BadReg(Rd) || Rn == 13)
7201 return false;
7202 break;
7203 case eEncodingA1:
7204 Rd = Bits32(opcode, 15, 12);
7205 Rn = Bits32(opcode, 19, 16);
7206 setflags = BitIsSet(opcode, 20);
7207 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7208 // TODO: Emulate SUBS PC, LR and related instructions.
7209 if (Rd == 15 && setflags)
7210 return false;
7211 break;
7212 default:
7213 return false;
7214 }
7215
7216 // Read the first operand.
7217 uint32_t val1 = ReadCoreReg(Rn, &success);
7218 if (!success)
7219 return false;
7220
7221 uint32_t result = val1 | imm32;
7222
7223 EmulateInstruction::Context context;
7224 context.type = EmulateInstruction::eContextImmediate;
7225 context.SetNoArgs ();
7226
7227 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7228 return false;
7229 }
7230 return true;
7231}
7232
7233// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
7234// value, and writes the result to the destination register. It can optionally update the condition flags based
7235// on the result.
7236bool
7237EmulateInstructionARM::EmulateORRReg (ARMEncoding encoding)
7238{
7239#if 0
7240 // ARM pseudo code...
7241 if ConditionPassed() then
7242 EncodingSpecificOperations();
7243 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
7244 result = R[n] OR shifted;
7245 if d == 15 then // Can only occur for ARM encoding
7246 ALUWritePC(result); // setflags is always FALSE here
7247 else
7248 R[d] = result;
7249 if setflags then
7250 APSR.N = result<31>;
7251 APSR.Z = IsZeroBit(result);
7252 APSR.C = carry;
7253 // APSR.V unchanged
7254#endif
7255
7256 bool success = false;
7257 const uint32_t opcode = OpcodeAsUnsigned (&success);
7258 if (!success)
7259 return false;
7260
7261 if (ConditionPassed())
7262 {
7263 uint32_t Rd, Rn, Rm;
7264 ARM_ShifterType shift_t;
7265 uint32_t shift_n; // the shift applied to the value read from Rm
7266 bool setflags;
7267 uint32_t carry;
7268 switch (encoding)
7269 {
7270 case eEncodingT1:
7271 Rd = Rn = Bits32(opcode, 2, 0);
7272 Rm = Bits32(opcode, 5, 3);
7273 setflags = !InITBlock();
7274 shift_t = SRType_LSL;
7275 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00007276 break;
Johnny Chen7c5234d2011-02-18 23:41:11 +00007277 case eEncodingT2:
7278 Rd = Bits32(opcode, 11, 8);
7279 Rn = Bits32(opcode, 19, 16);
7280 Rm = Bits32(opcode, 3, 0);
7281 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007282 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7283 // if Rn == '1111' then SEE MOV (register);
Johnny Chen7c5234d2011-02-18 23:41:11 +00007284 if (Rn == 15)
7285 return EmulateMOVRdRm(eEncodingT3);
7286 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
7287 return false;
7288 break;
7289 case eEncodingA1:
7290 Rd = Bits32(opcode, 15, 12);
7291 Rn = Bits32(opcode, 19, 16);
7292 Rm = Bits32(opcode, 3, 0);
7293 setflags = BitIsSet(opcode, 20);
Johnny Chen3dd06052011-02-22 21:17:52 +00007294 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen7c5234d2011-02-18 23:41:11 +00007295 // TODO: Emulate SUBS PC, LR and related instructions.
7296 if (Rd == 15 && setflags)
7297 return false;
7298 break;
7299 default:
7300 return false;
7301 }
7302
7303 // Read the first operand.
7304 uint32_t val1 = ReadCoreReg(Rn, &success);
7305 if (!success)
7306 return false;
7307
7308 // Read the second operand.
7309 uint32_t val2 = ReadCoreReg(Rm, &success);
7310 if (!success)
7311 return false;
7312
7313 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
Johnny Chen2115b412011-02-21 23:42:44 +00007314 uint32_t result = val1 | shifted;
Johnny Chen7c5234d2011-02-18 23:41:11 +00007315
7316 EmulateInstruction::Context context;
7317 context.type = EmulateInstruction::eContextImmediate;
7318 context.SetNoArgs ();
7319
7320 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
7321 return false;
7322 }
7323 return true;
7324}
7325
Johnny Chened32e7c2011-02-22 23:42:58 +00007326// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
7327// the destination register. It can optionally update the condition flags based on the result.
7328bool
7329EmulateInstructionARM::EmulateRSBImm (ARMEncoding encoding)
7330{
7331#if 0
7332 // ARM pseudo code...
7333 if ConditionPassed() then
7334 EncodingSpecificOperations();
7335 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
7336 if d == 15 then // Can only occur for ARM encoding
7337 ALUWritePC(result); // setflags is always FALSE here
7338 else
7339 R[d] = result;
7340 if setflags then
7341 APSR.N = result<31>;
7342 APSR.Z = IsZeroBit(result);
7343 APSR.C = carry;
7344 APSR.V = overflow;
7345#endif
7346
7347 bool success = false;
7348 const uint32_t opcode = OpcodeAsUnsigned (&success);
7349 if (!success)
7350 return false;
7351
7352 uint32_t Rd; // the destination register
7353 uint32_t Rn; // the first operand
7354 bool setflags;
7355 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
7356 switch (encoding) {
7357 case eEncodingT1:
7358 Rd = Bits32(opcode, 2, 0);
7359 Rn = Bits32(opcode, 5, 3);
7360 setflags = !InITBlock();
7361 imm32 = 0;
7362 break;
7363 case eEncodingT2:
7364 Rd = Bits32(opcode, 11, 8);
7365 Rn = Bits32(opcode, 19, 16);
7366 setflags = BitIsSet(opcode, 20);
7367 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
7368 if (BadReg(Rd) || BadReg(Rn))
7369 return false;
7370 break;
7371 case eEncodingA1:
7372 Rd = Bits32(opcode, 15, 12);
7373 Rn = Bits32(opcode, 19, 16);
7374 setflags = BitIsSet(opcode, 20);
7375 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7376 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7377 // TODO: Emulate SUBS PC, LR and related instructions.
7378 if (Rd == 15 && setflags)
7379 return false;
7380 break;
7381 default:
7382 return false;
7383 }
7384 // Read the register value from the operand register Rn.
7385 uint32_t reg_val = ReadCoreReg(Rn, &success);
7386 if (!success)
7387 return false;
7388
7389 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
7390
7391 EmulateInstruction::Context context;
7392 context.type = EmulateInstruction::eContextImmediate;
7393 context.SetNoArgs ();
7394
7395 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7396 return false;
7397
7398 return true;
7399}
7400
7401// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
7402// result to the destination register. It can optionally update the condition flags based on the result.
7403bool
7404EmulateInstructionARM::EmulateRSBReg (ARMEncoding encoding)
7405{
7406#if 0
7407 // ARM pseudo code...
7408 if ConditionPassed() then
7409 EncodingSpecificOperations();
7410 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
7411 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
7412 if d == 15 then // Can only occur for ARM encoding
7413 ALUWritePC(result); // setflags is always FALSE here
7414 else
7415 R[d] = result;
7416 if setflags then
7417 APSR.N = result<31>;
7418 APSR.Z = IsZeroBit(result);
7419 APSR.C = carry;
7420 APSR.V = overflow;
7421#endif
7422
7423 bool success = false;
7424 const uint32_t opcode = OpcodeAsUnsigned (&success);
7425 if (!success)
7426 return false;
7427
7428 uint32_t Rd; // the destination register
7429 uint32_t Rn; // the first operand
7430 uint32_t Rm; // the second operand
7431 bool setflags;
7432 ARM_ShifterType shift_t;
7433 uint32_t shift_n; // the shift applied to the value read from Rm
7434 switch (encoding) {
7435 case eEncodingT1:
7436 Rd = Bits32(opcode, 11, 8);
7437 Rn = Bits32(opcode, 19, 16);
7438 Rm = Bits32(opcode, 3, 0);
7439 setflags = BitIsSet(opcode, 20);
7440 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7441 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
7442 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
7443 return false;
7444 break;
7445 case eEncodingA1:
7446 Rd = Bits32(opcode, 15, 12);
7447 Rn = Bits32(opcode, 19, 16);
7448 Rm = Bits32(opcode, 3, 0);
7449 setflags = BitIsSet(opcode, 20);
7450 shift_n = DecodeImmShiftARM(opcode, shift_t);
7451 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7452 // TODO: Emulate SUBS PC, LR and related instructions.
7453 if (Rd == 15 && setflags)
7454 return false;
7455 break;
7456 default:
7457 return false;
7458 }
7459 // Read the register value from register Rn.
7460 uint32_t val1 = ReadCoreReg(Rn, &success);
7461 if (!success)
7462 return false;
7463
7464 // Read the register value from register Rm.
7465 uint32_t val2 = ReadCoreReg(Rm, &success);
7466 if (!success)
7467 return false;
7468
7469 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
7470 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
7471
7472 EmulateInstruction::Context context;
7473 context.type = EmulateInstruction::eContextImmediate;
7474 context.SetNoArgs();
7475 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7476 return false;
7477
7478 return true;
7479}
7480
Johnny Chen90e607b2011-02-23 00:07:09 +00007481// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
7482// an immediate value, and writes the result to the destination register. It can optionally update the condition
7483// flags based on the result.
7484bool
7485EmulateInstructionARM::EmulateRSCImm (ARMEncoding encoding)
7486{
7487#if 0
7488 // ARM pseudo code...
7489 if ConditionPassed() then
7490 EncodingSpecificOperations();
7491 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
7492 if d == 15 then
7493 ALUWritePC(result); // setflags is always FALSE here
7494 else
7495 R[d] = result;
7496 if setflags then
7497 APSR.N = result<31>;
7498 APSR.Z = IsZeroBit(result);
7499 APSR.C = carry;
7500 APSR.V = overflow;
7501#endif
7502
7503 bool success = false;
7504 const uint32_t opcode = OpcodeAsUnsigned (&success);
7505 if (!success)
7506 return false;
7507
7508 uint32_t Rd; // the destination register
7509 uint32_t Rn; // the first operand
7510 bool setflags;
7511 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
7512 switch (encoding) {
7513 case eEncodingA1:
7514 Rd = Bits32(opcode, 15, 12);
7515 Rn = Bits32(opcode, 19, 16);
7516 setflags = BitIsSet(opcode, 20);
7517 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7518 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7519 // TODO: Emulate SUBS PC, LR and related instructions.
7520 if (Rd == 15 && setflags)
7521 return false;
7522 break;
7523 default:
7524 return false;
7525 }
7526 // Read the register value from the operand register Rn.
7527 uint32_t reg_val = ReadCoreReg(Rn, &success);
7528 if (!success)
7529 return false;
7530
7531 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
7532
7533 EmulateInstruction::Context context;
7534 context.type = EmulateInstruction::eContextImmediate;
7535 context.SetNoArgs ();
7536
7537 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7538 return false;
7539
7540 return true;
7541}
7542
7543// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
7544// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
7545// condition flags based on the result.
7546bool
7547EmulateInstructionARM::EmulateRSCReg (ARMEncoding encoding)
7548{
7549#if 0
7550 // ARM pseudo code...
7551 if ConditionPassed() then
7552 EncodingSpecificOperations();
7553 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
7554 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
7555 if d == 15 then
7556 ALUWritePC(result); // setflags is always FALSE here
7557 else
7558 R[d] = result;
7559 if setflags then
7560 APSR.N = result<31>;
7561 APSR.Z = IsZeroBit(result);
7562 APSR.C = carry;
7563 APSR.V = overflow;
7564#endif
7565
7566 bool success = false;
7567 const uint32_t opcode = OpcodeAsUnsigned (&success);
7568 if (!success)
7569 return false;
7570
7571 uint32_t Rd; // the destination register
7572 uint32_t Rn; // the first operand
7573 uint32_t Rm; // the second operand
7574 bool setflags;
7575 ARM_ShifterType shift_t;
7576 uint32_t shift_n; // the shift applied to the value read from Rm
7577 switch (encoding) {
7578 case eEncodingA1:
7579 Rd = Bits32(opcode, 15, 12);
7580 Rn = Bits32(opcode, 19, 16);
7581 Rm = Bits32(opcode, 3, 0);
7582 setflags = BitIsSet(opcode, 20);
7583 shift_n = DecodeImmShiftARM(opcode, shift_t);
7584 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7585 // TODO: Emulate SUBS PC, LR and related instructions.
7586 if (Rd == 15 && setflags)
7587 return false;
7588 break;
7589 default:
7590 return false;
7591 }
7592 // Read the register value from register Rn.
7593 uint32_t val1 = ReadCoreReg(Rn, &success);
7594 if (!success)
7595 return false;
7596
7597 // Read the register value from register Rm.
7598 uint32_t val2 = ReadCoreReg(Rm, &success);
7599 if (!success)
7600 return false;
7601
7602 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
7603 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
7604
7605 EmulateInstruction::Context context;
7606 context.type = EmulateInstruction::eContextImmediate;
7607 context.SetNoArgs();
7608 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7609 return false;
7610
7611 return true;
7612}
7613
Johnny Chen9b381772011-02-23 01:01:21 +00007614// Subtract with Carry (immediate) subtracts an immediate value and the value of
7615// NOT (Carry flag) from a register value, and writes the result to the destination register.
7616// It can optionally update the condition flags based on the result.
7617bool
7618EmulateInstructionARM::EmulateSBCImm (ARMEncoding encoding)
7619{
7620#if 0
7621 // ARM pseudo code...
7622 if ConditionPassed() then
7623 EncodingSpecificOperations();
Johnny Chen15a7a6b2011-02-23 23:47:56 +00007624 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
Johnny Chen9b381772011-02-23 01:01:21 +00007625 if d == 15 then // Can only occur for ARM encoding
7626 ALUWritePC(result); // setflags is always FALSE here
7627 else
7628 R[d] = result;
7629 if setflags then
7630 APSR.N = result<31>;
7631 APSR.Z = IsZeroBit(result);
7632 APSR.C = carry;
7633 APSR.V = overflow;
7634#endif
7635
7636 bool success = false;
7637 const uint32_t opcode = OpcodeAsUnsigned (&success);
7638 if (!success)
7639 return false;
7640
7641 uint32_t Rd; // the destination register
7642 uint32_t Rn; // the first operand
7643 bool setflags;
7644 uint32_t imm32; // the immediate value to be added to the value obtained from Rn
7645 switch (encoding) {
7646 case eEncodingT1:
7647 Rd = Bits32(opcode, 11, 8);
7648 Rn = Bits32(opcode, 19, 16);
7649 setflags = BitIsSet(opcode, 20);
7650 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
7651 if (BadReg(Rd) || BadReg(Rn))
7652 return false;
7653 break;
7654 case eEncodingA1:
7655 Rd = Bits32(opcode, 15, 12);
7656 Rn = Bits32(opcode, 19, 16);
7657 setflags = BitIsSet(opcode, 20);
7658 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7659 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7660 // TODO: Emulate SUBS PC, LR and related instructions.
7661 if (Rd == 15 && setflags)
7662 return false;
7663 break;
7664 default:
7665 return false;
7666 }
7667 // Read the register value from the operand register Rn.
7668 uint32_t reg_val = ReadCoreReg(Rn, &success);
7669 if (!success)
7670 return false;
7671
7672 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
7673
7674 EmulateInstruction::Context context;
7675 context.type = EmulateInstruction::eContextImmediate;
7676 context.SetNoArgs ();
7677
7678 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7679 return false;
7680
7681 return true;
7682}
7683
7684// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
7685// NOT (Carry flag) from a register value, and writes the result to the destination register.
7686// It can optionally update the condition flags based on the result.
7687bool
7688EmulateInstructionARM::EmulateSBCReg (ARMEncoding encoding)
7689{
7690#if 0
7691 // ARM pseudo code...
7692 if ConditionPassed() then
7693 EncodingSpecificOperations();
7694 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
7695 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
7696 if d == 15 then // Can only occur for ARM encoding
7697 ALUWritePC(result); // setflags is always FALSE here
7698 else
7699 R[d] = result;
7700 if setflags then
7701 APSR.N = result<31>;
7702 APSR.Z = IsZeroBit(result);
7703 APSR.C = carry;
7704 APSR.V = overflow;
7705#endif
7706
7707 bool success = false;
7708 const uint32_t opcode = OpcodeAsUnsigned (&success);
7709 if (!success)
7710 return false;
7711
7712 uint32_t Rd; // the destination register
7713 uint32_t Rn; // the first operand
7714 uint32_t Rm; // the second operand
7715 bool setflags;
7716 ARM_ShifterType shift_t;
7717 uint32_t shift_n; // the shift applied to the value read from Rm
7718 switch (encoding) {
7719 case eEncodingT1:
7720 Rd = Rn = Bits32(opcode, 2, 0);
7721 Rm = Bits32(opcode, 5, 3);
7722 setflags = !InITBlock();
7723 shift_t = SRType_LSL;
7724 shift_n = 0;
7725 break;
7726 case eEncodingT2:
7727 Rd = Bits32(opcode, 11, 8);
7728 Rn = Bits32(opcode, 19, 16);
7729 Rm = Bits32(opcode, 3, 0);
7730 setflags = BitIsSet(opcode, 20);
7731 shift_n = DecodeImmShiftThumb(opcode, shift_t);
7732 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
7733 return false;
7734 break;
7735 case eEncodingA1:
7736 Rd = Bits32(opcode, 15, 12);
7737 Rn = Bits32(opcode, 19, 16);
7738 Rm = Bits32(opcode, 3, 0);
7739 setflags = BitIsSet(opcode, 20);
7740 shift_n = DecodeImmShiftARM(opcode, shift_t);
7741 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7742 // TODO: Emulate SUBS PC, LR and related instructions.
7743 if (Rd == 15 && setflags)
7744 return false;
7745 break;
7746 default:
7747 return false;
7748 }
7749 // Read the register value from register Rn.
7750 uint32_t val1 = ReadCoreReg(Rn, &success);
7751 if (!success)
7752 return false;
7753
7754 // Read the register value from register Rm.
7755 uint32_t val2 = ReadCoreReg(Rm, &success);
7756 if (!success)
7757 return false;
7758
7759 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C);
7760 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
7761
7762 EmulateInstruction::Context context;
7763 context.type = EmulateInstruction::eContextImmediate;
7764 context.SetNoArgs();
7765 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7766 return false;
7767
7768 return true;
7769}
7770
Johnny Chen15a7a6b2011-02-23 23:47:56 +00007771// This instruction subtracts an immediate value from a register value, and writes the result
7772// to the destination register. It can optionally update the condition flags based on the result.
7773bool
7774EmulateInstructionARM::EmulateSUBImmThumb (ARMEncoding encoding)
7775{
7776#if 0
7777 // ARM pseudo code...
7778 if ConditionPassed() then
7779 EncodingSpecificOperations();
7780 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
7781 R[d] = result;
7782 if setflags then
7783 APSR.N = result<31>;
7784 APSR.Z = IsZeroBit(result);
7785 APSR.C = carry;
7786 APSR.V = overflow;
7787#endif
7788
7789 bool success = false;
7790 const uint32_t opcode = OpcodeAsUnsigned (&success);
7791 if (!success)
7792 return false;
7793
7794 uint32_t Rd; // the destination register
7795 uint32_t Rn; // the first operand
7796 bool setflags;
7797 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
7798 switch (encoding) {
7799 case eEncodingT1:
7800 Rd = Bits32(opcode, 2, 0);
7801 Rn = Bits32(opcode, 5, 3);
7802 setflags = !InITBlock();
7803 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
7804 break;
7805 case eEncodingT2:
7806 Rd = Rn = Bits32(opcode, 10, 8);
7807 setflags = !InITBlock();
7808 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
7809 break;
7810 case eEncodingT3:
7811 Rd = Bits32(opcode, 11, 8);
7812 Rn = Bits32(opcode, 19, 16);
7813 setflags = BitIsSet(opcode, 20);
7814 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
7815
7816 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
7817 if (Rd == 15 && setflags)
7818 return EmulateCMPImm(eEncodingT2);
7819
7820 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
7821 if (Rn == 13)
7822 return EmulateSUBSPImm(eEncodingT2);
7823
7824 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
7825 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
7826 return false;
7827 break;
7828 case eEncodingT4:
7829 Rd = Bits32(opcode, 11, 8);
7830 Rn = Bits32(opcode, 19, 16);
7831 setflags = BitIsSet(opcode, 20);
7832 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
7833
7834 // if Rn == '1111' then SEE ADR;
7835 if (Rn == 15)
7836 return EmulateADR(eEncodingT2);
7837
7838 // if Rn == '1101' then SEE SUB (SP minus immediate);
7839 if (Rn == 13)
7840 return EmulateSUBSPImm(eEncodingT3);
7841
7842 if (BadReg(Rd))
7843 return false;
7844 break;
7845 default:
7846 return false;
7847 }
7848 // Read the register value from the operand register Rn.
7849 uint32_t reg_val = ReadCoreReg(Rn, &success);
7850 if (!success)
7851 return false;
7852
7853 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
7854
7855 EmulateInstruction::Context context;
7856 context.type = EmulateInstruction::eContextImmediate;
7857 context.SetNoArgs ();
7858
7859 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7860 return false;
7861
7862 return true;
7863}
7864
7865// This instruction subtracts an immediate value from a register value, and writes the result
7866// to the destination register. It can optionally update the condition flags based on the result.
7867bool
7868EmulateInstructionARM::EmulateSUBImmARM (ARMEncoding encoding)
7869{
7870#if 0
7871 // ARM pseudo code...
7872 if ConditionPassed() then
7873 EncodingSpecificOperations();
7874 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
7875 if d == 15 then
7876 ALUWritePC(result); // setflags is always FALSE here
7877 else
7878 R[d] = result;
7879 if setflags then
7880 APSR.N = result<31>;
7881 APSR.Z = IsZeroBit(result);
7882 APSR.C = carry;
7883 APSR.V = overflow;
7884#endif
7885
7886 bool success = false;
7887 const uint32_t opcode = OpcodeAsUnsigned (&success);
7888 if (!success)
7889 return false;
7890
7891 uint32_t Rd; // the destination register
7892 uint32_t Rn; // the first operand
7893 bool setflags;
7894 uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
7895 switch (encoding) {
7896 case eEncodingA1:
7897 Rd = Bits32(opcode, 15, 12);
7898 Rn = Bits32(opcode, 19, 16);
7899 setflags = BitIsSet(opcode, 20);
7900 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
7901
7902 // if Rn == ‘1111’ && S == ‘0’ then SEE ADR;
7903 if (Rn == 15 && !setflags)
7904 return EmulateADR(eEncodingA2);
7905
7906 // if Rn == ‘1101’ then SEE SUB (SP minus immediate);
7907 if (Rn == 13)
7908 return EmulateSUBSPImm(eEncodingA1);
7909
7910 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
7911 // TODO: Emulate SUBS PC, LR and related instructions.
7912 if (Rd == 15 && setflags)
7913 return false;
7914 break;
7915 default:
7916 return false;
7917 }
7918 // Read the register value from the operand register Rn.
7919 uint32_t reg_val = ReadCoreReg(Rn, &success);
7920 if (!success)
7921 return false;
7922
7923 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
7924
7925 EmulateInstruction::Context context;
7926 context.type = EmulateInstruction::eContextImmediate;
7927 context.SetNoArgs ();
7928
7929 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
7930 return false;
7931
7932 return true;
7933}
7934
Johnny Chen2115b412011-02-21 23:42:44 +00007935// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
7936// immediate value. It updates the condition flags based on the result, and discards the result.
7937bool
7938EmulateInstructionARM::EmulateTEQImm (ARMEncoding encoding)
7939{
7940#if 0
7941 // ARM pseudo code...
7942 if ConditionPassed() then
7943 EncodingSpecificOperations();
7944 result = R[n] EOR imm32;
7945 APSR.N = result<31>;
7946 APSR.Z = IsZeroBit(result);
7947 APSR.C = carry;
7948 // APSR.V unchanged
7949#endif
7950
7951 bool success = false;
7952 const uint32_t opcode = OpcodeAsUnsigned (&success);
7953 if (!success)
7954 return false;
7955
7956 if (ConditionPassed())
7957 {
7958 uint32_t Rn;
7959 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
7960 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
7961 switch (encoding)
7962 {
7963 case eEncodingT1:
7964 Rn = Bits32(opcode, 19, 16);
7965 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
7966 if (BadReg(Rn))
7967 return false;
7968 break;
7969 case eEncodingA1:
7970 Rn = Bits32(opcode, 19, 16);
7971 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
7972 break;
7973 default:
7974 return false;
7975 }
7976
7977 // Read the first operand.
7978 uint32_t val1 = ReadCoreReg(Rn, &success);
7979 if (!success)
7980 return false;
7981
7982 uint32_t result = val1 ^ imm32;
7983
7984 EmulateInstruction::Context context;
7985 context.type = EmulateInstruction::eContextImmediate;
7986 context.SetNoArgs ();
7987
7988 if (!WriteFlags(context, result, carry))
7989 return false;
7990 }
7991 return true;
7992}
7993
7994// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
7995// optionally-shifted register value. It updates the condition flags based on the result, and discards
7996// the result.
7997bool
7998EmulateInstructionARM::EmulateTEQReg (ARMEncoding encoding)
7999{
8000#if 0
8001 // ARM pseudo code...
8002 if ConditionPassed() then
8003 EncodingSpecificOperations();
8004 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8005 result = R[n] EOR shifted;
8006 APSR.N = result<31>;
8007 APSR.Z = IsZeroBit(result);
8008 APSR.C = carry;
8009 // APSR.V unchanged
8010#endif
8011
8012 bool success = false;
8013 const uint32_t opcode = OpcodeAsUnsigned (&success);
8014 if (!success)
8015 return false;
8016
8017 if (ConditionPassed())
8018 {
8019 uint32_t Rn, Rm;
8020 ARM_ShifterType shift_t;
8021 uint32_t shift_n; // the shift applied to the value read from Rm
8022 uint32_t carry;
8023 switch (encoding)
8024 {
8025 case eEncodingT1:
8026 Rn = Bits32(opcode, 19, 16);
8027 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008028 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008029 if (BadReg(Rn) || BadReg(Rm))
8030 return false;
8031 break;
8032 case eEncodingA1:
8033 Rn = Bits32(opcode, 19, 16);
8034 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008035 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chen2115b412011-02-21 23:42:44 +00008036 break;
8037 default:
8038 return false;
8039 }
8040
8041 // Read the first operand.
8042 uint32_t val1 = ReadCoreReg(Rn, &success);
8043 if (!success)
8044 return false;
8045
8046 // Read the second operand.
8047 uint32_t val2 = ReadCoreReg(Rm, &success);
8048 if (!success)
8049 return false;
8050
8051 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8052 uint32_t result = val1 ^ shifted;
8053
8054 EmulateInstruction::Context context;
8055 context.type = EmulateInstruction::eContextImmediate;
8056 context.SetNoArgs ();
8057
8058 if (!WriteFlags(context, result, carry))
8059 return false;
8060 }
8061 return true;
8062}
8063
Johnny Chende3cce32011-02-21 21:24:49 +00008064// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
8065// It updates the condition flags based on the result, and discards the result.
8066bool
8067EmulateInstructionARM::EmulateTSTImm (ARMEncoding encoding)
8068{
8069#if 0
8070 // ARM pseudo code...
8071 if ConditionPassed() then
8072 EncodingSpecificOperations();
8073 result = R[n] AND imm32;
8074 APSR.N = result<31>;
8075 APSR.Z = IsZeroBit(result);
8076 APSR.C = carry;
8077 // APSR.V unchanged
8078#endif
8079
8080 bool success = false;
8081 const uint32_t opcode = OpcodeAsUnsigned (&success);
8082 if (!success)
8083 return false;
8084
8085 if (ConditionPassed())
8086 {
8087 uint32_t Rn;
8088 uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
8089 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8090 switch (encoding)
8091 {
8092 case eEncodingT1:
8093 Rn = Bits32(opcode, 19, 16);
8094 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8095 if (BadReg(Rn))
8096 return false;
8097 break;
8098 case eEncodingA1:
8099 Rn = Bits32(opcode, 19, 16);
8100 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8101 break;
8102 default:
8103 return false;
8104 }
8105
8106 // Read the first operand.
8107 uint32_t val1 = ReadCoreReg(Rn, &success);
8108 if (!success)
8109 return false;
8110
8111 uint32_t result = val1 & imm32;
8112
8113 EmulateInstruction::Context context;
8114 context.type = EmulateInstruction::eContextImmediate;
8115 context.SetNoArgs ();
8116
8117 if (!WriteFlags(context, result, carry))
8118 return false;
8119 }
8120 return true;
8121}
8122
8123// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
8124// It updates the condition flags based on the result, and discards the result.
8125bool
8126EmulateInstructionARM::EmulateTSTReg (ARMEncoding encoding)
8127{
8128#if 0
8129 // ARM pseudo code...
8130 if ConditionPassed() then
8131 EncodingSpecificOperations();
8132 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8133 result = R[n] AND shifted;
8134 APSR.N = result<31>;
8135 APSR.Z = IsZeroBit(result);
8136 APSR.C = carry;
8137 // APSR.V unchanged
8138#endif
8139
8140 bool success = false;
8141 const uint32_t opcode = OpcodeAsUnsigned (&success);
8142 if (!success)
8143 return false;
8144
8145 if (ConditionPassed())
8146 {
8147 uint32_t Rn, Rm;
8148 ARM_ShifterType shift_t;
8149 uint32_t shift_n; // the shift applied to the value read from Rm
8150 uint32_t carry;
8151 switch (encoding)
8152 {
8153 case eEncodingT1:
8154 Rn = Bits32(opcode, 2, 0);
8155 Rm = Bits32(opcode, 5, 3);
8156 shift_t = SRType_LSL;
8157 shift_n = 0;
Johnny Chened32e7c2011-02-22 23:42:58 +00008158 break;
Johnny Chende3cce32011-02-21 21:24:49 +00008159 case eEncodingT2:
8160 Rn = Bits32(opcode, 19, 16);
8161 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008162 shift_n = DecodeImmShiftThumb(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00008163 if (BadReg(Rn) || BadReg(Rm))
8164 return false;
8165 break;
8166 case eEncodingA1:
8167 Rn = Bits32(opcode, 19, 16);
8168 Rm = Bits32(opcode, 3, 0);
Johnny Chen3dd06052011-02-22 21:17:52 +00008169 shift_n = DecodeImmShiftARM(opcode, shift_t);
Johnny Chende3cce32011-02-21 21:24:49 +00008170 break;
8171 default:
8172 return false;
8173 }
8174
8175 // Read the first operand.
8176 uint32_t val1 = ReadCoreReg(Rn, &success);
8177 if (!success)
8178 return false;
8179
8180 // Read the second operand.
8181 uint32_t val2 = ReadCoreReg(Rm, &success);
8182 if (!success)
8183 return false;
8184
8185 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry);
8186 uint32_t result = val1 & shifted;
8187
8188 EmulateInstruction::Context context;
8189 context.type = EmulateInstruction::eContextImmediate;
8190 context.SetNoArgs ();
8191
8192 if (!WriteFlags(context, result, carry))
8193 return false;
8194 }
8195 return true;
8196}
8197
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008198EmulateInstructionARM::ARMOpcode*
8199EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
Greg Clayton64c84432011-01-21 22:02:52 +00008200{
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008201 static ARMOpcode
8202 g_arm_opcodes[] =
8203 {
8204 //----------------------------------------------------------------------
8205 // Prologue instructions
8206 //----------------------------------------------------------------------
Johnny Chenfdd179e2011-01-31 20:09:28 +00008207
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008208 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00008209 { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
8210 { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
Johnny Chenbcec3af2011-01-27 01:26:19 +00008211
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008212 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00008213 { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00008214 { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
Johnny Chene7cf4202011-02-10 18:13:23 +00008215 // copy the stack pointer to ip
Johnny Chen9f687722011-02-18 00:02:28 +00008216 { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
8217 { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
Johnny Chen864a8e82011-02-18 00:07:39 +00008218 { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
Johnny Chen4c0e0bc2011-01-25 22:45:28 +00008219
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008220 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00008221 { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
Johnny Chence1ca772011-01-25 01:13:00 +00008222
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008223 // push one register
8224 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
Johnny Chenc28a76d2011-02-01 18:51:48 +00008225 { 0x0fff0000, 0x052d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
Johnny Chen799dfd02011-01-26 23:14:33 +00008226
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008227 // vector push consecutive extension register(s)
Johnny Chen9b8d7832011-02-02 01:13:56 +00008228 { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
8229 { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenef85e912011-01-31 23:07:40 +00008230
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008231 //----------------------------------------------------------------------
Johnny Chen587a0a42011-02-01 18:35:28 +00008232 // Epilogue instructions
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008233 //----------------------------------------------------------------------
Johnny Chenef85e912011-01-31 23:07:40 +00008234
Johnny Chen9f687722011-02-18 00:02:28 +00008235 { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
8236 { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
Johnny Chen9b8d7832011-02-02 01:13:56 +00008237 { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008238 { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
8239
8240 //----------------------------------------------------------------------
8241 // Supervisor Call (previously Software Interrupt)
8242 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00008243 { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
8244
8245 //----------------------------------------------------------------------
8246 // Branch instructions
8247 //----------------------------------------------------------------------
Johnny Chen696b4ef2011-02-24 21:54:22 +00008248 { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
Johnny Chen383d6292011-02-11 21:23:32 +00008249 // To resolve ambiguity, "blx <label>" should come before "bl <label>".
8250 { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
8251 { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
8252 { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00008253 // for example, "bx lr"
8254 { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00008255 // bxj
8256 { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008257
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008258 //----------------------------------------------------------------------
Johnny Chen28070c32011-02-12 01:27:26 +00008259 // Data-processing instructions
8260 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00008261 // adc (immediate)
8262 { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
8263 // adc (register)
8264 { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen8fa20592011-02-18 01:22:22 +00008265 // add (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008266 { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
Johnny Chen8fa20592011-02-18 01:22:22 +00008267 // add (register)
Johnny Chen157b9592011-02-18 21:13:05 +00008268 { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chena695f952011-02-23 21:24:25 +00008269 // adr
8270 { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
8271 { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008272 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008273 { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008274 // and (register)
Johnny Chen157b9592011-02-18 21:13:05 +00008275 { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00008276 // bic (immediate)
8277 { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
8278 // bic (register)
8279 { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00008280 // eor (immediate)
8281 { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
8282 // eor (register)
8283 { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008284 // orr (immediate)
8285 { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
8286 // orr (register)
8287 { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00008288 // rsb (immediate)
8289 { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
8290 // rsb (register)
8291 { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen90e607b2011-02-23 00:07:09 +00008292 // rsc (immediate)
8293 { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
8294 // rsc (register)
8295 { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00008296 // sbc (immediate)
8297 { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
8298 // sbc (register)
8299 { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008300 // sub (immediate, ARM)
8301 { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008302 // sub (sp minus immediate)
8303 { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
Johnny Chen2115b412011-02-21 23:42:44 +00008304 // teq (immediate)
8305 { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
8306 // teq (register)
8307 { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00008308 // tst (immediate)
8309 { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
8310 // tst (register)
8311 { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
8312
8313
Johnny Chen01d61572011-02-25 00:23:25 +00008314 // mov (register)
8315 { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00008316 // mvn (immediate)
8317 { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
8318 // mvn (register)
8319 { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
Johnny Chen3847dad2011-02-22 02:00:12 +00008320 // cmn (immediate)
8321 { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
8322 // cmn (register)
8323 { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008324 // cmp (immediate)
8325 { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
8326 // cmp (register)
8327 { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00008328 // asr (immediate)
8329 { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008330 // asr (register)
Johnny Chene7f89532011-02-15 23:22:46 +00008331 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008332 // lsl (immediate)
8333 { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
8334 // lsl (register)
8335 { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
8336 // lsr (immediate)
8337 { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
8338 // lsr (register)
8339 { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00008340 // rrx is a special case encoding of ror (immediate)
8341 { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
8342 // ror (immediate)
8343 { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
8344 // ror (register)
8345 { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen28070c32011-02-12 01:27:26 +00008346
8347 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008348 // Load instructions
8349 //----------------------------------------------------------------------
Caroline Tice0b29e242011-02-08 23:16:02 +00008350 { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice713c2662011-02-11 17:59:55 +00008351 { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
Caroline Tice85aab332011-02-08 23:56:10 +00008352 { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Caroline Ticefa172202011-02-11 22:49:54 +00008353 { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
Caroline Tice4d729c52011-02-18 00:55:53 +00008354 { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
Caroline Ticefe479112011-02-18 18:52:37 +00008355 { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
Caroline Tice30fec122011-02-18 23:52:21 +00008356 { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
Caroline Tice0491b3b2011-02-28 22:39:58 +00008357 { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00008358 { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00008359 { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00008360 { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
Caroline Tice5f593912011-03-01 22:25:17 +00008361 { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00008362 { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
Caroline Tice78fb5632011-03-02 00:39:42 +00008363 { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
Caroline Ticed2fac092011-03-02 19:45:34 +00008364 { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Ticefa172202011-02-11 22:49:54 +00008365
8366 //----------------------------------------------------------------------
8367 // Store instructions
8368 //----------------------------------------------------------------------
Caroline Tice1511f502011-02-15 00:19:42 +00008369 { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00008370 { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
Caroline Ticeaf556562011-02-15 18:42:15 +00008371 { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Tice3fd63e92011-02-16 00:33:43 +00008372 { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
8373 { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }
Caroline Tice1511f502011-02-15 00:19:42 +00008374
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008375
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008376 };
8377 static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
8378
8379 for (size_t i=0; i<k_num_arm_opcodes; ++i)
8380 {
8381 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value)
8382 return &g_arm_opcodes[i];
8383 }
8384 return NULL;
8385}
Greg Clayton64c84432011-01-21 22:02:52 +00008386
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008387
8388EmulateInstructionARM::ARMOpcode*
8389EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
Johnny Chen347320d2011-01-24 23:40:59 +00008390{
Johnny Chenfdd179e2011-01-31 20:09:28 +00008391
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008392 static ARMOpcode
8393 g_thumb_opcodes[] =
8394 {
8395 //----------------------------------------------------------------------
8396 // Prologue instructions
8397 //----------------------------------------------------------------------
Johnny Chenbcec3af2011-01-27 01:26:19 +00008398
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008399 // push register(s)
Johnny Chen9f687722011-02-18 00:02:28 +00008400 { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
8401 { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
8402 { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
Johnny Chen788e0552011-01-27 22:52:23 +00008403
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008404 // set r7 to point to a stack offset
Johnny Chen9f687722011-02-18 00:02:28 +00008405 { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
Johnny Chene7cf4202011-02-10 18:13:23 +00008406 // copy the stack pointer to r7
Johnny Chen9f687722011-02-18 00:02:28 +00008407 { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
Johnny Chene7cf4202011-02-10 18:13:23 +00008408 // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
Johnny Chen9f687722011-02-18 00:02:28 +00008409 { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
Johnny Chen60c0d622011-01-25 23:49:39 +00008410
Johnny Chen864a8e82011-02-18 00:07:39 +00008411 // PC-relative load into register (see also EmulateADDSPRm)
Johnny Chenc9de9102011-02-11 19:12:30 +00008412 { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
Johnny Chen799dfd02011-01-26 23:14:33 +00008413
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008414 // adjust the stack pointer
Johnny Chen864a8e82011-02-18 00:07:39 +00008415 { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008416 { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
Johnny Chen864a8e82011-02-18 00:07:39 +00008417 { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
8418 { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00008419
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008420 // vector push consecutive extension register(s)
Johnny Chend6c13f02011-02-08 20:36:34 +00008421 { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
8422 { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
Johnny Chenfdd179e2011-01-31 20:09:28 +00008423
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008424 //----------------------------------------------------------------------
8425 // Epilogue instructions
8426 //----------------------------------------------------------------------
Johnny Chen347320d2011-01-24 23:40:59 +00008427
Johnny Chen864a8e82011-02-18 00:07:39 +00008428 { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
Johnny Chen9f687722011-02-18 00:02:28 +00008429 { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
8430 { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
8431 { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
Johnny Chend6c13f02011-02-08 20:36:34 +00008432 { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
8433 { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
Johnny Chenb77be412011-02-04 00:40:18 +00008434
8435 //----------------------------------------------------------------------
8436 // Supervisor Call (previously Software Interrupt)
8437 //----------------------------------------------------------------------
Johnny Chenc315f862011-02-05 00:46:10 +00008438 { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
8439
8440 //----------------------------------------------------------------------
8441 // If Then makes up to four following instructions conditional.
8442 //----------------------------------------------------------------------
Johnny Chen3b620b32011-02-07 20:11:47 +00008443 { 0xffffff00, 0x0000bf00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
8444
8445 //----------------------------------------------------------------------
8446 // Branch instructions
8447 //----------------------------------------------------------------------
8448 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
8449 { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00008450 { 0xffff8000, 0x0000e000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
Johnny Chen9ee056b2011-02-08 00:06:35 +00008451 { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
Johnny Chen696b4ef2011-02-24 21:54:22 +00008452 { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
Johnny Chen383d6292011-02-11 21:23:32 +00008453 // J1 == J2 == 1
8454 { 0xf800f800, 0xf000f800, ARMV4T_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
8455 // J1 == J2 == 1
8456 { 0xf800e800, 0xf000e800, ARMV5_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
8457 { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
Johnny Chenab3b3512011-02-12 00:10:51 +00008458 // for example, "bx lr"
8459 { 0xffffff87, 0x00004700, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
Johnny Chen59e6ab72011-02-24 21:01:20 +00008460 // bxj
8461 { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
Johnny Chen53ebab72011-02-08 23:21:57 +00008462 // compare and branch
8463 { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
Johnny Chen60299ec2011-02-17 19:34:27 +00008464 // table branch byte
8465 { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
8466 // table branch halfword
8467 { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008468
8469 //----------------------------------------------------------------------
Johnny Chen26863dc2011-02-09 23:43:29 +00008470 // Data-processing instructions
8471 //----------------------------------------------------------------------
Johnny Chen157b9592011-02-18 21:13:05 +00008472 // adc (immediate)
8473 { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
8474 // adc (register)
8475 { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
8476 { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
8477 // add (register)
Johnny Chen9f687722011-02-18 00:02:28 +00008478 { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00008479 // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
Johnny Chen9f687722011-02-18 00:02:28 +00008480 { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
Johnny Chena695f952011-02-23 21:24:25 +00008481 // adr
8482 { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
8483 { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
8484 { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008485 // and (immediate)
Johnny Chen157b9592011-02-18 21:13:05 +00008486 { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
Johnny Chene97c0d52011-02-18 19:32:20 +00008487 // and (register)
8488 { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
8489 { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chenb9f02cf2011-02-24 01:15:17 +00008490 // bic (immediate)
8491 { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
8492 // bic (register)
8493 { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
8494 { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen2115b412011-02-21 23:42:44 +00008495 // eor (immediate)
8496 { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
8497 // eor (register)
8498 { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
8499 { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008500 // orr (immediate)
8501 { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
8502 // orr (register)
8503 { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
8504 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chened32e7c2011-02-22 23:42:58 +00008505 // rsb (immediate)
8506 { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
8507 { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
8508 // rsb (register)
8509 { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen9b381772011-02-23 01:01:21 +00008510 // sbc (immediate)
8511 { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
8512 // sbc (register)
8513 { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
8514 { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
Johnny Chen15a7a6b2011-02-23 23:47:56 +00008515 // sub (immediate, Thumb)
8516 { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
8517 { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
8518 { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
8519 { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
Johnny Chenc9e747f2011-02-23 01:55:07 +00008520 // sub (sp minus immediate)
8521 { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
8522 { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
Johnny Chen2115b412011-02-21 23:42:44 +00008523 // teq (immediate)
8524 { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
8525 // teq (register)
8526 { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chende3cce32011-02-21 21:24:49 +00008527 // tst (immediate)
Johnny Chen2115b412011-02-21 23:42:44 +00008528 { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
Johnny Chende3cce32011-02-21 21:24:49 +00008529 // tst (register)
8530 { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
8531 { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
8532
Johnny Chen7c5234d2011-02-18 23:41:11 +00008533
Johnny Chen338bf542011-02-10 19:29:03 +00008534 // move from high register to high register
Johnny Chen9f687722011-02-18 00:02:28 +00008535 { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
Johnny Chen338bf542011-02-10 19:29:03 +00008536 // move from low register to low register
Johnny Chen9f687722011-02-18 00:02:28 +00008537 { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
Johnny Chen7c5234d2011-02-18 23:41:11 +00008538 // mov{s}<c>.w <Rd>, <Rm>
8539 { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
Johnny Chen357c30f2011-02-14 22:04:25 +00008540 // move immediate
Johnny Chen9f687722011-02-18 00:02:28 +00008541 { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
8542 { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
Johnny Chend642a6a2011-02-22 01:01:03 +00008543 // mvn (immediate)
8544 { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
8545 // mvn (register)
8546 { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
8547 { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008548 // cmn (immediate)
Johnny Chen688926f2011-02-22 19:01:11 +00008549 { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008550 // cmn (register)
8551 { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
Johnny Chen078fbc62011-02-22 19:48:22 +00008552 { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008553 // cmp (immediate)
8554 { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
Johnny Chen078fbc62011-02-22 19:48:22 +00008555 { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
Johnny Chen34075cb2011-02-22 01:56:31 +00008556 // cmp (register) (Rn and Rm both from r0-r7)
8557 { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
8558 // cmp (register) (Rn and Rm not both from r0-r7)
8559 { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
Johnny Chen82f16aa2011-02-15 20:10:55 +00008560 // asr (immediate)
8561 { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
Johnny Chen4d896db2011-02-15 20:14:02 +00008562 { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
Johnny Chene7f89532011-02-15 23:22:46 +00008563 // asr (register)
8564 { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
8565 { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008566 // lsl (immediate)
8567 { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
8568 { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
8569 // lsl (register)
8570 { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
8571 { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
8572 // lsr (immediate)
8573 { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
8574 { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
8575 // lsr (register)
Johnny Cheneeab4852011-02-16 22:14:44 +00008576 { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
Johnny Chen2ee35bc2011-02-16 19:27:43 +00008577 { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Cheneeab4852011-02-16 22:14:44 +00008578 // rrx is a special case encoding of ror (immediate)
8579 { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
8580 // ror (immediate)
8581 { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
8582 // ror (register)
8583 { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
8584 { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
Johnny Chen26863dc2011-02-09 23:43:29 +00008585
8586 //----------------------------------------------------------------------
Caroline Ticeb9f76c32011-02-08 22:24:38 +00008587 // Load instructions
8588 //----------------------------------------------------------------------
8589 { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
Caroline Tice0b29e242011-02-08 23:16:02 +00008590 { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
Johnny Chenef21b592011-02-10 01:52:38 +00008591 { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
Johnny Chenc9de9102011-02-11 19:12:30 +00008592 { 0xfffff800, 0x00006800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
8593 // Thumb2 PC-relative load into register
Caroline Ticefa172202011-02-11 22:49:54 +00008594 { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
Caroline Ticefe479112011-02-18 18:52:37 +00008595 { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" },
8596 { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Tice21b604b2011-02-18 21:06:04 +00008597 { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
8598 { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
8599 { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[>Rn>, #+/-<imm8>]{!}" },
Caroline Ticef55261f2011-02-18 22:24:22 +00008600 { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
Caroline Tice30fec122011-02-18 23:52:21 +00008601 { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
8602 { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, eSize32,&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice0491b3b2011-02-28 22:39:58 +00008603 { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" },
8604 { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
8605 { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" },
Caroline Tice952b5382011-02-28 23:15:24 +00008606 { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
Caroline Tice0e6bc952011-03-01 18:00:42 +00008607 { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
8608 { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
Caroline Ticea5e28af2011-03-01 21:53:03 +00008609 { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
8610 { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Tice5f593912011-03-01 22:25:17 +00008611 { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
Caroline Tice672f3112011-03-01 23:55:59 +00008612 { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
8613 { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
Caroline Tice78fb5632011-03-02 00:39:42 +00008614 { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
8615 { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
Caroline Ticed2fac092011-03-02 19:45:34 +00008616 { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
Caroline Ticefa172202011-02-11 22:49:54 +00008617
8618 //----------------------------------------------------------------------
8619 // Store instructions
8620 //----------------------------------------------------------------------
8621 { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
Caroline Ticeb6f8d7e2011-02-15 18:10:01 +00008622 { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
Caroline Tice7fac8572011-02-15 22:53:54 +00008623 { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
Caroline Ticefe479112011-02-18 18:52:37 +00008624 { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
8625 { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
8626 { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
8627 { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
8628 { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
8629 { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
8630 { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
8631 { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
8632 { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }
Greg Clayton2b8e8b02011-02-01 00:49:32 +00008633 };
8634
8635 const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
8636 for (size_t i=0; i<k_num_thumb_opcodes; ++i)
8637 {
8638 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value)
8639 return &g_thumb_opcodes[i];
8640 }
8641 return NULL;
8642}
Greg Clayton64c84432011-01-21 22:02:52 +00008643
Greg Clayton31e2a382011-01-30 20:03:56 +00008644bool
Greg Clayton395fc332011-02-15 21:59:32 +00008645EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
Greg Clayton31e2a382011-01-30 20:03:56 +00008646{
8647 m_arm_isa = 0;
Greg Clayton940b1032011-02-23 00:35:02 +00008648 const char *arch_cstr = arch.GetArchitectureName ();
Greg Clayton395fc332011-02-15 21:59:32 +00008649 if (arch_cstr)
Greg Clayton31e2a382011-01-30 20:03:56 +00008650 {
Greg Clayton395fc332011-02-15 21:59:32 +00008651 if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T;
8652 else if (0 == ::strcasecmp(arch_cstr, "armv4")) m_arm_isa = ARMv4;
8653 else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ;
8654 else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE;
8655 else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T;
8656 else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K;
8657 else if (0 == ::strcasecmp(arch_cstr, "armv6")) m_arm_isa = ARMv6;
8658 else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2;
8659 else if (0 == ::strcasecmp(arch_cstr, "armv7")) m_arm_isa = ARMv7;
8660 else if (0 == ::strcasecmp(arch_cstr, "armv8")) m_arm_isa = ARMv8;
Greg Clayton31e2a382011-01-30 20:03:56 +00008661 }
8662 return m_arm_isa != 0;
8663}
8664
8665
Greg Clayton64c84432011-01-21 22:02:52 +00008666bool
8667EmulateInstructionARM::ReadInstruction ()
8668{
8669 bool success = false;
8670 m_inst_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
8671 if (success)
8672 {
8673 addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
8674 if (success)
8675 {
Caroline Tice9bfe7f22011-02-14 23:03:21 +00008676 Context read_inst_context;
8677 read_inst_context.type = eContextReadOpcode;
8678 read_inst_context.SetNoArgs ();
8679
Greg Clayton64c84432011-01-21 22:02:52 +00008680 if (m_inst_cpsr & MASK_CPSR_T)
8681 {
8682 m_inst_mode = eModeThumb;
Caroline Ticecc96eb52011-02-17 19:20:40 +00008683 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00008684
8685 if (success)
8686 {
8687 if ((m_inst.opcode.inst16 & 0xe000) != 0xe000 || ((m_inst.opcode.inst16 & 0x1800u) == 0))
8688 {
8689 m_inst.opcode_type = eOpcode16;
8690 m_inst.opcode.inst16 = thumb_opcode;
8691 }
8692 else
8693 {
8694 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00008695 m_inst.opcode.inst32 = (thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00008696 }
8697 }
8698 }
8699 else
8700 {
8701 m_inst_mode = eModeARM;
8702 m_inst.opcode_type = eOpcode32;
Caroline Ticecc96eb52011-02-17 19:20:40 +00008703 m_inst.opcode.inst32 = MemARead(read_inst_context, pc, 4, 0, &success);
Greg Clayton64c84432011-01-21 22:02:52 +00008704 }
8705 }
8706 }
8707 if (!success)
8708 {
8709 m_inst_mode = eModeInvalid;
8710 m_inst_pc = LLDB_INVALID_ADDRESS;
8711 }
8712 return success;
8713}
8714
Johnny Chenee9b1f72011-02-09 01:00:31 +00008715uint32_t
8716EmulateInstructionARM::ArchVersion ()
8717{
8718 return m_arm_isa;
8719}
8720
Greg Clayton64c84432011-01-21 22:02:52 +00008721bool
8722EmulateInstructionARM::ConditionPassed ()
8723{
8724 if (m_inst_cpsr == 0)
8725 return false;
8726
8727 const uint32_t cond = CurrentCond ();
8728
8729 if (cond == UINT32_MAX)
8730 return false;
8731
8732 bool result = false;
8733 switch (UnsignedBits(cond, 3, 1))
8734 {
8735 case 0: result = (m_inst_cpsr & MASK_CPSR_Z) != 0; break;
8736 case 1: result = (m_inst_cpsr & MASK_CPSR_C) != 0; break;
8737 case 2: result = (m_inst_cpsr & MASK_CPSR_N) != 0; break;
8738 case 3: result = (m_inst_cpsr & MASK_CPSR_V) != 0; break;
8739 case 4: result = ((m_inst_cpsr & MASK_CPSR_C) != 0) && ((m_inst_cpsr & MASK_CPSR_Z) == 0); break;
8740 case 5:
8741 {
8742 bool n = (m_inst_cpsr & MASK_CPSR_N);
8743 bool v = (m_inst_cpsr & MASK_CPSR_V);
8744 result = n == v;
8745 }
8746 break;
8747 case 6:
8748 {
8749 bool n = (m_inst_cpsr & MASK_CPSR_N);
8750 bool v = (m_inst_cpsr & MASK_CPSR_V);
8751 result = n == v && ((m_inst_cpsr & MASK_CPSR_Z) == 0);
8752 }
8753 break;
8754 case 7:
8755 result = true;
8756 break;
8757 }
8758
8759 if (cond & 1)
8760 result = !result;
8761 return result;
8762}
8763
Johnny Chen9ee056b2011-02-08 00:06:35 +00008764uint32_t
8765EmulateInstructionARM::CurrentCond ()
8766{
8767 switch (m_inst_mode)
8768 {
8769 default:
8770 case eModeInvalid:
8771 break;
8772
8773 case eModeARM:
8774 return UnsignedBits(m_inst.opcode.inst32, 31, 28);
8775
8776 case eModeThumb:
8777 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
8778 // 'cond' field of the encoding.
8779 if (m_inst.opcode_type == eOpcode16 &&
8780 Bits32(m_inst.opcode.inst16, 15, 12) == 0x0d &&
8781 Bits32(m_inst.opcode.inst16, 11, 7) != 0x0f)
8782 {
8783 return Bits32(m_inst.opcode.inst16, 11, 7);
8784 }
8785 else if (m_inst.opcode_type == eOpcode32 &&
8786 Bits32(m_inst.opcode.inst32, 31, 27) == 0x1e &&
8787 Bits32(m_inst.opcode.inst32, 15, 14) == 0x02 &&
8788 Bits32(m_inst.opcode.inst32, 12, 12) == 0x00 &&
8789 Bits32(m_inst.opcode.inst32, 25, 22) <= 0x0d)
8790 {
8791 return Bits32(m_inst.opcode.inst32, 25, 22);
8792 }
8793
8794 return m_it_session.GetCond();
8795 }
8796 return UINT32_MAX; // Return invalid value
8797}
8798
Johnny Chen9ee056b2011-02-08 00:06:35 +00008799bool
Johnny Chen098ae2d2011-02-12 00:50:05 +00008800EmulateInstructionARM::InITBlock()
8801{
8802 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
8803}
8804
8805bool
8806EmulateInstructionARM::LastInITBlock()
8807{
8808 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
8809}
8810
8811bool
Johnny Chen9ee056b2011-02-08 00:06:35 +00008812EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
8813{
8814 addr_t target;
8815
Johnny Chenee9b1f72011-02-09 01:00:31 +00008816 // Check the current instruction set.
8817 if (CurrentInstrSet() == eModeARM)
Johnny Chen9ee056b2011-02-08 00:06:35 +00008818 target = addr & 0xfffffffc;
Johnny Chenee9b1f72011-02-09 01:00:31 +00008819 else
Johnny Chen9ee056b2011-02-08 00:06:35 +00008820 target = addr & 0xfffffffe;
Johnny Chenee9b1f72011-02-09 01:00:31 +00008821
Johnny Chen9ee056b2011-02-08 00:06:35 +00008822 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00008823 return false;
8824
8825 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00008826}
8827
8828// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
8829bool
Johnny Chen668b4512011-02-15 21:08:58 +00008830EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
Johnny Chen9ee056b2011-02-08 00:06:35 +00008831{
8832 addr_t target;
Johnny Chen0f309db2011-02-09 19:11:32 +00008833 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
8834 // we want to record it and issue a WriteRegister callback so the clients
8835 // can track the mode changes accordingly.
8836 bool cpsr_changed = false;
Johnny Chen9ee056b2011-02-08 00:06:35 +00008837
8838 if (BitIsSet(addr, 0))
8839 {
Johnny Chen0f309db2011-02-09 19:11:32 +00008840 if (CurrentInstrSet() != eModeThumb)
8841 {
8842 SelectInstrSet(eModeThumb);
8843 cpsr_changed = true;
8844 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00008845 target = addr & 0xfffffffe;
Johnny Chen668b4512011-02-15 21:08:58 +00008846 context.SetMode (eModeThumb);
Johnny Chen9ee056b2011-02-08 00:06:35 +00008847 }
8848 else if (BitIsClear(addr, 1))
8849 {
Johnny Chen0f309db2011-02-09 19:11:32 +00008850 if (CurrentInstrSet() != eModeARM)
8851 {
8852 SelectInstrSet(eModeARM);
8853 cpsr_changed = true;
8854 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00008855 target = addr & 0xfffffffc;
Johnny Chen668b4512011-02-15 21:08:58 +00008856 context.SetMode (eModeARM);
Johnny Chen9ee056b2011-02-08 00:06:35 +00008857 }
8858 else
8859 return false; // address<1:0> == '10' => UNPREDICTABLE
8860
Johnny Chen0f309db2011-02-09 19:11:32 +00008861 if (cpsr_changed)
8862 {
Johnny Chen558133b2011-02-09 23:59:17 +00008863 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
Johnny Chen0f309db2011-02-09 19:11:32 +00008864 return false;
8865 }
Johnny Chen9ee056b2011-02-08 00:06:35 +00008866 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
Johnny Chen53ebab72011-02-08 23:21:57 +00008867 return false;
8868
8869 return true;
Johnny Chen9ee056b2011-02-08 00:06:35 +00008870}
Greg Clayton64c84432011-01-21 22:02:52 +00008871
Johnny Chenee9b1f72011-02-09 01:00:31 +00008872// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
8873bool
Johnny Chen668b4512011-02-15 21:08:58 +00008874EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
Johnny Chenee9b1f72011-02-09 01:00:31 +00008875{
8876 if (ArchVersion() >= ARMv5T)
Johnny Chen668b4512011-02-15 21:08:58 +00008877 return BXWritePC(context, addr);
Johnny Chenee9b1f72011-02-09 01:00:31 +00008878 else
8879 return BranchWritePC((const Context)context, addr);
8880}
8881
Johnny Chen26863dc2011-02-09 23:43:29 +00008882// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
8883bool
Johnny Chen668b4512011-02-15 21:08:58 +00008884EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
Johnny Chen26863dc2011-02-09 23:43:29 +00008885{
8886 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
Johnny Chen668b4512011-02-15 21:08:58 +00008887 return BXWritePC(context, addr);
Johnny Chen26863dc2011-02-09 23:43:29 +00008888 else
8889 return BranchWritePC((const Context)context, addr);
8890}
8891
Johnny Chenee9b1f72011-02-09 01:00:31 +00008892EmulateInstructionARM::Mode
8893EmulateInstructionARM::CurrentInstrSet ()
8894{
8895 return m_inst_mode;
8896}
8897
8898// Set the 'T' bit of our CPSR. The m_inst_mode gets updated when the next
Johnny Chen558133b2011-02-09 23:59:17 +00008899// ReadInstruction() is performed. This function has a side effect of updating
8900// the m_new_inst_cpsr member variable if necessary.
Johnny Chenee9b1f72011-02-09 01:00:31 +00008901bool
8902EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
8903{
Johnny Chen558133b2011-02-09 23:59:17 +00008904 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chenee9b1f72011-02-09 01:00:31 +00008905 switch (arm_or_thumb)
8906 {
8907 default:
8908 return false;
8909 eModeARM:
8910 // Clear the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00008911 m_new_inst_cpsr &= ~MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00008912 break;
8913 eModeThumb:
8914 // Set the T bit.
Johnny Chen558133b2011-02-09 23:59:17 +00008915 m_new_inst_cpsr |= MASK_CPSR_T;
Johnny Chenee9b1f72011-02-09 01:00:31 +00008916 break;
8917 }
8918 return true;
8919}
8920
Johnny Chenef21b592011-02-10 01:52:38 +00008921// This function returns TRUE if the processor currently provides support for
8922// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
8923// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
8924bool
8925EmulateInstructionARM::UnalignedSupport()
8926{
8927 return (ArchVersion() >= ARMv7);
8928}
8929
Johnny Chenbf6ad172011-02-11 01:29:53 +00008930// The main addition and subtraction instructions can produce status information
8931// about both unsigned carry and signed overflow conditions. This status
8932// information can be used to synthesize multi-word additions and subtractions.
8933EmulateInstructionARM::AddWithCarryResult
8934EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
8935{
8936 uint32_t result;
8937 uint8_t carry_out;
8938 uint8_t overflow;
8939
8940 uint64_t unsigned_sum = x + y + carry_in;
8941 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
8942
8943 result = UnsignedBits(unsigned_sum, 31, 0);
8944 carry_out = (result == unsigned_sum ? 0 : 1);
8945 overflow = ((int32_t)result == signed_sum ? 0 : 1);
8946
8947 AddWithCarryResult res = { result, carry_out, overflow };
8948 return res;
8949}
8950
Johnny Chen157b9592011-02-18 21:13:05 +00008951uint32_t
Johnny Chene39f22d2011-02-19 01:36:13 +00008952EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
Johnny Chen157b9592011-02-18 21:13:05 +00008953{
Johnny Chene39f22d2011-02-19 01:36:13 +00008954 uint32_t reg_kind, reg_num;
8955 switch (num)
Johnny Chen157b9592011-02-18 21:13:05 +00008956 {
Johnny Chene39f22d2011-02-19 01:36:13 +00008957 case SP_REG:
8958 reg_kind = eRegisterKindGeneric;
8959 reg_num = LLDB_REGNUM_GENERIC_SP;
8960 break;
8961 case LR_REG:
8962 reg_kind = eRegisterKindGeneric;
8963 reg_num = LLDB_REGNUM_GENERIC_RA;
8964 break;
8965 case PC_REG:
8966 reg_kind = eRegisterKindGeneric;
8967 reg_num = LLDB_REGNUM_GENERIC_PC;
8968 break;
8969 default:
8970 if (0 <= num && num < SP_REG)
8971 {
8972 reg_kind = eRegisterKindDWARF;
8973 reg_num = dwarf_r0 + num;
8974 }
Johnny Chen157b9592011-02-18 21:13:05 +00008975 else
Johnny Chene39f22d2011-02-19 01:36:13 +00008976 {
8977 assert(0 && "Invalid register number");
8978 *success = false;
8979 return ~0u;
8980 }
8981 break;
Johnny Chen157b9592011-02-18 21:13:05 +00008982 }
Johnny Chene39f22d2011-02-19 01:36:13 +00008983
8984 // Read our register.
8985 uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
8986
8987 // When executing an ARM instruction , PC reads as the address of the current
8988 // instruction plus 8.
8989 // When executing a Thumb instruction , PC reads as the address of the current
8990 // instruction plus 4.
8991 if (num == 15)
8992 {
8993 if (CurrentInstrSet() == eModeARM)
8994 val += 8;
8995 else
8996 val += 4;
8997 }
Johnny Chen157b9592011-02-18 21:13:05 +00008998
8999 return val;
9000}
9001
Johnny Chenca67d1c2011-02-17 01:35:27 +00009002// Write the result to the ARM core register Rd, and optionally update the
9003// condition flags based on the result.
9004//
9005// This helper method tries to encapsulate the following pseudocode from the
9006// ARM Architecture Reference Manual:
9007//
9008// if d == 15 then // Can only occur for encoding A1
9009// ALUWritePC(result); // setflags is always FALSE here
9010// else
9011// R[d] = result;
9012// if setflags then
9013// APSR.N = result<31>;
9014// APSR.Z = IsZeroBit(result);
9015// APSR.C = carry;
9016// // APSR.V unchanged
9017//
9018// In the above case, the API client does not pass in the overflow arg, which
9019// defaults to ~0u.
9020bool
Johnny Chen10530c22011-02-17 22:37:12 +00009021EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
9022 const uint32_t result,
9023 const uint32_t Rd,
9024 bool setflags,
9025 const uint32_t carry,
9026 const uint32_t overflow)
Johnny Chenca67d1c2011-02-17 01:35:27 +00009027{
9028 if (Rd == 15)
9029 {
9030 if (!ALUWritePC (context, result))
9031 return false;
9032 }
9033 else
9034 {
Johnny Chena695f952011-02-23 21:24:25 +00009035 uint32_t reg_kind, reg_num;
9036 switch (Rd)
9037 {
9038 case SP_REG:
9039 reg_kind = eRegisterKindGeneric;
9040 reg_num = LLDB_REGNUM_GENERIC_SP;
9041 break;
9042 case LR_REG:
9043 reg_kind = eRegisterKindGeneric;
9044 reg_num = LLDB_REGNUM_GENERIC_RA;
9045 break;
9046 default:
9047 reg_kind = eRegisterKindDWARF;
9048 reg_num = dwarf_r0 + Rd;
9049 }
9050 if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
Johnny Chenca67d1c2011-02-17 01:35:27 +00009051 return false;
9052 if (setflags)
Johnny Chen10530c22011-02-17 22:37:12 +00009053 return WriteFlags (context, result, carry, overflow);
9054 }
9055 return true;
9056}
9057
9058// This helper method tries to encapsulate the following pseudocode from the
9059// ARM Architecture Reference Manual:
9060//
9061// APSR.N = result<31>;
9062// APSR.Z = IsZeroBit(result);
9063// APSR.C = carry;
9064// APSR.V = overflow
9065//
9066// Default arguments can be specified for carry and overflow parameters, which means
9067// not to update the respective flags.
9068bool
9069EmulateInstructionARM::WriteFlags (Context &context,
9070 const uint32_t result,
9071 const uint32_t carry,
9072 const uint32_t overflow)
9073{
9074 m_new_inst_cpsr = m_inst_cpsr;
Johnny Chen24348842011-02-23 00:15:56 +00009075 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
9076 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
Johnny Chen10530c22011-02-17 22:37:12 +00009077 if (carry != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00009078 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
Johnny Chen10530c22011-02-17 22:37:12 +00009079 if (overflow != ~0u)
Johnny Chen24348842011-02-23 00:15:56 +00009080 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
Johnny Chen10530c22011-02-17 22:37:12 +00009081 if (m_new_inst_cpsr != m_inst_cpsr)
9082 {
9083 if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
9084 return false;
Johnny Chenca67d1c2011-02-17 01:35:27 +00009085 }
9086 return true;
9087}
9088
Greg Clayton64c84432011-01-21 22:02:52 +00009089bool
9090EmulateInstructionARM::EvaluateInstruction ()
9091{
Johnny Chenc315f862011-02-05 00:46:10 +00009092 // Advance the ITSTATE bits to their values for the next instruction.
9093 if (m_inst_mode == eModeThumb && m_it_session.InITBlock())
9094 m_it_session.ITAdvance();
9095
Greg Clayton64c84432011-01-21 22:02:52 +00009096 return false;
9097}